@auto-ai/agent 2.1.183 → 2.1.187
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/dist/safe-a/404/index.html +1 -1
- package/dist/safe-a/404.html +1 -1
- package/dist/safe-a/_next/static/chunks/074a7a892d554827.js +1 -0
- package/dist/safe-a/_next/static/chunks/{e42498eec0c8d570.js → 0fde2a8866dd02fc.js} +1 -1
- package/dist/safe-a/_next/static/chunks/26f5809c84b263c0.css +7 -0
- package/dist/safe-a/_next/static/chunks/2ba468c7afb852bd.js +1 -0
- package/dist/safe-a/_next/static/chunks/{5434628aad5e5bc3.js → 2bac8f0a4e762326.js} +1 -1
- package/dist/safe-a/_next/static/chunks/{7f341bc0fb5ff708.js → 2d7f6aa6628bccd0.js} +1 -1
- package/dist/safe-a/_next/static/chunks/33678ff357855160.js +1 -0
- package/dist/safe-a/_next/static/chunks/5022180fa579a73a.js +1 -0
- package/dist/safe-a/_next/static/chunks/518d4c901787979a.js +1 -0
- package/dist/safe-a/_next/static/chunks/811897ffb3636359.js +1 -0
- package/dist/safe-a/_next/static/chunks/96feacf5b8cde310.js +1 -0
- package/dist/safe-a/_next/static/chunks/a56ab101155b1427.js +1 -0
- package/dist/safe-a/_next/static/chunks/a5b851b271052e89.js +1 -0
- package/dist/safe-a/_next/static/chunks/a6aafbc087d75717.js +1 -0
- package/dist/safe-a/_next/static/chunks/ceead8f438e931f7.js +1 -0
- package/dist/safe-a/_next/static/chunks/d16ae4f1eb111da5.js +1 -0
- package/dist/safe-a/_next/static/chunks/d47487bdc4a277fd.css +1 -0
- package/dist/safe-a/_next/static/chunks/e00679a7df05e016.js +1 -0
- package/dist/safe-a/_next/static/chunks/f1dde9052e8d1d3d.js +1 -0
- package/dist/safe-a/index.html +2 -2
- package/dist/safe-a/index.txt +26 -27
- package/dist/safe-a/manage/about/index.html +2 -2
- package/dist/safe-a/manage/about/index.txt +11 -11
- package/dist/safe-a/manage/env/index.html +2 -2
- package/dist/safe-a/manage/env/index.txt +13 -13
- package/dist/safe-a/manage/geelib/index.html +2 -2
- package/dist/safe-a/manage/geelib/index.txt +13 -13
- package/dist/safe-a/manage/general/index.html +2 -2
- package/dist/safe-a/manage/general/index.txt +11 -11
- package/dist/safe-a/manage/git/index.html +2 -2
- package/dist/safe-a/manage/git/index.txt +13 -13
- package/dist/safe-a/manage/im/index.html +2 -2
- package/dist/safe-a/manage/im/index.txt +13 -13
- package/dist/safe-a/manage/index.html +2 -2
- package/dist/safe-a/manage/index.txt +8 -8
- package/dist/safe-a/manage/library/index.html +2 -2
- package/dist/safe-a/manage/library/index.txt +11 -11
- package/dist/safe-a/manage/mcp/index.html +2 -2
- package/dist/safe-a/manage/mcp/index.txt +11 -11
- package/dist/safe-a/manage/permissions/index.html +2 -2
- package/dist/safe-a/manage/permissions/index.txt +11 -11
- package/dist/safe-a/manage/skills/index.html +2 -2
- package/dist/safe-a/manage/skills/index.txt +11 -11
- package/dist/safe-a/manage/system/index.html +2 -2
- package/dist/safe-a/manage/system/index.txt +13 -13
- package/dist/safe-a/manage/task/index.html +2 -2
- package/dist/safe-a/manage/task/index.txt +11 -11
- package/dist/safe-a/manage/teams/index.html +2 -2
- package/dist/safe-a/manage/teams/index.txt +11 -11
- package/dist/safe-a/manage/tools/index.html +2 -2
- package/dist/safe-a/manage/tools/index.txt +11 -11
- package/dist/ws-test/ws-test.css +89 -1
- package/dist/ws-test/ws-test.html +1 -0
- package/dist/ws-test/ws-test.js +276 -26
- package/mcps-runtime/claude-ws-channel/.mcp.json +18 -0
- package/mcps-runtime/claude-ws-channel/server/boot.mjs +30 -0
- package/mcps-runtime/claude-ws-channel/server/gateway.bundle.mjs +410306 -0
- package/mcps-runtime/claude-ws-channel/server/index.mjs +144 -0
- package/package.json +6 -6
- package/dist/safe-a/_next/static/chunks/044a195f3374d4b6.js +0 -1
- package/dist/safe-a/_next/static/chunks/0a7d5a51593d8c2f.js +0 -1
- package/dist/safe-a/_next/static/chunks/12fa90667e8fb0e3.js +0 -1
- package/dist/safe-a/_next/static/chunks/4682815462207a37.js +0 -1
- package/dist/safe-a/_next/static/chunks/5b44bdce5e5ebd06.js +0 -1
- package/dist/safe-a/_next/static/chunks/5b50a8c524507ee0.js +0 -1
- package/dist/safe-a/_next/static/chunks/66cdfa3e49dc50f3.js +0 -1
- package/dist/safe-a/_next/static/chunks/6b646b7144f0eb9e.js +0 -1
- package/dist/safe-a/_next/static/chunks/804376464cecbc36.css +0 -7
- package/dist/safe-a/_next/static/chunks/812fc979171f7ded.js +0 -1
- package/dist/safe-a/_next/static/chunks/8f31f818efd25c0f.js +0 -1
- package/dist/safe-a/_next/static/chunks/9edf76a11bf93bcc.js +0 -1
- package/dist/safe-a/_next/static/chunks/b63afdaa820ddad4.js +0 -1
- package/dist/safe-a/_next/static/chunks/b9590be9854a83fb.js +0 -1
- package/dist/safe-a/_next/static/chunks/dc7a9ce680ab0ce4.css +0 -1
- package/dist/safe-a/_next/static/chunks/dd98ccfeaf6ec72e.js +0 -1
- package/dist/safe-a/_next/static/chunks/e847138f5b487d3d.js +0 -1
- package/dist/safe-a/_next/static/chunks/f3c9f6b778f4cf1a.js +0 -1
- package/dist/safe-a/_next/static/chunks/fa686b4028e991a5.js +0 -1
- /package/dist/safe-a/_next/static/{yx70m3msfKAM3SckZNBAr → BDdAEI0K2Jg8YCxVKfY0_}/_buildManifest.js +0 -0
- /package/dist/safe-a/_next/static/{yx70m3msfKAM3SckZNBAr → BDdAEI0K2Jg8YCxVKfY0_}/_clientMiddlewareManifest.json +0 -0
- /package/dist/safe-a/_next/static/{yx70m3msfKAM3SckZNBAr → BDdAEI0K2Jg8YCxVKfY0_}/_ssgManifest.js +0 -0
package/dist/ws-test/ws-test.js
CHANGED
|
@@ -32,6 +32,9 @@
|
|
|
32
32
|
const promptFileSuggestions = $('promptFileSuggestions')
|
|
33
33
|
const composerUploadToast = $('composerUploadToast')
|
|
34
34
|
let composerUploadToastTimer = null
|
|
35
|
+
const debugNotifyStack = $('debugNotifyStack')
|
|
36
|
+
const DEBUG_NOTIFY_TTL_MS = 6000
|
|
37
|
+
const DEBUG_NOTIFY_MAX = 8
|
|
35
38
|
const btnNewSession = $('btnNewSession')
|
|
36
39
|
const btnSkillPackageManager = $('btnSkillPackageManager')
|
|
37
40
|
const btnEditAgentEnv = $('btnEditAgentEnv')
|
|
@@ -154,6 +157,10 @@
|
|
|
154
157
|
const mcpPackageImportInput = $('mcpPackageImportInput')
|
|
155
158
|
const sessionListEl = $('sessionList')
|
|
156
159
|
const sessionListMetaEl = $('sessionListMeta')
|
|
160
|
+
/** 侧栏会话列表运行时状态轮询定时器 */
|
|
161
|
+
let sessionRuntimePollTimer = null
|
|
162
|
+
/** 当前附着 session 的 turn 是否进行中(由 query.progress 驱动) */
|
|
163
|
+
let sessionTurnActive = false
|
|
157
164
|
const pendingPromptsBarEl = $('pendingPromptsBar')
|
|
158
165
|
const pendingPromptsListEl = $('pendingPromptsList')
|
|
159
166
|
let pendingPromptsCache = []
|
|
@@ -731,6 +738,11 @@
|
|
|
731
738
|
/** HTTP 历史回放进行中:暂存实时 conversation.delta,避免与回放竞态写乱 transcript 下标 */
|
|
732
739
|
let sessionReplayInProgress = false
|
|
733
740
|
const pendingConversationDeltaEnvelopes = []
|
|
741
|
+
/**
|
|
742
|
+
* 用户点击发送后、服务端 conversation.delta 到达前的本地回显。
|
|
743
|
+
* 业务语义:避免等待子进程 spawn / 路由期间聊天区无反馈。
|
|
744
|
+
*/
|
|
745
|
+
let pendingUserEcho = null
|
|
734
746
|
|
|
735
747
|
function sourceAgentPayloadToText(payload) {
|
|
736
748
|
if (!payload || typeof payload !== 'object') return ''
|
|
@@ -883,6 +895,41 @@
|
|
|
883
895
|
})
|
|
884
896
|
}
|
|
885
897
|
|
|
898
|
+
/** 发送 prompt 后立即在聊天区展示用户输入 */
|
|
899
|
+
function setPendingUserEcho(text) {
|
|
900
|
+
const trimmed = typeof text === 'string' ? text.trim() : ''
|
|
901
|
+
if (!trimmed) return
|
|
902
|
+
pendingUserEcho = {
|
|
903
|
+
text: trimmed,
|
|
904
|
+
sourceAgent: currentAgentParam(),
|
|
905
|
+
arrivalSeq: ++chatState.eventClock,
|
|
906
|
+
ts: new Date().toISOString(),
|
|
907
|
+
}
|
|
908
|
+
requestRenderChat()
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
function clearPendingUserEcho() {
|
|
912
|
+
if (!pendingUserEcho) return
|
|
913
|
+
pendingUserEcho = null
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
/** 渲染本地 pending 用户消息气泡(与 appendRunItemsToContainer 的 user 分支一致) */
|
|
917
|
+
function appendPendingUserEchoToContainer(container) {
|
|
918
|
+
if (!pendingUserEcho || !pendingUserEcho.text) return
|
|
919
|
+
const div = document.createElement('div')
|
|
920
|
+
div.className = 'chat-msg chat-msg-user chat-msg-pending-echo'
|
|
921
|
+
const lab = document.createElement('div')
|
|
922
|
+
lab.className = 'chat-msg-label'
|
|
923
|
+
lab.textContent = 'User · agent=' + pendingUserEcho.sourceAgent
|
|
924
|
+
const bodyEl = document.createElement('div')
|
|
925
|
+
bodyEl.className = 'chat-user-body'
|
|
926
|
+
setMessageBodyEl(bodyEl, pendingUserEcho.text)
|
|
927
|
+
div.appendChild(lab)
|
|
928
|
+
div.appendChild(bodyEl)
|
|
929
|
+
container.appendChild(div)
|
|
930
|
+
attachUserMessageCollapse(bodyEl)
|
|
931
|
+
}
|
|
932
|
+
|
|
886
933
|
if (typeof marked !== 'undefined' && marked.setOptions) {
|
|
887
934
|
marked.setOptions({ breaks: true, gfm: true })
|
|
888
935
|
}
|
|
@@ -1171,8 +1218,9 @@
|
|
|
1171
1218
|
}
|
|
1172
1219
|
|
|
1173
1220
|
if (nonToolBlocks.length > 0) {
|
|
1174
|
-
const
|
|
1175
|
-
|
|
1221
|
+
const rawBody = contentToPlainText(nonToolBlocks).trim()
|
|
1222
|
+
const unwrapped = unwrapChannelWrappedText(rawBody)
|
|
1223
|
+
if (unwrapped.body.trim()) {
|
|
1176
1224
|
units.push({
|
|
1177
1225
|
kind: 'message',
|
|
1178
1226
|
ev: ev,
|
|
@@ -1359,12 +1407,60 @@
|
|
|
1359
1407
|
return ''
|
|
1360
1408
|
}
|
|
1361
1409
|
|
|
1410
|
+
/**
|
|
1411
|
+
* 解析 channel 入站包裹:`<channel source="ws" ...>正文</channel>`。
|
|
1412
|
+
* 业务语义:与 wrapChannelMessage / ChannelManager.parseChannelMetaFromWrappedPrompt 同源,
|
|
1413
|
+
* 页面只展示正文,channel 元信息用于标签行。
|
|
1414
|
+
*/
|
|
1415
|
+
function unwrapChannelWrappedText(text) {
|
|
1416
|
+
const raw = typeof text === 'string' ? text : ''
|
|
1417
|
+
const matched = raw.match(/^<channel\s+([^>]+)>\s*([\s\S]*?)\s*<\/channel>\s*$/i)
|
|
1418
|
+
if (!matched) {
|
|
1419
|
+
return { body: raw, meta: null }
|
|
1420
|
+
}
|
|
1421
|
+
const attrs = matched[1] || ''
|
|
1422
|
+
const body = matched[2] != null ? String(matched[2]) : ''
|
|
1423
|
+
const meta = {}
|
|
1424
|
+
const attrRegex = /([a-zA-Z_][a-zA-Z0-9_]*)="([^"]*)"/g
|
|
1425
|
+
let am = null
|
|
1426
|
+
while ((am = attrRegex.exec(attrs)) !== null) {
|
|
1427
|
+
meta[am[1]] = am[2]
|
|
1428
|
+
}
|
|
1429
|
+
return { body: body, meta: meta }
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
/** channel 入站消息标签:channel_type/source + agent */
|
|
1433
|
+
function formatChannelInboundLabel(meta) {
|
|
1434
|
+
if (!meta || typeof meta !== 'object') return ''
|
|
1435
|
+
const parts = []
|
|
1436
|
+
const channelName = meta.channel_type || meta.source || ''
|
|
1437
|
+
if (channelName) parts.push(channelName)
|
|
1438
|
+
if (meta.agent) parts.push('agent=' + meta.agent)
|
|
1439
|
+
return parts.join(' · ')
|
|
1440
|
+
}
|
|
1441
|
+
|
|
1442
|
+
function getRawUserMessageText(m, contentBlocks) {
|
|
1443
|
+
if (contentBlocks) {
|
|
1444
|
+
return contentToPlainText(contentBlocks).trim()
|
|
1445
|
+
}
|
|
1446
|
+
if (!m || m.type !== 'user') return ''
|
|
1447
|
+
const inner = m.message
|
|
1448
|
+
if (inner && inner.content !== undefined) {
|
|
1449
|
+
return contentToPlainText(inner.content).trim()
|
|
1450
|
+
}
|
|
1451
|
+
return ''
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1362
1454
|
/**
|
|
1363
1455
|
* 与 messages.shouldShowUserMessage 一致:isMeta 为系统/Skill 注入,进模型但不展示。
|
|
1456
|
+
* channel 入站(正文含 <channel> 包裹)仍展示。
|
|
1364
1457
|
*/
|
|
1365
1458
|
function shouldShowWsUserMessage(m) {
|
|
1366
1459
|
if (!m || m.type !== 'user') return false
|
|
1367
|
-
if (m.isMeta === true)
|
|
1460
|
+
if (m.isMeta === true) {
|
|
1461
|
+
const raw = getRawUserMessageText(m, null)
|
|
1462
|
+
return unwrapChannelWrappedText(raw).meta != null
|
|
1463
|
+
}
|
|
1368
1464
|
return true
|
|
1369
1465
|
}
|
|
1370
1466
|
|
|
@@ -1373,7 +1469,13 @@
|
|
|
1373
1469
|
const t = m.type
|
|
1374
1470
|
if (t === 'user' || t === 'assistant') {
|
|
1375
1471
|
const inner = m.message
|
|
1376
|
-
if (inner && inner.content !== undefined)
|
|
1472
|
+
if (inner && inner.content !== undefined) {
|
|
1473
|
+
const plain = contentToPlainText(inner.content)
|
|
1474
|
+
if (t === 'user') {
|
|
1475
|
+
return unwrapChannelWrappedText(plain).body
|
|
1476
|
+
}
|
|
1477
|
+
return plain
|
|
1478
|
+
}
|
|
1377
1479
|
}
|
|
1378
1480
|
if (t === 'system' && typeof m.content === 'string') return m.content
|
|
1379
1481
|
return ''
|
|
@@ -1442,7 +1544,11 @@
|
|
|
1442
1544
|
)
|
|
1443
1545
|
})
|
|
1444
1546
|
if (nonTool.length > 0) {
|
|
1445
|
-
|
|
1547
|
+
const plain = contentToPlainText(nonTool).trim()
|
|
1548
|
+
if (m.type === 'user') {
|
|
1549
|
+
return unwrapChannelWrappedText(plain).body.trim()
|
|
1550
|
+
}
|
|
1551
|
+
return plain
|
|
1446
1552
|
}
|
|
1447
1553
|
return extractMessageBody(m).trim()
|
|
1448
1554
|
}
|
|
@@ -1501,16 +1607,24 @@
|
|
|
1501
1607
|
const t = unit.messageType
|
|
1502
1608
|
|
|
1503
1609
|
if (t === 'user') {
|
|
1504
|
-
const
|
|
1505
|
-
|
|
1506
|
-
|
|
1610
|
+
const rawUserText = getRawUserMessageText(m, unit.contentBlocks)
|
|
1611
|
+
const unwrapped = unwrapChannelWrappedText(rawUserText)
|
|
1612
|
+
const body = unwrapped.body.trim()
|
|
1507
1613
|
if (!body) continue
|
|
1614
|
+
const channelLabel = formatChannelInboundLabel(unwrapped.meta)
|
|
1508
1615
|
const div = document.createElement('div')
|
|
1509
|
-
div.className =
|
|
1616
|
+
div.className =
|
|
1617
|
+
'chat-msg chat-msg-user' +
|
|
1618
|
+
(channelLabel ? ' chat-msg-channel-inbound' : '')
|
|
1510
1619
|
applyScheduledMsgClass(div, isScheduled)
|
|
1511
1620
|
const lab = document.createElement('div')
|
|
1512
1621
|
lab.className = 'chat-msg-label'
|
|
1513
|
-
lab.textContent = formatScheduledLabel(
|
|
1622
|
+
lab.textContent = formatScheduledLabel(
|
|
1623
|
+
channelLabel
|
|
1624
|
+
? 'Channel · ' + channelLabel
|
|
1625
|
+
: 'User · agent=' + messageAgent,
|
|
1626
|
+
isScheduled,
|
|
1627
|
+
)
|
|
1514
1628
|
const bodyEl = document.createElement('div')
|
|
1515
1629
|
bodyEl.className = 'chat-user-body'
|
|
1516
1630
|
setMessageBodyEl(bodyEl, body)
|
|
@@ -1582,7 +1696,8 @@
|
|
|
1582
1696
|
const sourceAgentMessages = chatState.sourceAgentMessages
|
|
1583
1697
|
const shouldStickBottom = autoScrollState.mode === 'STICKY_BOTTOM' && isNearBottom(chatThreadEl)
|
|
1584
1698
|
chatThreadEl.innerHTML = ''
|
|
1585
|
-
const hasConversation =
|
|
1699
|
+
const hasConversation =
|
|
1700
|
+
runs.size > 0 || !!pendingUserEcho
|
|
1586
1701
|
if (!hasConversation && streamEntries.length === 0 && sourceAgentMessages.length === 0) {
|
|
1587
1702
|
chatThreadEl.innerHTML =
|
|
1588
1703
|
'<div class="chat-placeholder">连接后将在此展示对话(Markdown 渲染)</div>'
|
|
@@ -1757,6 +1872,12 @@
|
|
|
1757
1872
|
}
|
|
1758
1873
|
chatThreadEl.appendChild(groupContainer)
|
|
1759
1874
|
}
|
|
1875
|
+
if (pendingUserEcho) {
|
|
1876
|
+
const echoWrap = document.createElement('div')
|
|
1877
|
+
echoWrap.className = 'chat-run-group chat-run-group--pending-echo'
|
|
1878
|
+
appendPendingUserEchoToContainer(echoWrap)
|
|
1879
|
+
chatThreadEl.appendChild(echoWrap)
|
|
1880
|
+
}
|
|
1760
1881
|
if (streamEntries.length > 0) {
|
|
1761
1882
|
for (let i = 0; i < streamEntries.length; i++) {
|
|
1762
1883
|
const streamItem = streamEntries[i]
|
|
@@ -1798,6 +1919,7 @@
|
|
|
1798
1919
|
chatState.seenEventIds.clear()
|
|
1799
1920
|
sessionReplayInProgress = false
|
|
1800
1921
|
pendingConversationDeltaEnvelopes.length = 0
|
|
1922
|
+
pendingUserEcho = null
|
|
1801
1923
|
autoScrollState.mode = 'STICKY_BOTTOM'
|
|
1802
1924
|
if (logEl) logEl.textContent = ''
|
|
1803
1925
|
requestRenderChat()
|
|
@@ -1907,6 +2029,13 @@
|
|
|
1907
2029
|
arrivalSeq: ++chatState.eventClock,
|
|
1908
2030
|
}
|
|
1909
2031
|
applyConversationDeltaToRunBuffer(runBuffer, action, index, runMessage)
|
|
2032
|
+
if (
|
|
2033
|
+
msg &&
|
|
2034
|
+
msg.type === 'user' &&
|
|
2035
|
+
shouldShowWsUserMessage(msg)
|
|
2036
|
+
) {
|
|
2037
|
+
clearPendingUserEcho()
|
|
2038
|
+
}
|
|
1910
2039
|
requestRenderChat()
|
|
1911
2040
|
return true
|
|
1912
2041
|
}
|
|
@@ -1968,6 +2097,17 @@
|
|
|
1968
2097
|
// 回放边界控制事件:仅用于内部流程标记,不进入聊天消息区。
|
|
1969
2098
|
return true
|
|
1970
2099
|
}
|
|
2100
|
+
if (type === 'run.lifecycle' && payload.state === 'console') {
|
|
2101
|
+
const consoleMsg =
|
|
2102
|
+
typeof payload.message === 'string' ? payload.message.trim() : ''
|
|
2103
|
+
if (consoleMsg) {
|
|
2104
|
+
showDebugNotify(
|
|
2105
|
+
consoleMsg,
|
|
2106
|
+
typeof payload.level === 'string' ? payload.level : 'log',
|
|
2107
|
+
)
|
|
2108
|
+
}
|
|
2109
|
+
return true
|
|
2110
|
+
}
|
|
1971
2111
|
if (
|
|
1972
2112
|
type === 'run.lifecycle' &&
|
|
1973
2113
|
payload.state === 'teammateExit' &&
|
|
@@ -2027,12 +2167,15 @@
|
|
|
2027
2167
|
}
|
|
2028
2168
|
if (type === 'query.progress') {
|
|
2029
2169
|
const phase = typeof payload.phase === 'string' ? payload.phase : ''
|
|
2170
|
+
sessionTurnActive = !!(phase && phase !== 'idle')
|
|
2171
|
+
kickSessionRuntimePoll()
|
|
2030
2172
|
if (phase === 'idle') {
|
|
2031
2173
|
if (serverReady) setStatus('已就绪', 'ready')
|
|
2032
2174
|
// 一轮 prompt 收尾后 transcript 已落盘,刷新列表以更新页签 firstPrompt/summary
|
|
2033
|
-
void loadSessions()
|
|
2175
|
+
void loadSessions({ silent: true })
|
|
2034
2176
|
} else if (phase) {
|
|
2035
2177
|
setStatus('查询阶段: ' + phase + '…', '')
|
|
2178
|
+
void loadSessions({ silent: true })
|
|
2036
2179
|
}
|
|
2037
2180
|
return true
|
|
2038
2181
|
}
|
|
@@ -2124,10 +2267,36 @@
|
|
|
2124
2267
|
return null
|
|
2125
2268
|
}
|
|
2126
2269
|
|
|
2270
|
+
/**
|
|
2271
|
+
* 右上角通知:仅展示 warn(黄)、error(红);info/log 等蓝色类不弹窗。
|
|
2272
|
+
*/
|
|
2273
|
+
function showDebugNotify(message, level) {
|
|
2274
|
+
if (!debugNotifyStack) return
|
|
2275
|
+
const text = typeof message === 'string' ? message.trim() : ''
|
|
2276
|
+
if (!text) return
|
|
2277
|
+
const lvlRaw = typeof level === 'string' ? level.trim().toLowerCase() : 'log'
|
|
2278
|
+
if (lvlRaw !== 'warn' && lvlRaw !== 'error') return
|
|
2279
|
+
const lvl = lvlRaw === 'error' ? 'error' : 'warn'
|
|
2280
|
+
const item = document.createElement('div')
|
|
2281
|
+
item.className = 'debug-notify debug-notify--' + lvl
|
|
2282
|
+
item.setAttribute('role', 'status')
|
|
2283
|
+
item.textContent = text
|
|
2284
|
+
debugNotifyStack.appendChild(item)
|
|
2285
|
+
while (debugNotifyStack.children.length > DEBUG_NOTIFY_MAX) {
|
|
2286
|
+
debugNotifyStack.removeChild(debugNotifyStack.firstChild)
|
|
2287
|
+
}
|
|
2288
|
+
setTimeout(function () {
|
|
2289
|
+
if (item.parentNode === debugNotifyStack) {
|
|
2290
|
+
debugNotifyStack.removeChild(item)
|
|
2291
|
+
}
|
|
2292
|
+
}, DEBUG_NOTIFY_TTL_MS)
|
|
2293
|
+
}
|
|
2294
|
+
|
|
2127
2295
|
function logLine(type, obj) {
|
|
2128
|
-
if (!logEl) return
|
|
2129
2296
|
const t = new Date().toISOString().slice(11, 23)
|
|
2130
|
-
const line =
|
|
2297
|
+
const line =
|
|
2298
|
+
'[' + t + '] ' + type + ' ' + (typeof obj === 'string' ? obj : JSON.stringify(obj, null, 0))
|
|
2299
|
+
if (!logEl) return
|
|
2131
2300
|
logEl.textContent += line + '\n'
|
|
2132
2301
|
logEl.scrollTop = logEl.scrollHeight
|
|
2133
2302
|
}
|
|
@@ -4616,16 +4785,29 @@
|
|
|
4616
4785
|
const title = sessionTitle(s)
|
|
4617
4786
|
if (isActive) activeTitle = title
|
|
4618
4787
|
|
|
4788
|
+
const isRunning = s.running === true
|
|
4619
4789
|
const row = document.createElement('div')
|
|
4620
|
-
row.className =
|
|
4790
|
+
row.className =
|
|
4791
|
+
'sidebar-session-item' +
|
|
4792
|
+
(isActive ? ' active' : '') +
|
|
4793
|
+
(isRunning ? ' running' : '')
|
|
4621
4794
|
row.setAttribute('role', 'tab')
|
|
4622
4795
|
row.setAttribute('aria-selected', isActive ? 'true' : 'false')
|
|
4623
|
-
row.title = s.sessionId
|
|
4796
|
+
row.title = s.sessionId + (isRunning ? '(运行中)' : '')
|
|
4624
4797
|
|
|
4625
4798
|
const mainBtn = document.createElement('button')
|
|
4626
4799
|
mainBtn.type = 'button'
|
|
4627
4800
|
mainBtn.className = 'sidebar-session-main'
|
|
4628
|
-
|
|
4801
|
+
if (isRunning) {
|
|
4802
|
+
const runBadge = document.createElement('span')
|
|
4803
|
+
runBadge.className = 'sidebar-session-running-badge'
|
|
4804
|
+
runBadge.textContent = '运行中'
|
|
4805
|
+
mainBtn.appendChild(runBadge)
|
|
4806
|
+
}
|
|
4807
|
+
const titleSpan = document.createElement('span')
|
|
4808
|
+
titleSpan.className = 'sidebar-session-title'
|
|
4809
|
+
titleSpan.textContent = title
|
|
4810
|
+
mainBtn.appendChild(titleSpan)
|
|
4629
4811
|
mainBtn.addEventListener('click', function (ev) {
|
|
4630
4812
|
ev.stopPropagation()
|
|
4631
4813
|
switchToSession(s.sessionId)
|
|
@@ -4704,8 +4886,62 @@
|
|
|
4704
4886
|
return u.toString()
|
|
4705
4887
|
}
|
|
4706
4888
|
|
|
4889
|
+
/** 列表里是否存在运行中 session(子进程存活) */
|
|
4890
|
+
function sessionListHasRunning(sessions) {
|
|
4891
|
+
if (!Array.isArray(sessions)) return false
|
|
4892
|
+
return sessions.some(function (s) {
|
|
4893
|
+
return s && s.running === true
|
|
4894
|
+
})
|
|
4895
|
+
}
|
|
4896
|
+
|
|
4897
|
+
/** 轮询间隔:有运行中或本页 turn 时 1.5s,否则 4s */
|
|
4898
|
+
function sessionRuntimePollDelayMs() {
|
|
4899
|
+
if (sessionTurnActive || sessionListHasRunning(window.__lastSessions)) {
|
|
4900
|
+
return 1500
|
|
4901
|
+
}
|
|
4902
|
+
return 4000
|
|
4903
|
+
}
|
|
4904
|
+
|
|
4905
|
+
function stopSessionRuntimePoll() {
|
|
4906
|
+
if (sessionRuntimePollTimer != null) {
|
|
4907
|
+
clearTimeout(sessionRuntimePollTimer)
|
|
4908
|
+
sessionRuntimePollTimer = null
|
|
4909
|
+
}
|
|
4910
|
+
}
|
|
4911
|
+
|
|
4912
|
+
/**
|
|
4913
|
+
* 调度下一次会话列表运行时状态拉取。
|
|
4914
|
+
* 业务语义:侧栏「运行中」依赖主进程 RPC,不能仅靠当前 WS 事件;后台定时静默刷新。
|
|
4915
|
+
*/
|
|
4916
|
+
function scheduleSessionRuntimePoll() {
|
|
4917
|
+
stopSessionRuntimePoll()
|
|
4918
|
+
sessionRuntimePollTimer = setTimeout(function () {
|
|
4919
|
+
sessionRuntimePollTimer = null
|
|
4920
|
+
if (document.visibilityState === 'hidden') {
|
|
4921
|
+
scheduleSessionRuntimePoll()
|
|
4922
|
+
return
|
|
4923
|
+
}
|
|
4924
|
+
void loadSessions({ silent: true }).then(
|
|
4925
|
+
function () {
|
|
4926
|
+
scheduleSessionRuntimePoll()
|
|
4927
|
+
},
|
|
4928
|
+
function () {
|
|
4929
|
+
scheduleSessionRuntimePoll()
|
|
4930
|
+
},
|
|
4931
|
+
)
|
|
4932
|
+
}, sessionRuntimePollDelayMs())
|
|
4933
|
+
}
|
|
4934
|
+
|
|
4935
|
+
/** 立即按最新状态重置轮询节奏(例如 turn 开始/结束) */
|
|
4936
|
+
function kickSessionRuntimePoll() {
|
|
4937
|
+
scheduleSessionRuntimePoll()
|
|
4938
|
+
}
|
|
4939
|
+
|
|
4707
4940
|
async function loadSessions(options) {
|
|
4708
|
-
|
|
4941
|
+
const silent = !!(options && options.silent)
|
|
4942
|
+
if (!silent) {
|
|
4943
|
+
sessionListMetaEl.textContent = '加载中…'
|
|
4944
|
+
}
|
|
4709
4945
|
let data
|
|
4710
4946
|
try {
|
|
4711
4947
|
const r = await fetch(buildSessionsListUrl())
|
|
@@ -4713,12 +4949,14 @@
|
|
|
4713
4949
|
if (!r.ok) throw new Error(data.message || r.statusText)
|
|
4714
4950
|
} catch (e) {
|
|
4715
4951
|
const urlTried = buildSessionsListUrl()
|
|
4716
|
-
|
|
4717
|
-
|
|
4718
|
-
|
|
4719
|
-
|
|
4952
|
+
if (!silent) {
|
|
4953
|
+
const hint =
|
|
4954
|
+
'(https 页请求 http API 会被拦截。请求: ' + urlTried + ')'
|
|
4955
|
+
sessionListMetaEl.textContent = '加载失败: ' + e + hint
|
|
4956
|
+
sessionListEl.textContent = ''
|
|
4957
|
+
}
|
|
4720
4958
|
logLine('sessions', String(e) + ' url=' + urlTried)
|
|
4721
|
-
|
|
4959
|
+
throw e
|
|
4722
4960
|
}
|
|
4723
4961
|
const sessions = data.sessions || []
|
|
4724
4962
|
const dir =
|
|
@@ -4749,6 +4987,8 @@
|
|
|
4749
4987
|
socket = null
|
|
4750
4988
|
}
|
|
4751
4989
|
serverReady = false
|
|
4990
|
+
sessionTurnActive = false
|
|
4991
|
+
kickSessionRuntimePoll()
|
|
4752
4992
|
updateButtons()
|
|
4753
4993
|
}
|
|
4754
4994
|
|
|
@@ -4911,6 +5151,9 @@
|
|
|
4911
5151
|
if (!socket || socket.readyState !== WebSocket.OPEN) return
|
|
4912
5152
|
hidePromptFileSuggestions()
|
|
4913
5153
|
const text = getPromptPlainText()
|
|
5154
|
+
const trimmed = text.trim()
|
|
5155
|
+
if (!trimmed) return
|
|
5156
|
+
setPendingUserEcho(trimmed)
|
|
4914
5157
|
const payload = { type: 'prompt', text: text }
|
|
4915
5158
|
autoScrollState.mode = 'FORCE_ON_SEND'
|
|
4916
5159
|
socket.send(JSON.stringify(payload))
|
|
@@ -7021,9 +7264,8 @@
|
|
|
7021
7264
|
})
|
|
7022
7265
|
})
|
|
7023
7266
|
const buttons = [toggleBtn]
|
|
7024
|
-
|
|
7025
|
-
|
|
7026
|
-
}
|
|
7267
|
+
// 系统 skill 与 agent 导入 skill 均可编辑 SKILL.md;仅 agent 层支持保存
|
|
7268
|
+
buttons.push(createManageRowBtn('编辑', '', function () { openSkillMdModal(id) }))
|
|
7027
7269
|
if (canDelete) {
|
|
7028
7270
|
buttons.push(createManageRowBtn('导出', '', function () {
|
|
7029
7271
|
window.open(buildRuntimeSkillExportUrl(id), '_blank', 'noopener')
|
|
@@ -8478,10 +8720,18 @@
|
|
|
8478
8720
|
|
|
8479
8721
|
async function bootstrapSessionSelection() {
|
|
8480
8722
|
await loadSessions({ activateFirstIfEmpty: true })
|
|
8723
|
+
kickSessionRuntimePoll()
|
|
8481
8724
|
if (!sessionIdInput || sessionIdInput.value.trim()) return
|
|
8482
8725
|
switchToSession('')
|
|
8483
8726
|
}
|
|
8484
8727
|
|
|
8728
|
+
document.addEventListener('visibilitychange', function () {
|
|
8729
|
+
if (document.visibilityState !== 'hidden') {
|
|
8730
|
+
void loadSessions({ silent: true })
|
|
8731
|
+
}
|
|
8732
|
+
kickSessionRuntimePoll()
|
|
8733
|
+
})
|
|
8734
|
+
|
|
8485
8735
|
function onAgentChanged() {
|
|
8486
8736
|
updateBrandAgent()
|
|
8487
8737
|
rewriteSameOriginNavLinks()
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"mcpServers": {
|
|
3
|
+
"ws": {
|
|
4
|
+
"command": "bun",
|
|
5
|
+
"args": [
|
|
6
|
+
"${AGENT_PACKAGE_ROOT}/mcps-runtime/claude-ws-channel/server/boot.mjs"
|
|
7
|
+
],
|
|
8
|
+
"env": {
|
|
9
|
+
"WS_PORT": "${WS_PORT}",
|
|
10
|
+
"WS_MAIN_RPC_SOCKET": "${WS_MAIN_RPC_SOCKET}",
|
|
11
|
+
"WS_PROJECT_ROOT": "${WS_PROJECT_ROOT}",
|
|
12
|
+
"WS_AGENTS_ROOT": "${WS_AGENTS_ROOT}",
|
|
13
|
+
"WS_AGENT_NAME": "${WS_AGENT_NAME}",
|
|
14
|
+
"WS_STATE_DIR": "${WS_AGENTS_ROOT}/agent-runtime/${WS_AGENT_NAME}/channels/ws/.state"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { mkdirSync, appendFileSync } from 'node:fs'
|
|
2
|
+
import { dirname, join } from 'node:path'
|
|
3
|
+
import { homedir } from 'node:os'
|
|
4
|
+
|
|
5
|
+
const stateDir =
|
|
6
|
+
process.env.WS_STATE_DIR ||
|
|
7
|
+
join(homedir(), '.claude', 'channels', 'ws')
|
|
8
|
+
const bootLog = join(stateDir, 'boot.log')
|
|
9
|
+
mkdirSync(dirname(bootLog), { recursive: true })
|
|
10
|
+
|
|
11
|
+
function log(line) {
|
|
12
|
+
appendFileSync(bootLog, `${new Date().toISOString()} ${line}\n`, {
|
|
13
|
+
encoding: 'utf8',
|
|
14
|
+
mode: 0o600,
|
|
15
|
+
flag: 'a',
|
|
16
|
+
})
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
log(`[BOOT] ws-channel boot.mjs start pid=${process.pid}`)
|
|
20
|
+
log(`[BOOT] WS_PORT=${process.env.WS_PORT || ''} WS_MAIN_RPC_SOCKET=${process.env.WS_MAIN_RPC_SOCKET || ''}`)
|
|
21
|
+
|
|
22
|
+
process.on('uncaughtException', err => {
|
|
23
|
+
log(`[BOOT] uncaughtException ${err?.stack || err}`)
|
|
24
|
+
})
|
|
25
|
+
process.on('unhandledRejection', err => {
|
|
26
|
+
log(`[BOOT] unhandledRejection ${err?.stack || err}`)
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
await import('./index.mjs')
|
|
30
|
+
log('[BOOT] imported index.mjs successfully')
|