agentworkshop 0.7.38 → 0.7.39
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.
- package/.AgentWorkShop/prompts/aml-mission-default.md +20 -20
- package/.AgentWorkShop/prompts/aml-playbook.md +49 -49
- package/.AgentWorkShop/prompts/host-tools.json +1238 -1238
- package/.AgentWorkShop/prompts/peer-reply-cross-channel.md +10 -10
- package/.output/.AgentWorkShop/prompts/aml-mission-default.md +20 -20
- package/.output/.AgentWorkShop/prompts/aml-playbook.md +49 -49
- package/.output/.AgentWorkShop/prompts/host-tools.json +1238 -1238
- package/.output/.AgentWorkShop/prompts/peer-reply-cross-channel.md +10 -10
- package/.output/nitro.json +1 -1
- package/.output/public/_nuxt/{BG8sCcwx.js → CUDwzgLV.js} +4 -4
- package/.output/public/_nuxt/CmsOtOAA2.js +1 -0
- package/.output/public/_nuxt/builds/latest.json +1 -1
- package/.output/public/_nuxt/builds/meta/4457d63f-0866-4cea-b320-04a321f24795.json +1 -0
- package/.output/public/_nuxt/default.BXI_fZUi.css +1 -0
- package/.output/server/chunks/_/nitro.mjs +706 -706
- package/.output/server/chunks/build/{default-hseyOqBT.mjs → default-CZmZFpqH.mjs} +27 -42
- package/.output/server/chunks/build/{default-hseyOqBT.mjs.map → default-CZmZFpqH.mjs.map} +1 -1
- package/.output/server/chunks/routes/renderer.mjs +1 -1
- package/.output/server/chunks/virtual/entry.mjs +3 -1
- package/.output/server/chunks/virtual/precomputed.mjs +1 -1
- package/.output/server/package.json +1 -1
- package/README-zh.md +6 -6
- package/README.md +6 -6
- package/app/components/AppHeader.vue +0 -17
- package/app/components/AppSidebar.vue +1 -0
- package/docs/full-test-plan.md +4 -0
- package/docs/plugins.en.md +1 -0
- package/docs/plugins.md +1 -0
- package/i18n/locales/en.ts +1 -0
- package/i18n/locales/zh-CN.ts +1 -0
- package/package.json +1 -1
- package/scripts/_audit/detached-start.mjs +103 -0
- package/scripts/_audit/guard-upstream-liveness.mjs +104 -0
- package/scripts/_dbg-perms-e2e.mjs +10 -3
- package/scripts/_dbg-protocol-matrix.mjs +453 -441
- package/scripts/_dbg-render-regression.mjs +151 -130
- package/scripts/_dbg-town-agents-probe.mjs +60 -0
- package/scripts/_dbg-visual-acceptance.mjs +63 -0
- package/scripts/e2e-agent-team.mjs +5 -3
- package/scripts/three-system-e2e.mjs +6 -6
- package/server/plugins-builtin/rag-bridge/index.mjs +9 -2
- package/.output/public/_nuxt/DVsjtsvZ2.js +0 -1
- package/.output/public/_nuxt/builds/meta/44b66249-54d0-4c8a-9057-9755a32329e2.json +0 -1
- package/.output/public/_nuxt/default.DE_vT238.css +0 -1
|
@@ -1,130 +1,151 @@
|
|
|
1
|
-
/** 渲染优化功能回归:/daq 行渲染与交互、/daq/[id] 详情、/town 场景与模型预览、全局 smoke。
|
|
2
|
-
* 用法:node scripts/_dbg-render-regression.mjs [base] [email] [pass] */
|
|
3
|
-
import puppeteer from 'puppeteer-core'
|
|
4
|
-
import { writeFileSync } from 'node:fs'
|
|
5
|
-
|
|
6
|
-
const ROOT = process.argv[2] ?? 'http://127.0.0.1:3001'
|
|
7
|
-
const EMAIL = process.argv[3] ?? 'perf-runner@awshop.io'
|
|
8
|
-
const PASS = process.argv[4] ?? 'Perf@Run2026'
|
|
9
|
-
const sleep = ms => new Promise(r => setTimeout(r, ms))
|
|
10
|
-
const results = []
|
|
11
|
-
const ok = (name, pass, detail = '') => {
|
|
12
|
-
results.push({ name, pass, detail })
|
|
13
|
-
console.log(`${pass ? '✔' : '✖'} ${name}${detail ? ' —— ' + detail : ''}`)
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const login = await fetch(`${ROOT}/api/users/login`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ email: EMAIL, password: PASS }) }).then(r => r.json())
|
|
17
|
-
if (!login?.data?.token) { console.error('LOGIN FAIL'); process.exit(1) }
|
|
18
|
-
const browser = await puppeteer.launch({ executablePath: 'C:/Program Files/Google/Chrome/Application/chrome.exe', headless: 'new', args: ['--no-sandbox', '--disable-gpu', '--window-size=1600,1000'] })
|
|
19
|
-
const page = await browser.newPage()
|
|
20
|
-
await page.setViewport({ width: 1600, height: 1000, deviceScaleFactor: 1 })
|
|
21
|
-
await page.setCookie({ name: 'token', value: login.data.token, domain: new URL(ROOT).hostname, path: '/' })
|
|
22
|
-
const pageErrors = []
|
|
23
|
-
page.on('pageerror', e => pageErrors.push(String(e).slice(0, 200)))
|
|
24
|
-
|
|
25
|
-
//
|
|
26
|
-
|
|
27
|
-
await
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
ok('/daq
|
|
45
|
-
ok('/daq
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
await
|
|
68
|
-
await
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
await page.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
1
|
+
/** 渲染优化功能回归:/daq 行渲染与交互、/daq/[id] 详情、/town 场景与模型预览、全局 smoke。
|
|
2
|
+
* 用法:node scripts/_dbg-render-regression.mjs [base] [email] [pass] */
|
|
3
|
+
import puppeteer from 'puppeteer-core'
|
|
4
|
+
import { writeFileSync } from 'node:fs'
|
|
5
|
+
|
|
6
|
+
const ROOT = process.argv[2] ?? 'http://127.0.0.1:3001'
|
|
7
|
+
const EMAIL = process.argv[3] ?? 'perf-runner@awshop.io'
|
|
8
|
+
const PASS = process.argv[4] ?? 'Perf@Run2026'
|
|
9
|
+
const sleep = ms => new Promise(r => setTimeout(r, ms))
|
|
10
|
+
const results = []
|
|
11
|
+
const ok = (name, pass, detail = '') => {
|
|
12
|
+
results.push({ name, pass, detail })
|
|
13
|
+
console.log(`${pass ? '✔' : '✖'} ${name}${detail ? ' —— ' + detail : ''}`)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const login = await fetch(`${ROOT}/api/users/login`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ email: EMAIL, password: PASS }) }).then(r => r.json())
|
|
17
|
+
if (!login?.data?.token) { console.error('LOGIN FAIL'); process.exit(1) }
|
|
18
|
+
const browser = await puppeteer.launch({ executablePath: 'C:/Program Files/Google/Chrome/Application/chrome.exe', headless: 'new', args: ['--no-sandbox', '--disable-gpu', '--window-size=1600,1000'] })
|
|
19
|
+
const page = await browser.newPage()
|
|
20
|
+
await page.setViewport({ width: 1600, height: 1000, deviceScaleFactor: 1 })
|
|
21
|
+
await page.setCookie({ name: 'token', value: login.data.token, domain: new URL(ROOT).hostname, path: '/' })
|
|
22
|
+
const pageErrors = []
|
|
23
|
+
page.on('pageerror', e => pageErrors.push(String(e).slice(0, 200)))
|
|
24
|
+
|
|
25
|
+
// 动态基线:节点数从 API 取(共享实例会增长,硬编码计数必然漂移)
|
|
26
|
+
const AUTH = { authorization: `Bearer ${login.data.token}` }
|
|
27
|
+
const daqCount = (await fetch(`${ROOT}/api/workshop/daq`, { headers: AUTH }).then(r => r.json())).data?.nodes?.length ?? 0
|
|
28
|
+
ok('/daq 基线计数(daq API)', daqCount > 0, `nodes=${daqCount}`)
|
|
29
|
+
|
|
30
|
+
// ---------- 1. /daq 行渲染完整性 ----------
|
|
31
|
+
await page.goto(`${ROOT}/daq`, { waitUntil: 'domcontentloaded', timeout: 60000 })
|
|
32
|
+
await sleep(12000)
|
|
33
|
+
const daqStruct = await page.evaluate(() => {
|
|
34
|
+
const rows = document.querySelectorAll('.nodes-table tbody tr')
|
|
35
|
+
const polylines = document.querySelectorAll('.nodes-table svg polyline')
|
|
36
|
+
const limLines = document.querySelectorAll('.nodes-table svg line.lim')
|
|
37
|
+
const pills = document.querySelectorAll('.nodes-table .st-pill')
|
|
38
|
+
const valCells = [...document.querySelectorAll('.nodes-table .val')].slice(0, 5).map(c => c.textContent.trim())
|
|
39
|
+
const toggles = document.querySelectorAll('.nodes-table .node-toggle')
|
|
40
|
+
const links = document.querySelectorAll('.nodes-table .console-link')
|
|
41
|
+
const lineSelects = document.querySelectorAll('.nodes-table .line-sel:not(.dev-add)')
|
|
42
|
+
return { rows: rows.length, polylines: polylines.length, limLines: limLines.length, pills: pills.length, valCells, toggles: toggles.length, links: links.length, lineSelects: lineSelects.length }
|
|
43
|
+
})
|
|
44
|
+
ok('/daq 行数=API 节点数', daqStruct.rows === daqCount, `rows=${daqStruct.rows} expect=${daqCount}`)
|
|
45
|
+
ok('/daq 趋势折线有渲染(有数节点)', daqStruct.polylines >= Math.min(10, daqCount) && daqStruct.polylines <= daqCount, `polylines=${daqStruct.polylines}/${daqCount}`)
|
|
46
|
+
ok('/daq 状态 pill 齐全', daqStruct.pills >= daqCount, `pills=${daqStruct.pills}`)
|
|
47
|
+
ok('/daq 启停按钮齐全', daqStruct.toggles === daqCount, `toggles=${daqStruct.toggles}`)
|
|
48
|
+
ok('/daq 控制台链接齐全', daqStruct.links === daqCount, `links=${daqStruct.links}`)
|
|
49
|
+
ok('/daq 产线下拉齐全', daqStruct.lineSelects === daqCount, `selects=${daqStruct.lineSelects}`)
|
|
50
|
+
ok('/daq 值列有数据', daqStruct.valCells.some(v => /\d/.test(v)), daqStruct.valCells[0])
|
|
51
|
+
|
|
52
|
+
// ---------- 2. WS 实时收敛:值列随读数帧变化(优化后合批仍须驱动行更新) ----------
|
|
53
|
+
const valChanges = await page.evaluate(() => new Promise((resolve) => {
|
|
54
|
+
const cells = [...document.querySelectorAll('.nodes-table .val')]
|
|
55
|
+
const texts = cells.map(c => c.textContent.trim())
|
|
56
|
+
setTimeout(() => {
|
|
57
|
+
const now = cells.map(c => c.textContent.trim())
|
|
58
|
+
let changed = 0
|
|
59
|
+
for (let i = 0; i < texts.length; i++) if (now[i] !== texts[i]) changed++
|
|
60
|
+
resolve(changed)
|
|
61
|
+
}, 8000)
|
|
62
|
+
}))
|
|
63
|
+
ok('/daq WS 读数驱动行更新(8s 内 ≥5 行变化)', valChanges >= 5, `changedRows=${valChanges}`)
|
|
64
|
+
|
|
65
|
+
// ---------- 3. 筛选交互(行组件随筛选增减) ----------
|
|
66
|
+
await page.type('.nodes-search input, input[placeholder]', '压力', { delay: 30 }).catch(() => {})
|
|
67
|
+
await sleep(1500)
|
|
68
|
+
const searchFiltered = await page.evaluate(() => document.querySelectorAll('.nodes-table tbody tr').length)
|
|
69
|
+
ok('/daq 搜索筛选生效', searchFiltered > 0 && searchFiltered < daqCount, `rows=${searchFiltered}`)
|
|
70
|
+
await page.evaluate(() => { location.hash = '' })
|
|
71
|
+
// 清空搜索(全选删除)
|
|
72
|
+
await page.keyboard.down('Control'); await page.keyboard.press('a'); await page.keyboard.up('Control'); await page.keyboard.press('Backspace')
|
|
73
|
+
await sleep(1200)
|
|
74
|
+
const afterClear = await page.evaluate(() => document.querySelectorAll('.nodes-table tbody tr').length)
|
|
75
|
+
ok('/daq 清空搜索恢复全量', afterClear === daqCount, `rows=${afterClear} expect=${daqCount}`)
|
|
76
|
+
|
|
77
|
+
// ---------- 4. /daq/[id] 详情页(由行内控制台链接进入) ----------
|
|
78
|
+
const detailHref = await page.evaluate(() => document.querySelector('.nodes-table .console-link')?.getAttribute('href'))
|
|
79
|
+
await page.goto(`${ROOT}${detailHref}`, { waitUntil: 'domcontentloaded', timeout: 60000 })
|
|
80
|
+
await sleep(6000)
|
|
81
|
+
const detail = await page.evaluate(() => ({
|
|
82
|
+
bigVal: document.querySelector('.big-val')?.textContent?.trim() ?? '',
|
|
83
|
+
liveCanvas: !!document.querySelector('.live-canvas'),
|
|
84
|
+
histCanvas: !!document.querySelector('.hist-canvas'),
|
|
85
|
+
facts: document.querySelectorAll('.facts div').length,
|
|
86
|
+
}))
|
|
87
|
+
ok('/daq/[id] 大值卡渲染', /\d/.test(detail.bigVal), detail.bigVal.slice(0, 30))
|
|
88
|
+
ok('/daq/[id] live 趋势画布存在', detail.liveCanvas)
|
|
89
|
+
ok('/daq/[id] 历史画布存在', detail.histCanvas)
|
|
90
|
+
ok('/daq/[id] 参数事实表渲染', detail.facts >= 5, `facts=${detail.facts}`)
|
|
91
|
+
|
|
92
|
+
// ---------- 5. /town 场景 + 仪表化 + 模型预览 ----------
|
|
93
|
+
// 夹具自愈:hydrate 只呈现「已放置」频道 —— 共享实例的布局/挂载清单随各轮测试漂移,
|
|
94
|
+
// 零交集时 agents=0 是数据态而非代码回归;故断言前确保第一个挂载频道已被放置。
|
|
95
|
+
{
|
|
96
|
+
const wsList = (await fetch(`${ROOT}/api/workshop/workspaces`, { headers: AUTH }).then(r => r.json())).data ?? []
|
|
97
|
+
const firstCid = wsList.flatMap(w => w.channelIds ?? [])[0]
|
|
98
|
+
const layoutsRes = await fetch(`${ROOT}/api/workshop/scene/layouts`, { headers: AUTH }).then(r => r.json())
|
|
99
|
+
const laidIds = new Set((layoutsRes.data?.layouts ?? []).map(l => l.channelId))
|
|
100
|
+
if (firstCid && !laidIds.has(firstCid)) {
|
|
101
|
+
const put = await fetch(`${ROOT}/api/workshop/scene/layouts/${firstCid}`, {
|
|
102
|
+
method: 'PUT', headers: { ...AUTH, 'content-type': 'application/json' },
|
|
103
|
+
body: JSON.stringify({ x: 1150, z: 1500, radiusX: 320, radiusZ: 210, shape: 'ellipse' }),
|
|
104
|
+
}).then(r => r.json())
|
|
105
|
+
console.log(` [fixture] 放置频道 ${firstCid.slice(0, 8)} → ${put.code === 0 ? 'ok' : put.message}`)
|
|
106
|
+
await sleep(1000)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
await page.goto(`${ROOT}/town`, { waitUntil: 'domcontentloaded', timeout: 60000 })
|
|
110
|
+
await sleep(18000)
|
|
111
|
+
const town1 = await page.evaluate(() => ({
|
|
112
|
+
canvas: !!document.querySelector('#town-host canvas'),
|
|
113
|
+
stats: window.__townStats ? { ...window.__townStats } : null,
|
|
114
|
+
}))
|
|
115
|
+
ok('/town 3D 画布挂载', town1.canvas)
|
|
116
|
+
ok('/town 仪表化 __townStats 存在', !!town1.stats)
|
|
117
|
+
ok('/town 场景实体(Agent/设备)', !!town1.stats && town1.stats.agents >= 1 && town1.stats.devices >= 5, `agents=${town1.stats?.agents} devices=${town1.stats?.devices}`)
|
|
118
|
+
ok('/town 帧率 > 0(墙钟)', !!town1.stats && town1.stats.fps > 0, `fps=${town1.stats?.fps} rafHz=${town1.stats?.rafHz}`)
|
|
119
|
+
ok('/town 60fps 预算生效', !!town1.stats && town1.stats.frameBudgetMs === 16.67, `frameBudgetMs=${town1.stats?.frameBudgetMs}`)
|
|
120
|
+
const town2 = await page.evaluate(() => new Promise((resolve) => {
|
|
121
|
+
const s0 = JSON.stringify(window.__townStats)
|
|
122
|
+
setTimeout(() => resolve({ s0, s1: JSON.stringify(window.__townStats) }), 3000)
|
|
123
|
+
}))
|
|
124
|
+
ok('/town 仪表化持续更新', town2.s0 !== town2.s1)
|
|
125
|
+
|
|
126
|
+
// 打开模型库抽屉(若存在入口按钮)→ 预览卡渲染不崩
|
|
127
|
+
const libOpened = await page.evaluate(() => {
|
|
128
|
+
const btn = [...document.querySelectorAll('button, .hud-btn, [class*="lib"]')].find(b => /模型/.test(b.textContent ?? ''))
|
|
129
|
+
if (btn) { btn.click(); return true }
|
|
130
|
+
return false
|
|
131
|
+
})
|
|
132
|
+
if (libOpened) {
|
|
133
|
+
await sleep(4000)
|
|
134
|
+
const previews = await page.evaluate(() => document.querySelectorAll('.model-preview-3d canvas').length)
|
|
135
|
+
ok('/town 模型库打开且预览卡有画布', previews > 0, `previews=${previews}`)
|
|
136
|
+
}
|
|
137
|
+
await page.screenshot({ path: '.e2e-shots/regression-town.png' })
|
|
138
|
+
|
|
139
|
+
// ---------- 6. 全局页面 smoke(200 + 无 pageerror) ----------
|
|
140
|
+
for (const path of ['/workshop', '/dcw', '/logs', '/monitor', '/settings', '/users', '/permissions']) {
|
|
141
|
+
const resp = await page.goto(`${ROOT}${path}`, { waitUntil: 'domcontentloaded', timeout: 60000 }).then(r => r.status()).catch(() => 0)
|
|
142
|
+
await sleep(1500)
|
|
143
|
+
ok(`smoke ${path}`, resp === 200, `status=${resp}`)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
ok('全程无 pageerror', pageErrors.length === 0, pageErrors.slice(0, 3).join(' | '))
|
|
147
|
+
const failed = results.filter(r => !r.pass)
|
|
148
|
+
writeFileSync('.e2e-shots/render-regression.json', JSON.stringify({ at: new Date().toISOString(), base: ROOT, passed: results.length - failed.length, failed: failed.length, results }, null, 2))
|
|
149
|
+
console.log(`\n==== ${results.length - failed.length}/${results.length} PASS ====${failed.length ? ' FAILED: ' + failed.map(f => f.name).join(', ') : ''}`)
|
|
150
|
+
await browser.close()
|
|
151
|
+
process.exit(failed.length ? 1 : 0)
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/** 诊断探针:/town 场景 agents=0 之谜 —— 注入 WS 钩子记录 channel.snapshot,转储 __townStats。 */
|
|
2
|
+
import puppeteer from 'puppeteer-core'
|
|
3
|
+
|
|
4
|
+
const ROOT = process.argv[2] ?? 'http://127.0.0.1:3001'
|
|
5
|
+
const EMAIL = process.argv[3] ?? 'admin@awshop.local'
|
|
6
|
+
const PASS = process.argv[4] ?? 'admin123'
|
|
7
|
+
const sleep = ms => new Promise(r => setTimeout(r, ms))
|
|
8
|
+
|
|
9
|
+
const login = await fetch(`${ROOT}/api/users/login`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ email: EMAIL, password: PASS }) }).then(r => r.json())
|
|
10
|
+
if (!login?.data?.token) { console.error('LOGIN FAIL'); process.exit(1) }
|
|
11
|
+
const browser = await puppeteer.launch({ executablePath: 'C:/Program Files/Google/Chrome/Application/chrome.exe', headless: 'new', args: ['--no-sandbox', '--disable-gpu', '--window-size=1600,1000'] })
|
|
12
|
+
const page = await browser.newPage()
|
|
13
|
+
await page.setViewport({ width: 1600, height: 1000, deviceScaleFactor: 1 })
|
|
14
|
+
await page.setCookie({ name: 'token', value: login.data.token, domain: new URL(ROOT).hostname, path: '/' })
|
|
15
|
+
await page.evaluateOnNewDocument(() => {
|
|
16
|
+
window.__wslog = []
|
|
17
|
+
const OrigWS = window.WebSocket
|
|
18
|
+
window.WebSocket = function (url, protocols) {
|
|
19
|
+
window.__wslog.push({ ev: 'open-req', url: String(url) })
|
|
20
|
+
const ws = protocols !== undefined ? new OrigWS(url, protocols) : new OrigWS(url)
|
|
21
|
+
ws.addEventListener('open', () => window.__wslog.push({ ev: 'open', url: String(url) }))
|
|
22
|
+
ws.addEventListener('close', (e) => window.__wslog.push({ ev: 'close', code: e.code, reason: e.reason }))
|
|
23
|
+
ws.addEventListener('error', () => window.__wslog.push({ ev: 'error', url: String(url) }))
|
|
24
|
+
ws.addEventListener('message', (ev) => {
|
|
25
|
+
const raw = typeof ev.data === 'string' ? ev.data : ''
|
|
26
|
+
let entry = { ev: 'msg', bytes: ev.data?.size ?? raw.length, kind: ev.data?.constructor?.name }
|
|
27
|
+
try {
|
|
28
|
+
const d = JSON.parse(raw)
|
|
29
|
+
entry.t = d?.type ?? d?.event ?? '?'
|
|
30
|
+
if (String(entry.t).includes('snapshot')) {
|
|
31
|
+
const ag = d?.data?.agents ?? d?.payload?.agents
|
|
32
|
+
entry.agents = Array.isArray(ag) ? ag.length : typeof ag
|
|
33
|
+
entry.channelId = d?.data?.channelId ?? d?.channelId
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch { entry.parse = 'fail' }
|
|
37
|
+
window.__wslog.push(entry)
|
|
38
|
+
})
|
|
39
|
+
const origSend = ws.send.bind(ws)
|
|
40
|
+
ws.send = (d) => { window.__wslog.push({ ev: 'send', head: String(d).slice(0, 120) }); return origSend(d) }
|
|
41
|
+
return ws
|
|
42
|
+
}
|
|
43
|
+
window.WebSocket.prototype = OrigWS.prototype
|
|
44
|
+
window.WebSocket.CONNECTING = OrigWS.CONNECTING
|
|
45
|
+
window.WebSocket.OPEN = OrigWS.OPEN
|
|
46
|
+
window.WebSocket.CLOSING = OrigWS.CLOSING
|
|
47
|
+
window.WebSocket.CLOSED = OrigWS.CLOSED
|
|
48
|
+
})
|
|
49
|
+
page.on('pageerror', e => console.log('PAGEERROR:', String(e).slice(0, 160)))
|
|
50
|
+
|
|
51
|
+
await page.goto(`${ROOT}/town`, { waitUntil: 'domcontentloaded', timeout: 60000 })
|
|
52
|
+
await sleep(15000)
|
|
53
|
+
const dump = await page.evaluate(() => ({
|
|
54
|
+
stats: window.__townStats ?? null,
|
|
55
|
+
wslog: (window.__wslog ?? []).slice(0, 30),
|
|
56
|
+
empty: !!document.querySelector('[data-hud="town-empty"]'),
|
|
57
|
+
loading: !!document.querySelector('[data-hud="town-loading"]'),
|
|
58
|
+
}))
|
|
59
|
+
console.log(JSON.stringify(dump, null, 1))
|
|
60
|
+
await browser.close()
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/** P7 目视验收截图:关键页面逐页截图到 .e2e-shots/p7-*.png,并汇总每页 console error。 */
|
|
2
|
+
import puppeteer from 'puppeteer-core'
|
|
3
|
+
import { mkdirSync } from 'node:fs'
|
|
4
|
+
|
|
5
|
+
const ROOT = process.argv[2] ?? 'http://127.0.0.1:3001'
|
|
6
|
+
const EMAIL = process.argv[3] ?? 'admin@awshop.local'
|
|
7
|
+
const PASS = process.argv[4] ?? 'admin123'
|
|
8
|
+
const OUT = '.e2e-shots'
|
|
9
|
+
mkdirSync(OUT, { recursive: true })
|
|
10
|
+
|
|
11
|
+
const login = await fetch(`${ROOT}/api/users/login`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ email: EMAIL, password: PASS }) }).then(r => r.json())
|
|
12
|
+
if (!login?.data?.token) { console.error('LOGIN FAIL'); process.exit(1) }
|
|
13
|
+
|
|
14
|
+
const browser = await puppeteer.launch({ executablePath: 'C:/Program Files/Google/Chrome/Application/chrome.exe', headless: 'new', args: ['--no-sandbox', '--disable-gpu', '--window-size=1600,1000'] })
|
|
15
|
+
const page = await browser.newPage()
|
|
16
|
+
await page.setViewport({ width: 1600, height: 1000, deviceScaleFactor: 1 })
|
|
17
|
+
await page.setCookie({ name: 'token', value: login.data.token, domain: new URL(ROOT).hostname, path: '/' })
|
|
18
|
+
|
|
19
|
+
const pages = [
|
|
20
|
+
['workshop', '/workshop', 9000],
|
|
21
|
+
['daq', '/daq', 12000],
|
|
22
|
+
['dcw', '/dcw', 9000],
|
|
23
|
+
['town', '/town', 20000],
|
|
24
|
+
['settings', '/settings', 9000],
|
|
25
|
+
['monitor', '/monitor', 9000],
|
|
26
|
+
['aml', '/aml', 9000],
|
|
27
|
+
['logs', '/logs', 9000],
|
|
28
|
+
['users', '/users', 9000],
|
|
29
|
+
]
|
|
30
|
+
const summary = []
|
|
31
|
+
for (const [name, path, wait] of pages) {
|
|
32
|
+
const errors = []
|
|
33
|
+
const onConsole = (m) => { if (m.type() === 'error') errors.push(m.text().slice(0, 120)) }
|
|
34
|
+
page.on('console', onConsole)
|
|
35
|
+
try {
|
|
36
|
+
await page.goto(`${ROOT}${path}`, { waitUntil: 'domcontentloaded', timeout: 60000 })
|
|
37
|
+
await new Promise(r => setTimeout(r, wait))
|
|
38
|
+
const file = `${OUT}/p7-${name}.png`
|
|
39
|
+
await page.screenshot({ path: file })
|
|
40
|
+
summary.push({ name, ok: true, errors })
|
|
41
|
+
console.log(`✓ ${name} → ${file}${errors.length ? ` (console errors: ${errors.length})` : ''}`)
|
|
42
|
+
} catch (e) {
|
|
43
|
+
summary.push({ name, ok: false, errors: [String(e).slice(0, 120)] })
|
|
44
|
+
console.log(`✖ ${name}: ${String(e).slice(0, 120)}`)
|
|
45
|
+
}
|
|
46
|
+
page.off('console', onConsole)
|
|
47
|
+
}
|
|
48
|
+
// daq 详情页(从列表第一个 console-link 进入)
|
|
49
|
+
try {
|
|
50
|
+
await page.goto(`${ROOT}/daq`, { waitUntil: 'domcontentloaded', timeout: 60000 })
|
|
51
|
+
await new Promise(r => setTimeout(r, 10000))
|
|
52
|
+
const href = await page.evaluate(() => document.querySelector('.nodes-table .console-link')?.getAttribute('href'))
|
|
53
|
+
if (href) {
|
|
54
|
+
await page.goto(`${ROOT}${href}`, { waitUntil: 'domcontentloaded', timeout: 60000 })
|
|
55
|
+
await new Promise(r => setTimeout(r, 8000))
|
|
56
|
+
await page.screenshot({ path: `${OUT}/p7-daq-detail.png` })
|
|
57
|
+
console.log(`✓ daq-detail → ${OUT}/p7-daq-detail.png`)
|
|
58
|
+
}
|
|
59
|
+
} catch (e) { console.log(`✖ daq-detail: ${String(e).slice(0, 100)}`) }
|
|
60
|
+
await browser.close()
|
|
61
|
+
const bad = summary.filter(s => !s.ok || s.errors.length)
|
|
62
|
+
console.log(`\n页面数=${summary.length} 有问题页=${bad.length}`)
|
|
63
|
+
for (const b of bad) console.log(' -', b.name, b.errors.slice(0, 2).join(' | '))
|
|
@@ -7,7 +7,9 @@
|
|
|
7
7
|
* 5. 成员移除 / team 更新 / 删除
|
|
8
8
|
* 运行: node scripts/e2e-agent-team.mjs [--base http://127.0.0.1:3000]
|
|
9
9
|
*/
|
|
10
|
-
const BASE = (process.argv.find(a => a.startsWith('--base='))?.slice(7) ?? 'http://127.0.0.1:3000') + '/api/workshop'
|
|
10
|
+
const BASE = (process.argv.find(a => a.startsWith('--base='))?.slice(7) ?? 'http://127.0.0.1:3000') + '/api/workshop'
|
|
11
|
+
// 注册走平台 origin 的 /api/users/register(不在 /api/workshop 下;注册现要求 email+password)
|
|
12
|
+
const ORIGIN = BASE.slice(0, BASE.indexOf('/api'))
|
|
11
13
|
|
|
12
14
|
let pass = 0
|
|
13
15
|
let fail = 0
|
|
@@ -21,9 +23,9 @@ function check(name, ok, detail = '') {
|
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
// 用户级隔离:注册测试用户;管理面 API 全程携带用户 token
|
|
24
|
-
const __user = await fetch(
|
|
26
|
+
const __user = await fetch(ORIGIN + '/api/users/register', {
|
|
25
27
|
method: 'POST', headers: { 'content-type': 'application/json' },
|
|
26
|
-
body: JSON.stringify({ name: 'e2e-' + Math.random().toString(36).slice(2, 10) }),
|
|
28
|
+
body: JSON.stringify({ name: 'e2e-' + Math.random().toString(36).slice(2, 10), email: `e2e-team-${Date.now()}@test.local`, password: 'Passw0rd!123' }),
|
|
27
29
|
}).then(r => r.json()).catch(() => null)
|
|
28
30
|
const __userToken = __user?.data?.token
|
|
29
31
|
if (!__userToken) {
|
|
@@ -378,16 +378,16 @@ let channelB
|
|
|
378
378
|
|
|
379
379
|
// KB 回环:kb_index 入库独特自然语句 → kb_search 命中(嵌入/分词对自然语句才可靠);kb_store 沉淀经验
|
|
380
380
|
const marker = `三系统验证密语${Date.now().toString(36)}:青花瓷泵站三十七号叶片于黄昏完成校准`
|
|
381
|
-
const idx = await invoke(toolInvoker, 'kb_index', {
|
|
381
|
+
const idx = await invoke(toolInvoker, 'kb_index', { // rag 负载下事件循环停顿可达 60s+,放宽超时
|
|
382
382
|
title: `三系统集成验证 ${Date.now().toString(36)}`,
|
|
383
383
|
content: `# 三系统集成验证\n\n${marker}。\n\n本文由 three-system-e2e 经 rag-bridge 插件写入,验证 文档写盘 → 向量索引 → kb_search 检索 全链路。\n`,
|
|
384
384
|
tags: ['e2e'],
|
|
385
|
-
})
|
|
385
|
+
}, 120000)
|
|
386
386
|
ok(resultText(idx).includes('已入库'), 'kb_index 文档入库成功', resultText(idx).slice(0, 80))
|
|
387
387
|
let hit = ''
|
|
388
|
-
for (let i = 0; i <
|
|
388
|
+
for (let i = 0; i < 20; i++) { // 首次检索可能触发 BGE-M3 加载/异步索引落盘,放宽到 20×3s
|
|
389
389
|
await sleep(3000)
|
|
390
|
-
const s = await invoke(toolInvoker, 'kb_search', { query: marker })
|
|
390
|
+
const s = await invoke(toolInvoker, 'kb_search', { query: marker }, 120000)
|
|
391
391
|
hit = resultText(s)
|
|
392
392
|
if (hit.includes(marker)) break
|
|
393
393
|
}
|
|
@@ -400,7 +400,7 @@ let channelB
|
|
|
400
400
|
solution: '先查产线 LineRun 是否活动、节点 publishIntervalMs 是否在节拍上,再缩窗重试。',
|
|
401
401
|
key_lessons: ['空窗先查打标窗口', 'bucket 5s 可对齐多节点'],
|
|
402
402
|
tags: ['e2e', 'daq'],
|
|
403
|
-
})
|
|
403
|
+
}, 120000)
|
|
404
404
|
ok(resultText(store).includes('已沉淀'), 'kb_store 经验沉淀成功', resultText(store).slice(0, 80))
|
|
405
405
|
|
|
406
406
|
// 跨通道:分析组长 → 控制组长(require_reply;用频道 ID 定向,避免跨账号同名频道歧义)
|
|
@@ -628,7 +628,7 @@ let runId = ''
|
|
|
628
628
|
return (envelopeData(members) ?? []).find(m => m?.role === 'lead') ?? leadA
|
|
629
629
|
}
|
|
630
630
|
let gone = false
|
|
631
|
-
for (let i = 0; i <
|
|
631
|
+
for (let i = 0; i < 40 && !gone; i++) { // 共享实例 agent 运行时重建慢,60s 窗
|
|
632
632
|
await sleep(1500)
|
|
633
633
|
const fl = await freshLead()
|
|
634
634
|
const h = await raw('GET', `${BASE}/api/plugins/diag-bridge/health`, { token: userToken })
|
|
@@ -349,10 +349,17 @@ export default {
|
|
|
349
349
|
outbound: state.outbound,
|
|
350
350
|
auth: kbToken() ? 'bearer' : 'anonymous',
|
|
351
351
|
// token 配置与「实测是否被接受」分开呈现:401/403 = 明确被拒(运维一眼看出 token 配错),
|
|
352
|
-
// 网络不通/超时为 null(未知),2xx 或非鉴权类失败为 true(未被拒)
|
|
352
|
+
// 网络不通/超时为 null(未知),2xx 或非鉴权类失败为 true(未被拒)。
|
|
353
|
+
// 实测打受保护 GET /api/v1/auth/me —— rag 后端 GET 只读端点公开(/health 匿名可过,
|
|
354
|
+
// 测不出 token 对错),/auth/me 无 token/错 token 均 401。
|
|
353
355
|
token: {
|
|
354
356
|
configured: Boolean(kbToken()),
|
|
355
|
-
accepted:
|
|
357
|
+
accepted: await (async () => {
|
|
358
|
+
if (!state.outbound) return null
|
|
359
|
+
if (!kbToken()) return backend.ok ? true : null
|
|
360
|
+
const me = await callJson('GET', `${base()}/api/v1/auth/me`, null, { timeoutMs: 5000, retries: 0 })
|
|
361
|
+
return me.ok ? true : (me.status === 401 || me.status === 403 ? false : null)
|
|
362
|
+
})(),
|
|
356
363
|
},
|
|
357
364
|
kb: { name: KB_NAME, id: kbId() || null },
|
|
358
365
|
backend: { url: base(), ok: backend.ok, ...(backend.ok ? { status: backend.body?.status ?? null } : { status: backend.status ?? null, error: backend.error }) },
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{a as e,c as t,j as n}from"./BU83-NnX.js";import{$ as r,D as i,G as a,H as o,Ht as s,P as c,R as l,S as u,Ut as d,V as f,Vt as p,W as m,b as h,d as g,f as _,h as v,ht as y,i as b,m as x,nt as S,p as C,pt as w,tt as T,v as E,xt as D,y as O}from"./CSkxz2NX.js";import{d as ee,f as k,n as te,t as A,u as j}from"./D6uzXueg.js";import{d as M,p as N}from"./BJHKLJJU.js";import{i as ne}from"./YnQxK3eG.js";import{n as re,r as ie,t as ae}from"./BzHEilTt.js";import{t as oe}from"./BHA40aHa.js";import{n as P}from"./KZQX7xoM.js";import{t as se}from"./D9Oidm5I.js";import{At as F,St as ce,d as le,jt as I,n as L,nt as R,t as z,u as B,wt as V}from"./4sIEbgcl.js";import{i as ue}from"./DYr1VMiQ.js";import{t as de}from"./aWWIh8YL.js";import{a as H,i as U,n as fe,r as pe,t as me}from"./CzlMDL5H.js";import{t as he}from"./lO5tpDZ5.js";import{n as W}from"./JCoYF4IJ.js";import{t as ge}from"./Crod5z2f.js";import{t as _e}from"./C4DWUZ6d2.js";import{t as ve}from"./JTLM-kqr2.js";import{t as ye}from"./DIaZ2PTo2.js";import{t as G}from"./BDNMzG2s2.js";import{t as be}from"./Cc_9VzD42.js";import{t as xe}from"./D0ZBQrN_2.js";import{m as Se,p as Ce,t as we}from"./BNT8gYU92.js";import{t as Te}from"./BN6iuJEg2.js";var K=e=>{let{componentCls:t,colorBgContainer:n,colorBgBody:r,colorText:i}=e;return{[`${t}-sider-light`]:{background:n,[`${t}-sider-trigger`]:{color:i,background:n},[`${t}-sider-zero-width-trigger`]:{color:i,background:n,border:`1px solid ${r}`,borderInlineStart:0}}}},Ee=e=>{let{antCls:t,componentCls:n,colorText:r,colorTextLightSolid:i,colorBgHeader:a,colorBgBody:o,colorBgTrigger:s,layoutHeaderHeight:c,layoutHeaderPaddingInline:l,layoutHeaderColor:u,layoutFooterPadding:d,layoutTriggerHeight:f,layoutZeroTriggerSize:p,motionDurationMid:m,motionDurationSlow:h,fontSize:g,borderRadius:_}=e;return{[n]:F(F({display:`flex`,flex:`auto`,flexDirection:`column`,color:r,minHeight:0,background:o,"&, *":{boxSizing:`border-box`},[`&${n}-has-sider`]:{flexDirection:`row`,[`> ${n}, > ${n}-content`]:{width:0}},[`${n}-header, &${n}-footer`]:{flex:`0 0 auto`},[`${n}-header`]:{height:c,paddingInline:l,color:u,lineHeight:`${c}px`,background:a,[`${t}-menu`]:{lineHeight:`inherit`}},[`${n}-footer`]:{padding:d,color:r,fontSize:g,background:o},[`${n}-content`]:{flex:`auto`,minHeight:0},[`${n}-sider`]:{position:`relative`,minWidth:0,background:a,transition:`all ${m}, background 0s`,"&-children":{height:`100%`,marginTop:-.1,paddingTop:.1,[`${t}-menu${t}-menu-inline-collapsed`]:{width:`auto`}},"&-has-trigger":{paddingBottom:f},"&-right":{order:1},"&-trigger":{position:`fixed`,bottom:0,zIndex:1,height:f,color:i,lineHeight:`${f}px`,textAlign:`center`,background:s,cursor:`pointer`,transition:`all ${m}`},"&-zero-width":{"> *":{overflow:`hidden`},"&-trigger":{position:`absolute`,top:c,insetInlineEnd:-p,zIndex:1,width:p,height:p,color:i,fontSize:e.fontSizeXL,display:`flex`,alignItems:`center`,justifyContent:`center`,background:a,borderStartStartRadius:0,borderStartEndRadius:_,borderEndEndRadius:_,borderEndStartRadius:0,cursor:`pointer`,transition:`background ${h} ease`,"&::after":{position:`absolute`,inset:0,background:`transparent`,transition:`all ${h}`,content:`""`},"&:hover::after":{background:`rgba(255, 255, 255, 0.2)`},"&-right":{insetInlineStart:-p,borderStartStartRadius:_,borderStartEndRadius:0,borderEndEndRadius:0,borderEndStartRadius:_}}}}},K(e)),{"&-rtl":{direction:`rtl`}})}},De=le(`Layout`,e=>{let{colorText:t,controlHeightSM:n,controlHeight:r,controlHeightLG:i,marginXXS:a}=e,o=i*1.25;return[Ee(B(e,{layoutHeaderHeight:r*2,layoutHeaderPaddingInline:o,layoutHeaderColor:t,layoutFooterPadding:`${n}px ${o}px`,layoutTriggerHeight:i+a*2,layoutZeroTriggerSize:i}))]},e=>{let{colorBgLayout:t}=e;return{colorBgHeader:`#001529`,colorBgBody:t,colorBgTrigger:`#002140`}}),q=()=>({prefixCls:String,hasSider:{type:Boolean,default:void 0},tagName:String});function J(e){let{suffixCls:t,tagName:n,name:r}=e;return e=>u({compatConfig:{MODE:3},name:r,props:q(),setup(r,i){let{slots:a}=i,{prefixCls:o}=L(t,r);return()=>{let t=F(F({},r),{prefixCls:o.value,tagName:n});return h(e,t,a)}}})}var Y=u({compatConfig:{MODE:3},props:q(),setup(e,t){let{slots:n}=t;return()=>h(e.tagName,{class:e.prefixCls},n)}}),Oe=u({compatConfig:{MODE:3},inheritAttrs:!1,props:q(),setup(e,t){let{slots:n,attrs:r}=t,{prefixCls:i,direction:a}=L(``,e),[s,c]=De(i),l=w([]);o(H,{addSider:e=>{l.value=[...l.value,e]},removeSider:e=>{l.value=l.value.filter(t=>t!==e)}});let u=g(()=>{let{prefixCls:t,hasSider:n}=e;return{[c.value]:!0,[`${t}`]:!0,[`${t}-has-sider`]:typeof n==`boolean`?n:l.value.length>0,[`${t}-rtl`]:a.value===`rtl`}});return()=>{let{tagName:t}=e;return s(h(t,F(F({},r),{class:[u.value,r.class]}),n))}}}),ke=J({suffixCls:`layout`,tagName:`section`,name:`ALayout`})(Oe),X=J({suffixCls:`layout-header`,tagName:`header`,name:`ALayoutHeader`})(Y),Z=J({suffixCls:`layout-footer`,tagName:`footer`,name:`ALayoutFooter`})(Y),Q=J({suffixCls:`layout-content`,tagName:`main`,name:`ALayoutContent`})(Y),Ae={icon:{tag:`svg`,attrs:{viewBox:`0 0 1024 1024`,focusable:`false`},children:[{tag:`path`,attrs:{d:`M912 192H328c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h584c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 284H328c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h584c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 284H328c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h584c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM104 228a56 56 0 10112 0 56 56 0 10-112 0zm0 284a56 56 0 10112 0 56 56 0 10-112 0zm0 284a56 56 0 10112 0 56 56 0 10-112 0z`}}]},name:`bars`,theme:`outlined`};function je(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]==null?{}:Object(arguments[t]),r=Object.keys(n);typeof Object.getOwnPropertySymbols==`function`&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(e){return Object.getOwnPropertyDescriptor(n,e).enumerable}))),r.forEach(function(t){Me(e,t,n[t])})}return e}function Me(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var Ne=function(e,t){var r=je({},e,t.attrs);return h(n,je({},r,{icon:Ae}),null)};Ne.displayName=`BarsOutlined`,Ne.inheritAttrs=!1;var Pe={xs:`479.98px`,sm:`575.98px`,md:`767.98px`,lg:`991.98px`,xl:`1199.98px`,xxl:`1599.98px`,xxxl:`1999.98px`},Fe=()=>({prefixCls:String,collapsible:{type:Boolean,default:void 0},collapsed:{type:Boolean,default:void 0},defaultCollapsed:{type:Boolean,default:void 0},reverseArrow:{type:Boolean,default:void 0},zeroWidthTriggerStyle:{type:Object,default:void 0},trigger:z.any,width:z.oneOfType([z.number,z.string]),collapsedWidth:z.oneOfType([z.number,z.string]),breakpoint:z.oneOf(R(`xs`,`sm`,`md`,`lg`,`xl`,`xxl`,`xxxl`)),theme:z.oneOf(R(`light`,`dark`)).def(`dark`),onBreakpoint:Function,onCollapse:Function}),Ie=(()=>{let e=0;return function(){let t=arguments.length>0&&arguments[0]!==void 0?arguments[0]:``;return e+=1,`${t}${e}`}})(),$=u({compatConfig:{MODE:3},name:`ALayoutSider`,inheritAttrs:!1,props:ce(Fe(),{collapsible:!1,defaultCollapsed:!1,reverseArrow:!1,width:200,collapsedWidth:80}),emits:[`breakpoint`,`update:collapsed`,`collapse`],setup(e,t){let{emit:n,attrs:a,slots:s}=t,{prefixCls:u}=L(`layout-sider`,e),d=i(H,void 0),f=y(!!(e.collapsed===void 0?e.defaultCollapsed:e.collapsed)),p=y(!1);r(()=>e.collapsed,()=>{f.value=!!e.collapsed}),o(U,f);let m=(t,r)=>{e.collapsed===void 0&&(f.value=t),n(`update:collapsed`,t),n(`collapse`,t,r)},g=y(e=>{p.value=e.matches,n(`breakpoint`,e.matches),f.value!==e.matches&&m(e.matches,`responsive`)}),_;function v(e){return g.value(e)}let b=Ie(`ant-sider-`);d&&d.addSider(b),l(()=>{r(()=>e.breakpoint,()=>{try{_?.removeEventListener(`change`,v)}catch{_?.removeListener(v)}if(typeof window<`u`){let{matchMedia:t}=window;if(t&&e.breakpoint&&e.breakpoint in Pe){_=t(`(max-width: ${Pe[e.breakpoint]})`);try{_.addEventListener(`change`,v)}catch{_.addListener(v)}v(_)}}},{immediate:!0})}),c(()=>{try{_?.removeEventListener(`change`,v)}catch{_?.removeListener(v)}d&&d.removeSider(b)});let x=()=>{m(!f.value,`clickTrigger`)};return()=>{let t=u.value,{collapsedWidth:n,width:r,reverseArrow:i,zeroWidthTriggerStyle:o,trigger:c=s.trigger?.call(s),collapsible:l,theme:d}=e,m=f.value?n:r,g=he(m)?`${m}px`:String(m),_=parseFloat(String(n||0))===0?h(`span`,{onClick:x,class:V(`${t}-zero-width-trigger`,`${t}-zero-width-trigger-${i?`right`:`left`}`),style:o},[c||h(Ne,null,null)]):null,v={expanded:h(i?W:ge,null,null),collapsed:h(i?ge:W,null,null)}[f.value?`collapsed`:`expanded`],y=c===null?null:_||h(`div`,{class:`${t}-trigger`,onClick:x,style:{width:g}},[c||v]),b=[a.style,{flex:`0 0 ${g}`,maxWidth:g,minWidth:g,width:g}],S=V(t,`${t}-${d}`,{[`${t}-collapsed`]:!!f.value,[`${t}-has-trigger`]:l&&c!==null&&!_,[`${t}-below`]:!!p.value,[`${t}-zero-width`]:parseFloat(g)===0},a.class);return h(`aside`,I(I({},a),{},{class:S,style:b}),[h(`div`,{class:`${t}-children`},[s.default?.call(s)]),l||p.value&&_?y:null])}}}),Le=X,Re=Z,ze=$,Be=Q,Ve=F(ke,{Header:X,Footer:Z,Content:Q,Sider:$,install:e=>(e.component(ke.name,ke),e.component(X.name,X),e.component(Z.name,Z),e.component($.name,$),e.component(Q.name,Q),e)}),He=[`width`,`height`],Ue=Object.assign(u({__name:`AwLogo`,props:{size:{default:32}},setup(e){return(t,n)=>(f(),v(`svg`,{width:e.size,height:e.size,viewBox:`0 0 64 64`,fill:`none`,"aria-hidden":`true`},[...n[0]||=[E(`<defs><linearGradient id="aw-logo-gradient" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#35e0a0"></stop><stop offset="1" stop-color="#41c8f4"></stop></linearGradient></defs><path d="M32 4 L56 18 V46 L32 60 L8 46 V18 Z" stroke="url(#aw-logo-gradient)" stroke-width="4" stroke-linejoin="round"></path><path d="M32 15 L46.7 23.5 V40.5 L32 49 L17.3 40.5 V23.5 Z" stroke="#41c8f4" stroke-opacity="0.45" stroke-width="1.8" stroke-dasharray="4 3"></path><path d="M32 23 L25 38 M32 23 L39 38 M25 38 L39 38" stroke="#35e0a0" stroke-width="1.8" stroke-opacity="0.75"></path><circle cx="32" cy="23" r="3.4" fill="#35e0a0"></circle><circle cx="25" cy="38" r="3.4" fill="#41c8f4"></circle><circle cx="39" cy="38" r="3.4" fill="#41c8f4"></circle>`,7)]],8,He))}}),{__name:`AwLogo`}),We={class:`logo`},Ge={class:`logo-mark`,"aria-hidden":`true`},Ke={class:`logo-text`},qe={class:`logo-title`},Je={class:`app-menu`},Ye={class:`menu-group-label`},Xe={class:`menu-group-text`},Ze={class:`menu-group-sep`,"aria-hidden":`true`},Qe=[`title`,`onClick`],$e={class:`sider-footer`},et={class:`footer-line`},tt=Object.assign(G(u({__name:`AppSidebar`,setup(e){let t=ye(),{t:n}=P(),r=N(),i=ae(),a=re(),o=g(()=>[{id:`console`,label:n(`menu.groups.console`),items:[{key:`/`,icon:`i-tabler-layout-dashboard`,label:n(`menu.dashboard`),motion:`im-pop`},{key:`/workshop`,icon:`i-tabler-box`,label:n(`menu.workshop`),motion:`im-pop`},{key:`/town`,icon:`i-tabler-map-2`,label:n(`menu.town`),motion:`im-pop`},{key:`/daq`,icon:`i-tabler-activity`,label:n(`menu.daq`),motion:`im-pop`},{key:`/dcw`,icon:`i-tabler-settings-automation`,label:n(`menu.dcw`),motion:`im-pop`}]},{id:`ops`,label:n(`menu.groups.ops`),items:[{key:`/monitor`,icon:`i-tabler-cpu`,label:n(`menu.monitor`),motion:`im-pulse`},{key:`/logs`,icon:`i-tabler-list-details`,label:n(`menu.logs`),motion:`im-pop`}]},{id:`system`,label:n(`menu.groups.system`),items:[{key:`/tokens`,icon:`i-tabler-key`,label:n(`menu.tokens`),motion:`im-nudge-up`},{key:`/users`,icon:`i-tabler-users-group`,label:n(`menu.users`),motion:`im-pop`},{key:`/permissions`,icon:`i-tabler-shield-lock`,label:n(`menu.permissions`),motion:`im-pop`,adminOnly:!0},{key:`/plugins`,icon:`i-tabler-puzzle`,label:n(`menu.plugins`),motion:`im-pop`},{key:`/settings`,icon:`i-tabler-settings`,label:n(`menu.settings`),motion:`im-rotate`}]}].map(e=>({...e,items:e.items.filter(e=>!e.adminOnly||t.isAdmin)})).filter(e=>e.items.length>0)),s=e=>e===`/`?r.path===`/`:r.path.startsWith(e),c=e=>{s(e)||M(e)};return(e,t)=>{let n=Ue,r=ze;return f(),C(r,{collapsed:D(a).sidebarCollapsed,"onUpdate:collapsed":t[0]||=e=>D(a).sidebarCollapsed=e,trigger:null,collapsible:``,breakpoint:`lg`,width:228,"collapsed-width":64,class:`app-sider`},{default:T(()=>[_(`div`,We,[_(`div`,Ge,[h(n,{size:30})]),h(A,{name:`slide-fade`},{default:T(()=>[S(_(`div`,Ke,[_(`span`,qe,d(D(i).name),1),t[1]||=_(`span`,{class:`logo-sub`},`digital twin`,-1)],512),[[j,!D(a).sidebarCollapsed]])]),_:1})]),_(`nav`,Je,[(f(!0),v(b,null,m(D(o),e=>(f(),v(`div`,{key:e.id,class:`menu-group`},[S(_(`div`,Ye,[_(`span`,Xe,d(e.label),1),t[2]||=_(`span`,{class:`menu-group-rule`,"aria-hidden":`true`},null,-1)],512),[[j,!D(a).sidebarCollapsed]]),S(_(`div`,Ze,null,512),[[j,D(a).sidebarCollapsed]]),(f(!0),v(b,null,m(e.items,e=>(f(),v(`button`,{key:e.key,type:`button`,class:p([`menu-item im`,{active:s(e.key)}]),title:D(a).sidebarCollapsed?e.label:void 0,onClick:t=>c(e.key)},[_(`span`,{class:p([`menu-icon`,[e.icon,e.motion]])},null,2),S(_(`span`,{class:`menu-label`},d(e.label),513),[[j,!D(a).sidebarCollapsed]])],10,Qe))),128))]))),128))]),S(_(`div`,$e,[t[4]||=_(`div`,{class:`footer-rule`},null,-1),_(`div`,et,[_(`span`,null,`v`+d(D(i).version),1),t[3]||=_(`span`,{class:`sep`},`/`,-1),_(`span`,null,d(D(i).mode),1)])],512),[[j,!D(a).sidebarCollapsed]])]),_:1},8,[`collapsed`])}}}),[[`__scopeId`,`data-v-095cc5a0`]]),{__name:`AppSidebar`}),nt=ne(`app.routeTrail`,()=>{let e=w([]);function t(t){if(!t||t.startsWith(`/api`))return;let n=e.value.filter(e=>e.path!==t);e.value=[...n,{path:t,at:Date.now()}].slice(-8)}function n(t){let n=e.value.findIndex(e=>e.path===t);return n>=0&&(e.value=e.value.filter(e=>e.path!==t)),n}function r(){e.value=[]}return{waypoints:e,visit:t,remove:n,clear:r}},{persist:{pick:[`waypoints`],storage:ie.localStorage()}});function rt(){let{t:e}=P(),t=be(),n={"/":{key:`menu.dashboard`,icon:`i-tabler-layout-dashboard`},"/workshop":{key:`menu.workshop`,icon:`i-tabler-box`},"/workshop/agents":{key:`meta.agents`,icon:`i-tabler-users`},"/workshop/teams":{key:`meta.teams`,icon:`i-tabler-users-group`},"/workshop/channel-templates":{key:`meta.ctpl`,icon:`i-tabler-layout-grid-add`},"/town":{key:`menu.town`,icon:`i-tabler-map-2`},"/tokens":{key:`menu.tokens`,icon:`i-tabler-key`},"/daq":{key:`menu.daq`,icon:`i-tabler-activity`},"/dcw":{key:`menu.dcw`,icon:`i-tabler-settings-automation`},"/logs":{key:`menu.logs`,icon:`i-tabler-list-details`},"/permissions":{key:`menu.permissions`,icon:`i-tabler-shield-lock`},"/plugins":{key:`menu.plugins`,icon:`i-tabler-puzzle`},"/users":{key:`menu.users`,icon:`i-tabler-users-group`},"/monitor":{key:`menu.monitor`,icon:`i-tabler-cpu`},"/settings":{key:`menu.settings`,icon:`i-tabler-settings`}};return{metaFor:r=>{let i=n[r];if(i)return{title:e(i.key),icon:i.icon};let a=r.match(/^\/workshop\/w\/([^/]+)$/);if(a){let n=a[1];return{title:t.workspaces.find(e=>e.id===n)?.name??`${e(`header.workspace`)} ${n.slice(0,6)}`,icon:`i-tabler-console`}}let o=r.split(`/`).filter(Boolean).pop()??`·`;return{title:o.charAt(0).toUpperCase()+o.slice(1),icon:`i-tabler-point`}}}}var it={class:`header-left`},at=[`aria-label`],ot={class:`node-title`},st=[`aria-label`],ct=[`title`,`onClick`,`onKeydown`],lt={class:`node-title`},ut=[`aria-label`,`title`,`onClick`],dt={class:`header-right`},ft=[`title`],pt={class:`hitl-count`},mt={class:`hitl-menu`},ht={class:`hitl-menu-title`},gt=[`onClick`],_t={class:`hitl-item-top`},vt={class:`hitl-item-agent`},yt={class:`hitl-item-kind`},bt={class:`hitl-item-title`},xt=[`title`],St={class:`user-chip`},Ct={class:`user-initial aw-avatar`},wt={class:`user-meta`},Tt={class:`user-name`},Et={class:`user-role`},Dt=Object.assign(G(u({__name:`AppHeader`,setup(n){let{t:i,locale:a,locales:o,setLocale:s}=P(),u=re(),y=N(),S=nt(),E=ye(),{metaFor:A}=rt(),j=Ce(),ne=we(),ie=()=>{E.isLoggedIn&&ne.ensureConnected()};r(()=>E.token,e=>{e?(ie(),j.loadSnapshot()):j.clear()},{immediate:!0});let ae=new Set([`codex-approval`,`opencode-permission`,`dsh-permission`]),F=e=>{switch(e){case`omp-dialog`:return i(`appHeader.hitlKindOmp`);case`dcw-approval`:return i(`appHeader.hitlKindDcw`);case`codex-approval`:return i(`appHeader.hitlKindCodex`);case`opencode-permission`:return i(`appHeader.hitlKindOpencode`);case`dsh-permission`:return i(`appHeader.hitlKindDsh`);default:return e}},ce=e=>{M({path:`/monitor`,query:{agentId:e.agentId,channelId:e.channelId}})},le=Te(),I=w(null),L=async(t,n)=>{I.value=`${t.kind}:${t.id}`;try{await le.respondHitl({kind:t.kind,id:t.id,confirmed:n,cancelled:!n}),await j.loadSnapshot()}catch(t){e.error(xe(t))}finally{I.value=null}},R=g(()=>o.value.map(e=>({label:e.name,value:e.code}))),z=e=>{e!=null&&(localStorage.setItem(`aw.locale`,String(e)),s(String(e)),window.location.reload())},B=w(!1),V=w(!1),H=null;r(()=>y.path,()=>{S.visit(y.path),V.value=!1,requestAnimationFrame(()=>{V.value=!0,H&&clearTimeout(H),H=setTimeout(()=>{V.value=!1},620)})},{immediate:!1}),l(()=>{B.value=!0,S.visit(y.path)}),c(()=>{H&&clearTimeout(H)});let U=e=>{e!==y.path&&M(e)},he=e=>{let t=S.remove(e);if(e!==y.path)return;let n=S.waypoints,r=n[Math.min(Math.max(t-1,0),Math.max(n.length-1,0))]?.path??`/`;M(r)},W=w(!1);function ge(){document.fullscreenElement?(document.exitFullscreen(),W.value=!1):(document.documentElement.requestFullscreen(),W.value=!0)}let ve=g(()=>(E.user?.name??`?`).trim().charAt(0).toUpperCase()),G=g(()=>E.user?.name??i(`header.guest`)),be=g(()=>E.isLoggedIn?E.user?.role??`user`:`anonymous`),K=Se(),Ee=g(()=>K.state!==`closed`||K.lastDataAt>0),De=g(()=>K.state===`open`?K.pendingReplay?`syncing`:`live`:K.state===`connecting`?`syncing`:`down`),q=g(()=>K.state===`open`?K.pendingReplay?i(`appHeader.kwsdot0002`):i(`appHeader.kwsdot0001`):K.state===`connecting`?i(`appHeader.kwsdot0003`):i(`appHeader.kwsdot0004`)),J=g(()=>{let e=[{key:`tokens`,icon:`i-tabler-key`,label:i(`menu.tokens`)},{key:`settings`,icon:`i-tabler-adjustments`,label:i(`menu.settings`)}];return E.isLoggedIn&&(e.push({key:`d-logout`,label:``,divider:!0}),e.push({key:`logout`,icon:`i-tabler-logout`,label:i(`header.logout`),danger:!0})),e}),Y=async({key:e})=>{e===`settings`?M(`/settings`):e===`tokens`?M(`/tokens`):e===`logout`&&(await E.logout(),M(`/workshop`))};return(e,n)=>{let r=oe,o=t,s=_e,c=se,l=ue,g=de,w=fe,E=pe,M=me,N=Le;return f(),C(N,{class:`app-header app-header-glass`},{default:T(()=>[_(`div`,it,[_(`button`,{class:`collapse-btn`,"aria-label":D(u).sidebarCollapsed?D(i)(`header.expand`):D(i)(`header.collapse`),onClick:n[0]||=e=>D(u).toggleSidebar()},[...n[3]||=[_(`span`,{class:`i-tabler-menu-2`},null,-1)]],8,at),n[6]||=_(`span`,{class:`rail-mark i-tabler-route`},null,-1),h(r,{class:p([`trail-node aml-entry`,{active:D(y).path.startsWith(`/aml`)}]),to:`/aml`,title:D(i)(`aml.k1amlx159`)},{default:T(()=>[n[4]||=_(`span`,{class:`node-icon i-tabler-flask`},null,-1),_(`span`,ot,d(D(i)(`aml.k1amlx158`)),1)]),_:1},8,[`class`,`title`]),_(`nav`,{class:`trail`,"aria-label":D(i)(`header.trail`)},[h(te,{name:`stamp`,tag:`div`,class:`trail-row`},{default:T(()=>[D(B)?(f(!0),v(b,{key:0},m(D(S).waypoints,(t,r)=>(f(),v(b,{key:t.path},[r>0?(f(),v(`span`,{key:`link-${t.path}`,class:`trail-link`,"aria-hidden":`true`})):x(``,!0),_(`div`,{class:p([`trail-node`,{active:t.path===D(y).path}]),role:`button`,tabindex:`0`,title:D(A)(t.path).title,onClick:e=>U(t.path),onKeydown:ee(k(e=>U(t.path),[`prevent`]),[`enter`])},[_(`span`,{class:p([`node-icon`,D(A)(t.path).icon])},null,2),_(`span`,lt,d(D(A)(t.path).title),1),_(`button`,{class:`node-close`,"aria-label":e.$t(`appHeader.kzwjv99001`,{p0:D(A)(t.path).title}),title:e.$t(`appHeader.kzwjv99001`,{p0:D(A)(t.path).title}),onClick:k(e=>he(t.path),[`stop`])},[...n[5]||=[_(`span`,{class:`i-tabler-x`},null,-1)]],8,ut)],42,ct)],64))),128)):x(``,!0)]),_:1})],8,st)]),_(`div`,dt,[h(c,null,{default:T(()=>[D(j).count>0?(f(),C(s,{key:0,placement:`bottomRight`},{overlay:T(()=>[_(`div`,mt,[_(`div`,ht,d(D(i)(`appHeader.hitlBadge`))+` · `+d(D(j).count),1),(f(!0),v(b,null,m(D(j).items,e=>(f(),v(`button`,{key:`${e.kind}:${e.id}`,class:`hitl-item`,onClick:t=>ce(e)},[_(`span`,_t,[_(`span`,vt,d(e.agentName),1),_(`span`,yt,d(F(e.kind)),1)]),_(`span`,bt,d(e.title),1),D(ae).has(e.kind)?(f(),v(`span`,{key:0,class:`hitl-item-actions`,onClick:n[1]||=k(()=>{},[`stop`])},[h(o,{size:`small`,type:`primary`,loading:D(I)===`${e.kind}:${e.id}`,onClick:t=>L(e,!0)},{default:T(()=>[O(d(D(i)(`appHeader.hitlApprove`)),1)]),_:1},8,[`loading`,`onClick`]),h(o,{size:`small`,danger:``,disabled:D(I)===`${e.kind}:${e.id}`,onClick:t=>L(e,!1)},{default:T(()=>[O(d(D(i)(`appHeader.hitlReject`)),1)]),_:1},8,[`disabled`,`onClick`])])):x(``,!0)],8,gt))),128))])]),default:T(()=>[_(`button`,{class:`icon-btn hitl-bell`,title:D(i)(`appHeader.hitlBadge`)},[n[7]||=_(`span`,{class:`i-tabler-bell-ringing`},null,-1),_(`span`,pt,d(D(j).count),1)],8,ft)]),_:1})):x(``,!0)]),_:1}),D(Ee)?(f(),v(`span`,{key:0,class:p([`ws-dot`,D(De)]),title:D(q)},null,10,xt)):x(``,!0),h(l,{title:D(i)(`header.fullscreen`)},{default:T(()=>[_(`button`,{class:`icon-btn`,onClick:ge},[_(`span`,{class:p([`i-tabler-arrows-maximize`,{hidden:D(W)}])},null,2),_(`span`,{class:p([`i-tabler-arrows-minimize`,{hidden:!D(W)}])},null,2)])]),_:1},8,[`title`]),h(g,{id:`hdr-locale`,value:D(a),size:`middle`,options:D(R),class:`lang-select`,onChange:z},null,8,[`value`,`options`]),h(l,{title:D(u).isDark?D(i)(`common.light`):D(i)(`common.dark`)},{default:T(()=>[_(`button`,{class:`icon-btn`,onClick:n[2]||=e=>D(u).toggleDark()},[_(`span`,{class:p([`i-tabler-sun-high`,{hidden:D(u).isDark}])},null,2),_(`span`,{class:p([`i-tabler-moon-stars`,{hidden:!D(u).isDark}])},null,2)])]),_:1},8,[`title`]),h(s,null,{overlay:T(()=>[h(M,{onClick:Y},{default:T(()=>[(f(!0),v(b,null,m(D(J),e=>(f(),v(b,{key:e.key},[e.divider?(f(),C(w,{key:0})):(f(),C(E,{key:e.key,danger:e.danger},{default:T(()=>[_(`span`,{class:p([e.icon,`mr-2`])},null,2),O(` `+d(e.label),1)]),_:2},1032,[`danger`]))],64))),128))]),_:1})]),default:T(()=>[_(`div`,St,[h(c,null,{fallback:T(()=>[...n[8]||=[_(`span`,{class:`user-initial aw-avatar`},`·`,-1),_(`span`,{class:`user-meta`},[_(`span`,{class:`user-name`},`·`),_(`span`,{class:`user-role`},`·`)],-1)]]),default:T(()=>[_(`span`,Ct,d(D(ve)),1),_(`span`,wt,[_(`span`,Tt,d(D(G)),1),_(`span`,Et,d(D(be)),1)])]),_:1})])]),_:1})]),_(`span`,{class:p([`plotter-line`,{run:D(V)}]),"aria-hidden":`true`},null,2)]),_:1})}}}),[[`__scopeId`,`data-v-1fa471c5`]]),{__name:`AppHeader`}),Ot={class:`footer-title aw-serif-accent`},kt=G(u({__name:`default`,setup(e){let{token:t}=ve.useToken(),n=ae();return(e,r)=>{let i=tt,o=Dt,c=Be,l=Re,u=Ve;return f(),C(u,{class:`app-layout`,"has-sider":``},{default:T(()=>[h(i),h(u,{class:`app-main`,style:s({background:`transparent`,"--app-bg-container":D(t)?.colorBgContainer,"--app-bg-layout":D(t)?.colorBgLayout,"--app-text":D(t)?.colorText,"--app-text-secondary":D(t)?.colorTextSecondary,"--app-border":D(t)?.colorBorderSecondary,"--app-fill":D(t)?.colorFillQuaternary,"--app-header-h":`56px`,"--app-footer-h":`46px`})},{default:T(()=>[h(o),h(c,{class:`app-content`},{default:T(()=>[a(e.$slots,`default`,{},void 0,!0)]),_:3}),h(l,{class:`app-footer`,style:s({color:D(t)?.colorTextSecondary})},{default:T(()=>[_(`span`,Ot,d(D(n).title),1),r[0]||=_(`span`,{class:`sep`},`/`,-1),_(`span`,null,`v`+d(D(n).version),1),r[1]||=_(`span`,{class:`sep`},`/`,-1),_(`span`,null,`mode=`+d(D(n).mode),1)]),_:1},8,[`style`])]),_:3},8,[`style`]),r[2]||=_(`span`,{class:`aw-noise`,"aria-hidden":`true`},null,-1)]),_:3})}}}),[[`__scopeId`,`data-v-b48dd792`]]);export{kt as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"id":"44b66249-54d0-4c8a-9057-9755a32329e2","timestamp":1789189585393,"prerendered":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.app-sider[data-v-095cc5a0]{background:var(--mat-chrome-bg);height:100vh;-webkit-backdrop-filter:var(--vibrancy-chrome);backdrop-filter:var(--vibrancy-chrome);border-right:1px solid var(--glass-line);box-shadow:var(--glass-specular);z-index:20;position:sticky;top:0;overflow:hidden auto}.app-sider[data-v-095cc5a0]::-webkit-scrollbar{width:0}.logo[data-v-095cc5a0]{border-bottom:1px solid var(--line);align-items:center;gap:12px;height:58px;padding:0 16px;display:flex;overflow:hidden}.logo-mark[data-v-095cc5a0]{filter:drop-shadow(0 0 6px #35e0a042);flex:none;justify-content:center;align-items:center;width:32px;height:36px;display:flex}.logo-text[data-v-095cc5a0]{white-space:nowrap;flex-direction:column;line-height:1.25;display:flex}.logo-title[data-v-095cc5a0]{font-family:var(--font-mono);letter-spacing:.06em;text-transform:uppercase;color:var(--ink);font-size:13px;font-weight:600}.logo-sub[data-v-095cc5a0]{font-family:var(--font-mono);letter-spacing:.2em;text-transform:uppercase;color:var(--sider-ink-faint);font-size:8.5px}.app-menu[data-v-095cc5a0]{flex-direction:column;gap:14px;padding:16px 10px 0;display:flex}.menu-group[data-v-095cc5a0]{flex-direction:column;gap:1px;display:flex}.menu-group-label[data-v-095cc5a0]{align-items:center;gap:8px;height:22px;margin-bottom:3px;padding:0 10px;display:flex}.menu-group-text[data-v-095cc5a0]{font-family:var(--font-mono);letter-spacing:.16em;text-transform:uppercase;color:var(--sider-ink-faint);flex:none;font-size:9.5px;font-weight:600}.menu-group-rule[data-v-095cc5a0]{background:linear-gradient(90deg, var(--divider-hair), transparent);flex:auto;height:1px}.menu-group-sep[data-v-095cc5a0]{background:var(--line-strong);width:18px;height:1px;margin:6px 0 6px 13px}.menu-item[data-v-095cc5a0]{width:100%;min-height:34px;font-family:var(--font-body);color:var(--sider-ink);text-align:left;cursor:pointer;border-radius:var(--radius-panel-sm);transition:background-color var(--transition-fast), color var(--transition-fast), padding-left var(--transition-fast), transform var(--transition-fast);background:0 0;border:0;align-items:center;padding:0 10px;font-size:13px;font-weight:500;display:flex;position:relative}@media (hover:hover) and (pointer:fine){.menu-item[data-v-095cc5a0]:hover{color:var(--ink);background:var(--paper-deep);padding-left:13px}}.menu-item[data-v-095cc5a0]:active{transform:scale(.985)}.menu-item.active[data-v-095cc5a0]{color:var(--accent-strong);background:var(--accent-soft);box-shadow:inset 2px 0 0 var(--accent);font-weight:600}.menu-item.active[data-v-095cc5a0]:hover{background:var(--tone-success-bg);padding-left:10px}.menu-icon[data-v-095cc5a0]{flex:0 0 20px;font-size:16px}.menu-item .menu-icon[data-v-095cc5a0]{color:var(--sider-ink-faint);transition:color var(--transition-fast)}.menu-item:hover .menu-icon[data-v-095cc5a0]{color:var(--ink)}.menu-item.active .menu-icon[data-v-095cc5a0]{color:var(--accent-strong)}.menu-label[data-v-095cc5a0]{white-space:nowrap;text-overflow:ellipsis;transition:opacity var(--transition-fast);padding-left:10px;overflow:hidden}.sider-footer[data-v-095cc5a0]{background:linear-gradient(180deg, transparent, var(--frost-bg) 42%);width:100%;padding:0 18px 18px;position:absolute;bottom:0;left:0}.footer-rule[data-v-095cc5a0]{background:repeating-linear-gradient(90deg, var(--tick-c-fine) 0 1px, transparent 1px 9px), var(--divider-hair);opacity:.9;height:1px;margin-bottom:12px}.footer-line[data-v-095cc5a0]{font-family:var(--font-mono);font-variant-numeric:tabular-nums;letter-spacing:.06em;color:var(--sider-ink-faint);align-items:center;gap:8px;font-size:10px;display:flex}.footer-line .sep[data-v-095cc5a0]{color:var(--ink-faint)}.slide-fade-enter-active[data-v-095cc5a0],.slide-fade-leave-active[data-v-095cc5a0]{transition:opacity .2s cubic-bezier(.22,1,.36,1),transform .2s cubic-bezier(.22,1,.36,1)}.slide-fade-enter-from[data-v-095cc5a0],.slide-fade-leave-to[data-v-095cc5a0]{opacity:0;transform:translate(-8px)}.app-header[data-v-1fa471c5]{height:var(--app-header-h,56px);border-bottom:1px solid var(--divider-hair);justify-content:space-between;align-items:center;padding:0 20px 0 10px;transition:background .3s,border-color .3s;display:flex;position:relative;overflow:hidden}.app-header-glass[data-v-1fa471c5]{z-index:30;background:var(--mat-chrome-bg);-webkit-backdrop-filter:var(--vibrancy-chrome);backdrop-filter:var(--vibrancy-chrome);border-bottom:1px solid var(--glass-line);box-shadow:var(--glass-specular);position:sticky;top:0}.header-left[data-v-1fa471c5],.header-right[data-v-1fa471c5]{align-items:center;gap:10px;min-width:0;display:flex}.rail-mark[data-v-1fa471c5]{color:var(--ink-faint);flex:none;font-size:15px}.aml-entry[data-v-1fa471c5]{flex:none;margin-right:2px}.trail[data-v-1fa471c5]{scrollbar-width:none;flex:0 auto;min-width:0;overflow:auto hidden;-webkit-mask-image:linear-gradient(90deg,#0000 0,#000 8px calc(100% - 18px),#0000);mask-image:linear-gradient(90deg,#0000 0,#000 8px calc(100% - 18px),#0000)}.trail[data-v-1fa471c5]::-webkit-scrollbar{display:none}.trail-row[data-v-1fa471c5]{white-space:nowrap;align-items:center;gap:0;padding:3px 4px;display:flex}.trail-link[data-v-1fa471c5]{background:var(--line-strong);flex:none;width:14px;height:1px}.trail-node[data-v-1fa471c5]{height:32px;font-family:var(--font-body);letter-spacing:.01em;color:var(--app-text,var(--ink-soft));cursor:pointer;background:var(--paper-deep);border:1px solid var(--line);border-radius:var(--radius-pill);transition:background var(--transition-fast), color var(--transition-fast), border-color var(--transition-fast);flex:none;align-items:center;gap:6px;padding:0 12px;font-size:12px;font-weight:500;display:inline-flex;position:relative}.trail-node[data-v-1fa471c5]:hover{color:var(--ink);background:var(--paper-tint);border-color:var(--line-strong)}.trail-node[data-v-1fa471c5]:active{transform:scale(.98)}.trail-node[data-v-1fa471c5]:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.trail-node.active[data-v-1fa471c5]{color:var(--on-accent);background:var(--accent);border-color:var(--accent)}.node-icon[data-v-1fa471c5]{font-size:13px}.node-title[data-v-1fa471c5]{letter-spacing:.02em;text-overflow:ellipsis;white-space:nowrap;max-width:132px;transition:max-width .18s var(--ease-out-quart), margin .18s var(--ease-out-quart), opacity .18s var(--ease-out-quart);overflow:hidden}.node-close[data-v-1fa471c5]{width:16px;height:16px;color:var(--ink-faint);cursor:pointer;border-radius:var(--radius-chip);opacity:0;transition:opacity .18s var(--ease-out-quart), transform .18s var(--ease-out-quart), color var(--transition-fast), background var(--transition-fast);background:0 0;border:none;flex:none;justify-content:center;align-items:center;margin-left:4px;font-size:12px;display:inline-flex;transform:scale(.6)}.trail-node:focus-within .node-close[data-v-1fa471c5],.trail-node:hover .node-close[data-v-1fa471c5]{opacity:1;transform:none}.node-close[data-v-1fa471c5]:hover{color:var(--ink);background:var(--hover-tint)}.node-close[data-v-1fa471c5]:active{transform:scale(.9)}.trail-node.active .node-close[data-v-1fa471c5]{color:color-mix(in srgb, var(--on-accent) 85%, transparent)}.trail-node.active .node-close[data-v-1fa471c5]:hover{color:var(--on-accent);background:color-mix(in srgb, var(--on-accent) 18%, transparent)}.node-close[data-v-1fa471c5]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.stamp-enter-active[data-v-1fa471c5]{transition:opacity .22s var(--ease-out-quart), transform .22s var(--ease-out-quart)}.stamp-enter-from[data-v-1fa471c5]{opacity:0;transform:translateY(4px)}.stamp-leave-active[data-v-1fa471c5]{transition:opacity .14s;position:absolute}.stamp-leave-to[data-v-1fa471c5]{opacity:0}.stamp-move[data-v-1fa471c5]{transition:transform .22s}.plotter-line[data-v-1fa471c5]{background:linear-gradient(90deg, transparent, var(--ink-fainter) 30%, var(--accent));opacity:0;pointer-events:none;transform-origin:0;width:100%;height:2px;position:absolute;bottom:-1px;left:0;transform:scaleX(0)}.plotter-line.run[data-v-1fa471c5]{animation:.6s cubic-bezier(.3,.8,.4,1) forwards plot-sweep-1fa471c5}@keyframes plot-sweep-1fa471c5{0%{opacity:.9;transform:scaleX(0)}70%{opacity:.9}to{opacity:0;transform:scaleX(1)}}.collapse-btn[data-v-1fa471c5],.icon-btn[data-v-1fa471c5]{width:34px;height:34px;color:var(--app-text,var(--ink-soft));cursor:pointer;border-radius:var(--radius-panel-sm);transition:background var(--transition-fast), color var(--transition-fast), transform .16s cubic-bezier(.22, 1, .36, 1);background:0 0;border:0;flex:none;justify-content:center;align-items:center;font-size:16px;display:inline-flex}.collapse-btn[data-v-1fa471c5]:hover,.icon-btn[data-v-1fa471c5]:hover{color:var(--ink);background:var(--paper-deep)}.collapse-btn[data-v-1fa471c5]:active,.icon-btn[data-v-1fa471c5]:active{transform:scale(.94)}.lang-select[data-v-1fa471c5]{width:118px}.lang-select[data-v-1fa471c5] .ant-select-selector{color:var(--app-text,var(--ink));border-color:var(--app-border,var(--line))!important;background:0 0!important}.lang-select[data-v-1fa471c5] .ant-select-arrow{color:var(--app-text-secondary,var(--ink-faint))}.user-chip[data-v-1fa471c5]{cursor:pointer;border-radius:var(--radius-pill);border:1px solid #0000;align-items:center;gap:10px;height:42px;margin-left:4px;padding:0 12px 0 8px;transition:border-color .16s,background .16s;display:flex}.user-chip[data-v-1fa471c5]:hover{border-color:var(--line);background:var(--hover-tint)}.user-initial[data-v-1fa471c5]{width:28px;height:28px;font-size:12px}.user-meta[data-v-1fa471c5]{flex-direction:column;line-height:1.15;display:flex}.user-name[data-v-1fa471c5]{color:var(--app-text,var(--ink));letter-spacing:.01em;font-size:12.5px;font-weight:600}.user-role[data-v-1fa471c5]{font-family:var(--font-mono);letter-spacing:.18em;text-transform:uppercase;color:var(--app-text-secondary,var(--ink-faint));font-size:8.5px}.hidden[data-v-1fa471c5]{display:none}.ws-dot[data-v-1fa471c5]{background:var(--tone-success-dot);width:8px;height:8px;box-shadow:0 0 6px color-mix(in srgb, var(--tone-success-dot) 55%, transparent);border-radius:50%;flex:none;margin:0 2px}.ws-dot.syncing[data-v-1fa471c5]{background:var(--tone-warning-dot);box-shadow:0 0 6px color-mix(in srgb, var(--tone-warning-dot) 55%, transparent);animation:1.2s ease-in-out infinite ws-pulse-1fa471c5}.ws-dot.down[data-v-1fa471c5]{background:var(--tone-danger-dot);box-shadow:0 0 6px color-mix(in srgb, var(--tone-danger-dot) 55%, transparent)}@keyframes ws-pulse-1fa471c5{50%{opacity:.45}}.hitl-bell[data-v-1fa471c5]{color:var(--tone-warning-dot,#d4a017);position:relative}.hitl-count[data-v-1fa471c5]{min-width:15px;height:15px;font-family:var(--font-mono);color:var(--on-accent,#fff);text-align:center;background:var(--tone-danger-dot,#e05252);border-radius:8px;padding:0 4px;font-size:9.5px;font-weight:700;line-height:15px;position:absolute;top:2px;right:2px}.hitl-menu[data-v-1fa471c5]{background:var(--paper,#fff);border:1px solid var(--line);border-radius:var(--radius-panel-sm,10px);min-width:260px;max-width:340px;padding:6px;box-shadow:0 10px 32px #00000024}.hitl-menu-title[data-v-1fa471c5]{letter-spacing:.08em;color:var(--ink-faint);border-bottom:1px solid var(--line);padding:6px 10px;font-size:11px;font-weight:600}.hitl-item[data-v-1fa471c5]{text-align:left;cursor:pointer;border-radius:var(--radius-panel-sm,8px);width:100%;transition:background var(--transition-fast), border-color var(--transition-fast);background:0 0;border:1px solid #0000;flex-direction:column;gap:3px;margin-top:4px;padding:8px 10px;display:flex}.hitl-item[data-v-1fa471c5]:hover{background:var(--paper-deep);border-color:var(--line)}.hitl-item-top[data-v-1fa471c5]{justify-content:space-between;align-items:baseline;gap:8px;display:flex}.hitl-item-agent[data-v-1fa471c5]{color:var(--ink);font-size:12.5px;font-weight:600}.hitl-item-kind[data-v-1fa471c5]{font-family:var(--font-mono);letter-spacing:.1em;color:var(--tone-warning-dot,#d4a017);font-size:9.5px}.hitl-item-title[data-v-1fa471c5]{color:var(--ink-soft);text-overflow:ellipsis;white-space:nowrap;font-size:12px;overflow:hidden}.hitl-item-actions[data-v-1fa471c5]{gap:6px;margin-top:6px;display:flex}@media (prefers-reduced-motion:reduce){.plotter-line.run[data-v-1fa471c5]{opacity:0;animation:none}.stamp-enter-active[data-v-1fa471c5],.stamp-leave-active[data-v-1fa471c5],.stamp-move[data-v-1fa471c5]{transition:none}}.app-layout[data-v-b48dd792]{background:0 0;flex-direction:row;min-height:100vh;display:flex}.app-main[data-v-b48dd792]{flex-direction:column;flex:auto;min-width:0;min-height:100vh;display:flex;position:relative}.app-content[data-v-b48dd792]{flex:1;margin:12px 16px 0;padding:2px}.app-footer[data-v-b48dd792]{background:var(--mat-chrome-bg);-webkit-backdrop-filter:var(--vibrancy-chrome);backdrop-filter:var(--vibrancy-chrome);border-top:1px solid var(--glass-line);box-shadow:var(--glass-specular);height:var(--app-footer-h);font-family:var(--font-mono);letter-spacing:.08em;text-align:center;justify-content:center;align-items:center;gap:10px;padding:0 50px;font-size:10.5px;display:flex}.app-footer .sep[data-v-b48dd792]{color:var(--ink-faint)}.footer-title[data-v-b48dd792]{font-size:13px}
|