agentworkshop 0.7.64 → 0.7.66

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/_nuxt/{DAfWhONg.js → 1NcBJMyL.js} +3 -3
  3. package/.output/public/_nuxt/{CKE_kTL92.js → Bb4REys92.js} +1 -1
  4. package/.output/public/_nuxt/{CVUMEGa1.js → Bnf04goH.js} +1 -1
  5. package/.output/public/_nuxt/{Cuw2--X2.js → CJPIo2E7.js} +1 -1
  6. package/.output/public/_nuxt/{CkYk8bj02.js → Cfy5Jn8v2.js} +1 -1
  7. package/.output/public/_nuxt/{DSWuWYx_2.js → DBERjwK92.js} +1 -1
  8. package/.output/public/_nuxt/DG0esyZR.js +1 -0
  9. package/.output/public/_nuxt/{B5RD2ZST.js → DPP0W5Ni.js} +1 -1
  10. package/.output/public/_nuxt/{DqT2_Jtw2.js → DxJFBokW2.js} +1 -1
  11. package/.output/public/_nuxt/{Cnf1PFhB2.js → GKiBVVYe2.js} +1 -1
  12. package/.output/public/_nuxt/{Dc5NeCDq.js → H13l21fR.js} +1 -1
  13. package/.output/public/_nuxt/{Cdw4juXw.js → XErFZOU9.js} +1 -1
  14. package/.output/public/_nuxt/builds/latest.json +1 -1
  15. package/.output/public/_nuxt/builds/meta/8bf65244-eb00-45c7-be23-9dcd7b917ef3.json +1 -0
  16. package/.output/public/_nuxt/{D-z6N1Cz.js → kYyvM13M.js} +1 -1
  17. package/.output/public/_nuxt/{B0w8DZ4C.js → t54AYjsC.js} +1 -1
  18. package/.output/server/chunks/_/nitro.mjs +1220 -904
  19. package/.output/server/chunks/_/nitro.mjs.map +1 -1
  20. package/.output/server/chunks/build/useWorkshopWs-CM-Ywk4h.mjs.map +1 -1
  21. package/.output/server/chunks/routes/renderer.mjs +1 -1
  22. package/.output/server/chunks/virtual/precomputed.mjs +1 -1
  23. package/.output/server/package.json +1 -1
  24. package/README-zh.md +8 -6
  25. package/README.md +7 -5
  26. package/app/stores/workshop/notifications.ts +22 -1
  27. package/config.yml +1 -1
  28. package/docs/cli.en.md +2 -2
  29. package/docs/cli.md +2 -2
  30. package/docs/full-test-plan.md +1 -1
  31. package/docs/plugins.en.md +1 -1
  32. package/docs/plugins.md +1 -1
  33. package/docs/sdk.en.md +1 -1
  34. package/docs/sdk.md +1 -1
  35. package/package.json +1 -1
  36. package/server/plugins-builtin/diag-bridge/client.mjs +230 -132
  37. package/server/plugins-builtin/diag-bridge/i18n.json +45 -15
  38. package/server/plugins-builtin/rag-bridge/client.mjs +182 -108
  39. package/server/plugins-builtin/rag-bridge/i18n.json +84 -60
  40. package/server/services/workshop/agents/host-tool-bridge/dispatch.ts +5 -0
  41. package/server/services/workshop/agents/industrial/aml-dataset-tools.ts +14 -0
  42. package/server/services/workshop/agents/industrial/dcw-judge-tools.ts +7 -2
  43. package/server/services/workshop/agents/industrial/dcw-tools.ts +5 -3
  44. package/server/services/workshop/agents/industrial/line-tools.ts +16 -3
  45. package/server/services/workshop/agents/industrial/optimization-tools.ts +10 -0
  46. package/server/services/workshop/agents/industrial/param-tools.ts +1 -84
  47. package/server/services/workshop/agents/industrial/tool-verify.ts +373 -0
  48. package/server/services/workshop/agents/industrial/twin-tools.ts +5 -0
  49. package/server/services/workshop/runtime/manager/channel-template-constants.ts +20 -0
  50. package/server/services/workshop/runtime/manager/channel-templates.ts +3 -12
  51. package/.output/public/_nuxt/DIDbAMv5.js +0 -1
  52. package/.output/public/_nuxt/builds/meta/1809e625-ff1d-4fd5-9ad2-28cea81f06ab.json +0 -1
@@ -1,132 +1,230 @@
1
- /**
2
- * diag-bridge 客户端面板 —— 注入 'plugins.page' 插槽。
3
- * 诊断记录表(runId/产线/状态/评分/入库/报告),30s 自动刷新,语言切换即重渲染;
4
- * 已完成诊断可点「报告」在线查看 report md 全文(经 /report 路由代理诊断服务)。
5
- */
6
- export function setup(ctx) {
7
- const styleId = 'aw-diag-styles'
8
- if (!document.getElementById(styleId)) {
9
- document.head.append(ctx.el('style', { id: styleId }, [`
10
- .aw-diag { display:flex; flex-direction:column; gap:8px; font-size:12px; }
11
- .aw-diag-toolbar { display:flex; justify-content:flex-end; }
12
- .aw-diag-btn { padding:4px 12px; border:1px solid color-mix(in srgb, currentColor 28%, transparent); border-radius:7px; background:transparent; color:inherit; cursor:pointer; }
13
- .aw-diag-btn:disabled { opacity:.45; cursor:default; }
14
- .aw-diag-table { width:100%; border-collapse:collapse; }
15
- .aw-diag-table th, .aw-diag-table td { text-align:left; padding:5px 8px; border-bottom:1px solid color-mix(in srgb, currentColor 10%, transparent); }
16
- .aw-diag-table th { opacity:.65; font-weight:500; }
17
- .aw-diag-st { display:inline-flex; align-items:center; gap:5px; }
18
- .aw-diag-dot { width:8px; height:8px; border-radius:50%; display:inline-block; }
19
- .aw-diag-dot-running { background:#41c8f4; }
20
- .aw-diag-dot-completed { background:#35e0a0; }
21
- .aw-diag-dot-failed, .aw-diag-dot-stopped { background:#e05a5a; }
22
- .aw-diag-empty { opacity:.6; padding:8px 0; }
23
- .aw-diag-modal { position:fixed; inset:0; z-index:9999; background:rgba(0,0,0,.55); display:flex; align-items:center; justify-content:center; }
24
- .aw-diag-modal-box { width:min(860px, 92vw); max-height:84vh; display:flex; flex-direction:column; gap:8px; background:var(--aw-bg, #101826); color:inherit; border:1px solid color-mix(in srgb, currentColor 22%, transparent); border-radius:12px; padding:14px 16px; }
25
- .aw-diag-modal-head { display:flex; align-items:center; justify-content:space-between; gap:12px; font-weight:600; }
26
- .aw-diag-report { flex:1; overflow:auto; white-space:pre-wrap; font-family:ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size:12px; line-height:1.6; }
27
- `]))
28
- }
29
-
30
- ctx.ui.registerPanel({
31
- slot: 'plugins.page',
32
- name: 'diag-runs',
33
- titleKey: 'panel.title',
34
- order: 20,
35
- mount(el) {
36
- const t = k => ctx.t(`panel.${k}`)
37
- const timer = setInterval(load, 30_000)
38
- const table = ctx.el('div', { class: 'aw-diag-table-wrap' })
39
- el.append(ctx.el('div', { class: 'aw-diag' }, [
40
- ctx.el('div', { class: 'aw-diag-toolbar' }, [
41
- ctx.el('button', { class: 'aw-diag-btn', onclick: () => void load() }, [t('refresh')]),
42
- ]),
43
- table,
44
- ]))
45
-
46
- const statusOf = (s) => {
47
- const key = ['running', 'completed', 'failed', 'stopped'].includes(s) ? s : 'other'
48
- return ctx.el('span', { class: 'aw-diag-st' }, [
49
- ctx.el('span', { class: `aw-diag-dot aw-diag-dot-${key}` }),
50
- t(`st_${key}`),
51
- ])
52
- }
53
-
54
- // 报告查看:拉 /report 路由,弹层渲染 report md 全文
55
- async function showReport(runId, btn) {
56
- const modal = ctx.el('div', { class: 'aw-diag-modal' }, [
57
- ctx.el('div', { class: 'aw-diag-modal-box' }, [
58
- ctx.el('div', { class: 'aw-diag-modal-head' }, [
59
- ctx.el('span', {}, [`${t('report')} · ${runId}`]),
60
- ctx.el('button', { class: 'aw-diag-btn', onclick: () => modal.remove() }, [t('close')]),
61
- ]),
62
- ctx.el('div', { class: 'aw-diag-report' }, [t('loading')]),
63
- ]),
64
- ])
65
- modal.addEventListener('click', (e) => {
66
- if (e.target === modal) modal.remove()
67
- })
68
- document.body.append(modal)
69
- const box = modal.querySelector('.aw-diag-report')
70
- try {
71
- const r = await ctx.fetch(`/api/plugins/diag-bridge/report?run_id=${encodeURIComponent(runId)}`)
72
- if (!r?.success) throw new Error(r?.error || `HTTP error(${runId})`)
73
- const rep = r.report ?? {}
74
- box.textContent = typeof rep === 'string' ? rep : String(rep.content ?? JSON.stringify(rep, null, 2))
75
- }
76
- catch (err) {
77
- box.textContent = `${t('report_fail')}: ${err?.message ?? err}`
78
- }
79
- finally {
80
- if (btn) btn.disabled = false
81
- }
82
- }
83
-
84
- async function load() {
85
- const r = await ctx.fetch('/api/plugins/diag-bridge/runs').catch(() => null)
86
- const runs = Array.isArray(r?.runs) ? r.runs.slice(0, 8) : []
87
- if (!runs.length) {
88
- table.replaceChildren(ctx.el('div', { class: 'aw-diag-empty' }, [t('none')]))
89
- return
90
- }
91
- const thead = ctx.el('tr', {}, [
92
- ctx.el('th', {}, [t('run')]),
93
- ctx.el('th', {}, [t('line')]),
94
- ctx.el('th', {}, [t('status')]),
95
- ctx.el('th', {}, [t('score')]),
96
- ctx.el('th', {}, [t('stored')]),
97
- ctx.el('th', {}, [t('report')]),
98
- ])
99
- const tbody = ctx.el('tbody')
100
- for (const run of runs) {
101
- const isDone = String(run.status ?? '') === 'completed'
102
- const btn = isDone
103
- ? ctx.el('button', {
104
- class: 'aw-diag-btn',
105
- onclick: () => {
106
- btn.disabled = true
107
- void showReport(String(run.runId), btn)
108
- },
109
- }, [t('view')])
110
- : ctx.el('span', { style: 'opacity:.4' }, ['-'])
111
- tbody.append(ctx.el('tr', {}, [
112
- ctx.el('td', { class: 'aw-mono' }, [String(run.runId ?? '-')]),
113
- ctx.el('td', {}, [String(run.line ?? '-')]),
114
- ctx.el('td', {}, [statusOf(String(run.status ?? ''))]),
115
- ctx.el('td', {}, [run.score != null ? String(run.score) : '-']),
116
- ctx.el('td', {}, [run.stored === true ? t('yes') : t('no')]),
117
- ctx.el('td', {}, [btn]),
118
- ]))
119
- }
120
- table.replaceChildren(ctx.el('table', { class: 'aw-diag-table' }, [ctx.el('thead', {}, [thead]), tbody]))
121
- }
122
-
123
- void load()
124
- // 语言切换 → 重渲染(标题由插槽响应式解析,表格文案在此重取)
125
- const offLocale = ctx.hooks.on('i18n:changed', () => void load())
126
- return () => {
127
- clearInterval(timer)
128
- offLocale()
129
- }
130
- },
131
- })
132
- }
1
+ /**
2
+ * diag-bridge 客户端面板 —— 注入 'plugins.page' 插槽。
3
+ * 连接检测(调 /health,含用户配置 token 的实测三态,结构化渲染) +
4
+ * 诊断记录表(runId/产线/状态/评分/入库/报告),30s 自动刷新,语言切换即重渲染;
5
+ * 已完成诊断可点「报告」在线查看 report md 全文(经 /report 路由代理诊断服务)。
6
+ */
7
+ export function setup(ctx) {
8
+ const styleId = 'aw-diag-styles'
9
+ if (!document.getElementById(styleId)) {
10
+ document.head.append(ctx.el('style', { id: styleId }, [`
11
+ .aw-diag { display:flex; flex-direction:column; gap:8px; font-size:12px; }
12
+ .aw-diag-toolbar { display:flex; justify-content:flex-end; }
13
+ .aw-diag-btn { padding:4px 12px; border:1px solid color-mix(in srgb, currentColor 28%, transparent); border-radius:7px; background:transparent; color:inherit; cursor:pointer; }
14
+ .aw-diag-btn:disabled { opacity:.45; cursor:default; }
15
+ .aw-diag-table { width:100%; border-collapse:collapse; }
16
+ .aw-diag-table th, .aw-diag-table td { text-align:left; padding:5px 8px; border-bottom:1px solid color-mix(in srgb, currentColor 10%, transparent); }
17
+ .aw-diag-table th { opacity:.65; font-weight:500; }
18
+ .aw-diag-st { display:inline-flex; align-items:center; gap:5px; }
19
+ .aw-diag-dot { width:8px; height:8px; border-radius:50%; display:inline-block; }
20
+ .aw-diag-dot-running { background:#41c8f4; }
21
+ .aw-diag-dot-completed { background:#35e0a0; }
22
+ .aw-diag-dot-failed, .aw-diag-dot-stopped { background:#e05a5a; }
23
+ .aw-diag-dot-na { background:#9aa4ad; }
24
+ .aw-diag-empty { opacity:.6; padding:8px 0; }
25
+ .aw-diag-status { display:flex; gap:12px; align-items:center; flex-wrap:wrap; }
26
+ .aw-diag-check { padding:8px 10px; border:1px dashed color-mix(in srgb, currentColor 20%, transparent); border-radius:8px; display:flex; flex-direction:column; gap:5px; }
27
+ .aw-diag-check-rows { display:flex; flex-direction:column; gap:3px; }
28
+ .aw-diag-check-row { display:flex; gap:6px; align-items:baseline; flex-wrap:wrap; }
29
+ .aw-diag-check-k { opacity:.65; min-width:86px; }
30
+ .aw-diag-check-err { color:#e05a5a; }
31
+ .aw-diag-check-ok { color:#35e0a0; }
32
+ .aw-diag-modal { position:fixed; inset:0; z-index:9999; background:rgba(0,0,0,.55); display:flex; align-items:center; justify-content:center; }
33
+ .aw-diag-modal-box { width:min(860px, 92vw); max-height:84vh; display:flex; flex-direction:column; gap:8px; background:var(--aw-bg, #101826); color:inherit; border:1px solid color-mix(in srgb, currentColor 22%, transparent); border-radius:12px; padding:14px 16px; }
34
+ .aw-diag-modal-head { display:flex; align-items:center; justify-content:space-between; gap:12px; font-weight:600; }
35
+ .aw-diag-report { flex:1; overflow:auto; white-space:pre-wrap; font-family:ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size:12px; line-height:1.6; }
36
+ `]))
37
+ }
38
+
39
+ ctx.ui.registerPanel({
40
+ slot: 'plugins.page',
41
+ name: 'diag-runs',
42
+ titleKey: 'panel.title',
43
+ order: 20,
44
+ mount(el) {
45
+ const t = k => ctx.t(`panel.${k}`)
46
+ const timer = setInterval(() => { void load(); void refreshStatus() }, 30_000)
47
+ const table = ctx.el('div', { class: 'aw-diag-table-wrap' })
48
+
49
+ function dot(ok, na = false) {
50
+ return ctx.el('span', {
51
+ class: `aw-diag-dot ${na ? 'aw-diag-dot-na' : ok ? 'aw-diag-dot-completed' : 'aw-diag-dot-failed'}`,
52
+ title: na ? t('tokenUnknown') : ok ? t('ok') : t('bad'),
53
+ })
54
+ }
55
+
56
+ // ---- 连接状态行(30s 轮询) + 「检测连接」显式检测(宿主后端会拿用户配置的 token 实测受保护端点) ----
57
+ const remoteCell = ctx.el('span', { class: 'aw-diag-st' }, [dot(false), ` ${t('remote')}: -`])
58
+ const tokenCell = ctx.el('span', { class: 'aw-diag-st' }, [dot(false, true), ` ${t('tokenCfg')}: -`])
59
+ const engineCell = ctx.el('span', { class: 'aw-diag-st faint' }, [` ${t('engine')}: -`])
60
+ const statusRow = ctx.el('div', { class: 'aw-diag-status' }, [remoteCell, tokenCell, engineCell])
61
+
62
+ const checkBtn = ctx.el('button', { class: 'aw-diag-btn' }, [t('checkBtn')])
63
+ const checkRows = ctx.el('div', { class: 'aw-diag-check-rows' })
64
+ const checkBox = ctx.el('div', { class: 'aw-diag-check' }, [checkRows])
65
+ checkBtn.addEventListener('click', () => void runCheck())
66
+
67
+ /** 检测明细行:true 绿 / false 红 / null 灰 */
68
+ function checkRow(label, okState, value) {
69
+ const val = ctx.el('span')
70
+ for (const seg of (Array.isArray(value) ? value : [{ text: String(value) }])) {
71
+ val.append(ctx.el('span', { class: seg.cls ?? '' }, [String(seg.text)]))
72
+ }
73
+ return ctx.el('div', { class: 'aw-diag-check-row' }, [
74
+ ctx.el('span', { class: 'aw-diag-check-k' }, [label]),
75
+ dot(okState === true, okState == null),
76
+ val,
77
+ ])
78
+ }
79
+
80
+ /** token 三态文案 */
81
+ const tokenText = (tk) => !tk?.configured
82
+ ? t('tokenNone')
83
+ : tk?.accepted === true ? t('tokenAccepted') : tk?.accepted === false ? t('tokenRejected') : t('tokenUnknown')
84
+
85
+ async function runCheck() {
86
+ checkBtn.disabled = true
87
+ checkBtn.textContent = t('checking')
88
+ const t0 = Date.now()
89
+ const h = await ctx.fetch('/api/plugins/diag-bridge/health').catch(() => null)
90
+ const ms = Date.now() - t0
91
+ const rows = []
92
+ if (!h) {
93
+ rows.push(checkRow(t('checkBtn'), false, [{ text: t('checkFail'), cls: 'aw-diag-check-err' }]))
94
+ }
95
+ else {
96
+ const remote = h?.remote ?? {}
97
+ const rOk = remote?.status === 'ok'
98
+ rows.push(checkRow(t('remote'), rOk, [
99
+ { text: `${h?.base ?? '-'} · ${remote?.status ?? '-'}`, cls: rOk ? '' : 'aw-diag-check-err' },
100
+ ...(remote?.auth ? [{ text: ` · auth=${remote.auth}`, cls: /被拒|401|403/.test(String(remote.auth)) ? 'aw-diag-check-err' : '' }] : []),
101
+ ...(remote?.error ? [{ text: ` · ${remote.error}`, cls: 'aw-diag-check-err' }] : []),
102
+ ]))
103
+ const tk = h?.token ?? {}
104
+ rows.push(checkRow(t('tokenCfg'), tk?.configured ? tk?.accepted : null,
105
+ [{ text: tokenText(tk), cls: tk?.accepted === false ? 'aw-diag-check-err' : '' },
106
+ ...(tk?.hint ? [{ text: ` · ${tk.hint}`, cls: 'aw-diag-check-err' }] : []),
107
+ ...(h?.auth ? [{ text: ` · ${h.auth === 'bearer' ? t('bearer') : t('anonymous')}` }] : [])]))
108
+ rows.push(checkRow(t('engine'), true, [{ text: String(h?.harness ?? '-') }]))
109
+ const by = h?.runs?.byStatus ?? {}
110
+ rows.push(checkRow(t('runs'), true, [{ text: `${h?.runs?.total ?? 0} (completed ${by.completed ?? 0} / running ${by.running ?? 0} / failed ${by.failed ?? 0})` }]))
111
+ const allOk = rOk && tk?.accepted !== false
112
+ rows.push(ctx.el('div', { class: 'aw-diag-check-row' }, [
113
+ ctx.el('span', { class: allOk ? 'aw-diag-check-ok' : 'aw-diag-check-err' },
114
+ [allOk ? `✔ ${t('allOk')}` : `✖ ${t('allBad')}`]),
115
+ ctx.el('span', { class: 'faint' }, [` · ${t('latency')} ${ms}ms`]),
116
+ ]))
117
+ }
118
+ checkRows.replaceChildren(...rows)
119
+ checkBtn.disabled = false
120
+ checkBtn.textContent = t('checkBtn')
121
+ }
122
+
123
+ async function refreshStatus() {
124
+ const h = await ctx.fetch('/api/plugins/diag-bridge/health').catch(() => null)
125
+ const remote = h?.remote ?? {}
126
+ const rOk = remote?.status === 'ok'
127
+ remoteCell.replaceChildren(dot(rOk), ` ${t('remote')}: ${remote?.status ?? '-'}${remote?.auth ? `(${remote.auth})` : ''}`)
128
+ const tk = h?.token ?? {}
129
+ tokenCell.replaceChildren(dot(tk?.configured ? tk?.accepted === true : false, !tk?.configured), ` ${t('tokenCfg')}: ${tokenText(tk)}`)
130
+ engineCell.replaceChildren(` ${t('engine')}: ${h?.harness ?? '-'}`)
131
+ }
132
+
133
+ el.append(ctx.el('div', { class: 'aw-diag' }, [
134
+ statusRow,
135
+ ctx.el('div', { class: 'aw-diag-toolbar' }, [
136
+ checkBtn,
137
+ ctx.el('button', { class: 'aw-diag-btn', onclick: () => void load() }, [t('refresh')]),
138
+ ]),
139
+ checkBox,
140
+ table,
141
+ ]))
142
+
143
+ const statusOf = (s) => {
144
+ const key = ['running', 'completed', 'failed', 'stopped'].includes(s) ? s : 'other'
145
+ return ctx.el('span', { class: 'aw-diag-st' }, [
146
+ ctx.el('span', { class: `aw-diag-dot aw-diag-dot-${key}` }),
147
+ t(`st_${key}`),
148
+ ])
149
+ }
150
+
151
+ // 报告查看:拉 /report 路由,弹层渲染 report md 全文
152
+ async function showReport(runId, btn) {
153
+ const modal = ctx.el('div', { class: 'aw-diag-modal' }, [
154
+ ctx.el('div', { class: 'aw-diag-modal-box' }, [
155
+ ctx.el('div', { class: 'aw-diag-modal-head' }, [
156
+ ctx.el('span', {}, [`${t('report')} · ${runId}`]),
157
+ ctx.el('button', { class: 'aw-diag-btn', onclick: () => modal.remove() }, [t('close')]),
158
+ ]),
159
+ ctx.el('div', { class: 'aw-diag-report' }, [t('loading')]),
160
+ ]),
161
+ ])
162
+ modal.addEventListener('click', (e) => {
163
+ if (e.target === modal) modal.remove()
164
+ })
165
+ document.body.append(modal)
166
+ const box = modal.querySelector('.aw-diag-report')
167
+ try {
168
+ const r = await ctx.fetch(`/api/plugins/diag-bridge/report?run_id=${encodeURIComponent(runId)}`)
169
+ if (!r?.success) throw new Error(r?.error || `HTTP error(${runId})`)
170
+ const rep = r.report ?? {}
171
+ box.textContent = typeof rep === 'string' ? rep : String(rep.content ?? JSON.stringify(rep, null, 2))
172
+ }
173
+ catch (err) {
174
+ box.textContent = `${t('report_fail')}: ${err?.message ?? err}`
175
+ }
176
+ finally {
177
+ if (btn) btn.disabled = false
178
+ }
179
+ }
180
+
181
+ async function load() {
182
+ const r = await ctx.fetch('/api/plugins/diag-bridge/runs').catch(() => null)
183
+ const runs = Array.isArray(r?.runs) ? r.runs.slice(0, 8) : []
184
+ if (!runs.length) {
185
+ table.replaceChildren(ctx.el('div', { class: 'aw-diag-empty' }, [t('none')]))
186
+ return
187
+ }
188
+ const thead = ctx.el('tr', {}, [
189
+ ctx.el('th', {}, [t('run')]),
190
+ ctx.el('th', {}, [t('line')]),
191
+ ctx.el('th', {}, [t('status')]),
192
+ ctx.el('th', {}, [t('score')]),
193
+ ctx.el('th', {}, [t('stored')]),
194
+ ctx.el('th', {}, [t('report')]),
195
+ ])
196
+ const tbody = ctx.el('tbody')
197
+ for (const run of runs) {
198
+ const isDone = String(run.status ?? '') === 'completed'
199
+ const btn = isDone
200
+ ? ctx.el('button', {
201
+ class: 'aw-diag-btn',
202
+ onclick: () => {
203
+ btn.disabled = true
204
+ void showReport(String(run.runId), btn)
205
+ },
206
+ }, [t('view')])
207
+ : ctx.el('span', { style: 'opacity:.4' }, ['-'])
208
+ tbody.append(ctx.el('tr', {}, [
209
+ ctx.el('td', { class: 'aw-mono' }, [String(run.runId ?? '-')]),
210
+ ctx.el('td', {}, [String(run.line ?? '-')]),
211
+ ctx.el('td', {}, [statusOf(String(run.status ?? ''))]),
212
+ ctx.el('td', {}, [run.score != null ? String(run.score) : '-']),
213
+ ctx.el('td', {}, [run.stored === true ? t('yes') : t('no')]),
214
+ ctx.el('td', {}, [btn]),
215
+ ]))
216
+ }
217
+ table.replaceChildren(ctx.el('table', { class: 'aw-diag-table' }, [ctx.el('thead', {}, [thead]), tbody]))
218
+ }
219
+
220
+ void load()
221
+ void refreshStatus()
222
+ // 语言切换 → 重渲染(标题由插槽响应式解析,表格文案在此重取)
223
+ const offLocale = ctx.hooks.on('i18n:changed', () => { void load(); void refreshStatus() })
224
+ return () => {
225
+ clearInterval(timer)
226
+ offLocale()
227
+ }
228
+ },
229
+ })
230
+ }
@@ -9,12 +9,6 @@
9
9
  "auto_enabled": "自动诊断",
10
10
  "auto_rules": "自动诊断规则"
11
11
  },
12
- "group": {
13
- "conn": "诊断服务连接",
14
- "run": "诊断执行参数",
15
- "auto": "自动诊断",
16
- "rules": "自动诊断规则"
17
- },
18
12
  "panel": {
19
13
  "title": "深度诊断(industrial-deep-diagnostic)",
20
14
  "runs": "诊断记录",
@@ -32,11 +26,32 @@
32
26
  "st_other": "其他",
33
27
  "yes": "是",
34
28
  "no": "否",
29
+ "remote": "诊断服务",
30
+ "engine": "诊断引擎",
31
+ "checkBtn": "检测连接",
32
+ "checking": "检测中…",
33
+ "checkFail": "检测请求失败(插件路由不可达)",
34
+ "tokenCfg": "API Token",
35
+ "tokenNone": "未配置(匿名)",
36
+ "tokenAccepted": "已配置并被服务接受",
37
+ "tokenRejected": "已配置但被拒绝(401/403)",
38
+ "tokenUnknown": "未知(网络不可达)",
39
+ "allOk": "连接正常:API 可达,token 有效",
40
+ "allBad": "连接异常:按上行明细排查",
41
+ "latency": "耗时",
42
+ "ok": "正常",
43
+ "bad": "不可达",
35
44
  "report": "报告",
36
45
  "view": "查看",
37
46
  "close": "关闭",
38
47
  "loading": "加载中…",
39
48
  "report_fail": "报告获取失败"
49
+ },
50
+ "group": {
51
+ "conn": "诊断服务连接",
52
+ "run": "诊断执行参数",
53
+ "auto": "自动诊断",
54
+ "rules": "自动诊断规则"
40
55
  }
41
56
  },
42
57
  "en": {
@@ -49,15 +64,9 @@
49
64
  "auto_enabled": "Auto diagnosis",
50
65
  "auto_rules": "Auto diagnosis rules"
51
66
  },
52
- "group": {
53
- "conn": "Diagnosis service connection",
54
- "run": "Diagnosis run parameters",
55
- "auto": "Auto diagnosis",
56
- "rules": "Auto diagnosis rules"
57
- },
58
67
  "panel": {
59
68
  "title": "Deep diagnosis (industrial-deep-diagnostic)",
60
- "runs": "Diagnosis runs",
69
+ "runs": "Runs",
61
70
  "none": "No runs yet; agents start one via the diag_run tool",
62
71
  "run": "Run",
63
72
  "line": "Line",
@@ -72,11 +81,32 @@
72
81
  "st_other": "Other",
73
82
  "yes": "Yes",
74
83
  "no": "No",
84
+ "remote": "Diag service",
85
+ "engine": "Harness",
86
+ "checkBtn": "Test connection",
87
+ "checking": "Checking…",
88
+ "checkFail": "Check request failed (plugin route unreachable)",
89
+ "tokenCfg": "API Token",
90
+ "tokenNone": "Not set (anonymous)",
91
+ "tokenAccepted": "Configured and accepted",
92
+ "tokenRejected": "Configured but rejected (401/403)",
93
+ "tokenUnknown": "Unknown (unreachable)",
94
+ "allOk": "Connection OK: API reachable, token valid",
95
+ "allBad": "Connection problem: see details above",
96
+ "latency": "Latency",
97
+ "ok": "Up",
98
+ "bad": "Down",
75
99
  "report": "Report",
76
100
  "view": "View",
77
101
  "close": "Close",
78
102
  "loading": "Loading…",
79
- "report_fail": "Failed to load report"
103
+ "report_fail": "Failed to fetch report"
104
+ },
105
+ "group": {
106
+ "conn": "Diagnosis service connection",
107
+ "run": "Diagnosis run parameters",
108
+ "auto": "Auto diagnosis",
109
+ "rules": "Auto diagnosis rules"
80
110
  }
81
111
  }
82
- }
112
+ }