- json/llm_call_trace_list.json: noedit只读列表;exclouded隐藏id/req_path/resp_path/org_id;
url/note加宽;kind/method内联枚举(含gen同步生成,此前草稿引用的get_llm_kind_options.dspy不存在);
删color_mapping(bricks全库0消费的死配置);toolbar查看IO+binds urlwidget→PopupWindow(85%)
url不带?id=${id}$——生成期ArgsConvert会eval成<built-in function id>垃圾串,
行数据id经_add_event_data自动并入params(dapi/llmage生产同款)
- api/llm_call_trace_io.dspy: 薄代理(get_user门禁+get_userorgid机构隔离)→env.llm_call_trace_io;
修草稿4处实锤bug:get_user未await/user.get当dict/sor块外使用/返回PopupWindow套娃
- init.py: llm_call_trace_io读表+同批次+llm_usage上下文(块内读全拷dict)→读文件
(trace.trace_root realpath前缀校验防穿越)→TabPanel三tab(摘要Html+pre escape防注入/
请求/响应CodeEditor readonly mode=null);单侧150K截断提示盘上路径;env注册
- api/llm_project_cost_query.dspy: 改{total,rows}契约接Tabular data_url(PageDataLoader);
wwwroot/llm_project_cost/index.ui: InlineForm(date_from/date_to/status)+Tabular;
script内getWidgetById起点bricks.app(弹窗DOM挂body下,app.root搜不到)
- card_popup.dspy: titles加llm_call_trace;新增page_targets白名单挂按项目费用页;
index.ui挂两张卡片(调用原文追踪/按项目费用)
- accounting.py: _maybe_cleanup_traces每日一次接cleanup_expired(trace.py铁律3
文档承诺worker每日调但循环没接,补齐);放抢锁前(清理幂等多进程同日无害)
- scripts/load_path.py: 注释说明/**通配已覆盖新页面(rbac check_roles_path前缀匹配)
- models/mysql.ddl/README/design-spec: 9张表同步(kind补gen枚举;3.9节;F19/F20)
- scripts/test_llm_call_trace_io.py: stub harness 22断言全过(隔离/穿越/转义/截断/每日门控)
- .gitignore: wwwroot/llm_call_trace/生成目录不入库
95 lines
4.0 KiB
Plaintext
95 lines
4.0 KiB
Plaintext
# card_popup.dspy — 模型治理功能卡片弹窗(2026-09-07 用户定夺:卡片点击一律弹窗处理,不在页面下方展示)
|
||
# 参数:target=白名单内的 CRUD 目录名;模型注册弹窗额外带「自动配置/上线检查」工具按钮
|
||
|
||
import json as _json
|
||
|
||
uid = await get_user()
|
||
if not uid:
|
||
return _json.dumps({
|
||
"widgettype": "PopupWindow",
|
||
"options": {"title": "提示", "cwidth": 30, "cheight": 8, "auto_open": True},
|
||
"subwidgets": [{"widgettype": "Text", "options": {"text": "请先登录", "padding": "20px"}}]
|
||
}, ensure_ascii=False)
|
||
|
||
target = ((params_kw or {}).get('target', '') or '').strip()
|
||
titles = {
|
||
'llm_vendor': '供应商与端点',
|
||
'llm_model': '模型注册',
|
||
'llm_api_profile': '适配模板',
|
||
'llm_org_policy': '组织容错策略',
|
||
'llm_org_quota': '组织限额限流',
|
||
'llm_user_quota': '个人限额限流',
|
||
'llm_usage': '用量流水',
|
||
'llm_call_trace': '调用原文追踪',
|
||
}
|
||
# 非 CRUD 的定制页面入口(页面路径白名单)
|
||
# llm_project_cost: 按项目费用统计页(2026-09-10,llm_project_cost_query 的展示页)
|
||
page_targets = {
|
||
'llm_project_cost': ('按项目费用', '/pipeline-llm/llm_project_cost/index.ui'),
|
||
}
|
||
if target not in titles and target not in page_targets:
|
||
return _json.dumps({
|
||
"widgettype": "PopupWindow",
|
||
"options": {"title": "提示", "cwidth": 40, "cheight": 10, "auto_open": True},
|
||
"subwidgets": [{"widgettype": "Text", "options": {
|
||
"text": "无效的功能入口:" + target, "padding": "20px"}}]
|
||
}, ensure_ascii=False)
|
||
|
||
if target in page_targets:
|
||
_page_title, _page_url = page_targets[target]
|
||
_page_resp = {
|
||
"widgettype": "PopupWindow",
|
||
"id": "llm_card_pw",
|
||
"options": {"title": _page_title, "width": "85%", "height": "85%", "auto_open": True},
|
||
"subwidgets": [{
|
||
"widgettype": "urlwidget",
|
||
"options": {"url": entire_url(_page_url)}}]
|
||
}
|
||
return _json.dumps(_page_resp, ensure_ascii=False)
|
||
|
||
subwidgets = []
|
||
if target == 'llm_model':
|
||
# 模型注册工具栏:自动配置(内部助手全链)+ 上线检查(真实调用测试+记账检查)
|
||
auto_url = entire_url('/pipeline-llm/api/auto_config_popup.dspy')
|
||
check_url = entire_url('/pipeline-llm/api/online_check_popup.dspy')
|
||
auto_script = (
|
||
"var old=bricks.getWidgetById('llm_auto_cfg_pw',bricks.app);"
|
||
"if(old&&old.destroy){old.destroy();}"
|
||
"var r=await fetch(" + _json.dumps(auto_url) + ");"
|
||
"var d=await r.json();if(d&&d.widgettype){bricks.widgetBuild(d,bricks.app);}")
|
||
check_script = (
|
||
"var old=bricks.getWidgetById('llm_online_chk_pw',bricks.app);"
|
||
"if(old&&old.destroy){old.destroy();}"
|
||
"var r=await fetch(" + _json.dumps(check_url) + ");"
|
||
"var d=await r.json();if(d&&d.widgettype){bricks.widgetBuild(d,bricks.app);}")
|
||
subwidgets.append({
|
||
"widgettype": "HBox",
|
||
"options": {"gap": "8px", "padding": "0 0 10px 0", "alignItems": "center"},
|
||
"subwidgets": [
|
||
{"widgettype": "Button",
|
||
"options": {"label": "🤖 自动配置", "css": "small"},
|
||
"binds": [{"wid": "self", "event": "click", "actiontype": "script",
|
||
"target": "self", "script": auto_script}]},
|
||
{"widgettype": "Button",
|
||
"options": {"label": "✅ 上线检查", "css": "small"},
|
||
"binds": [{"wid": "self", "event": "click", "actiontype": "script",
|
||
"target": "self", "script": check_script}]},
|
||
{"widgettype": "Text",
|
||
"options": {"text": "自动配置:粘贴 API/定价文档链接或正文,内部助手全链完成并汇报模型状态;上线检查:选择模型后真实调用测试+记账检查",
|
||
"cfontsize": 0.85, "color": "#94a3b8", "halign": "left"}},
|
||
]})
|
||
subwidgets.append({
|
||
"widgettype": "urlwidget",
|
||
"options": {"url": entire_url('/pipeline-llm/' + target)}})
|
||
|
||
resp = {
|
||
"widgettype": "PopupWindow",
|
||
"id": "llm_card_pw",
|
||
"options": {"title": titles[target], "width": "85%", "height": "85%", "auto_open": True},
|
||
"subwidgets": [{
|
||
"widgettype": "VBox",
|
||
"options": {"css": "filler", "width": "100%", "height": "100%", "padding": "12px"},
|
||
"subwidgets": subwidgets}]
|
||
}
|
||
return _json.dumps(resp, ensure_ascii=False)
|