@auto-ai/agent 2.1.220 → 2.1.222
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/index.html +2 -2
- package/dist/safe-a/index.txt +1 -1
- package/dist/safe-a/manage/about/index.html +2 -2
- package/dist/safe-a/manage/about/index.txt +1 -1
- package/dist/safe-a/manage/env/index.html +2 -2
- package/dist/safe-a/manage/env/index.txt +1 -1
- package/dist/safe-a/manage/geelib/index.html +2 -2
- package/dist/safe-a/manage/geelib/index.txt +1 -1
- package/dist/safe-a/manage/general/index.html +2 -2
- package/dist/safe-a/manage/general/index.txt +1 -1
- package/dist/safe-a/manage/git/index.html +2 -2
- package/dist/safe-a/manage/git/index.txt +1 -1
- package/dist/safe-a/manage/im/index.html +2 -2
- package/dist/safe-a/manage/im/index.txt +1 -1
- package/dist/safe-a/manage/index.html +2 -2
- package/dist/safe-a/manage/index.txt +1 -1
- package/dist/safe-a/manage/library/index.html +2 -2
- package/dist/safe-a/manage/library/index.txt +1 -1
- package/dist/safe-a/manage/mcp/index.html +2 -2
- package/dist/safe-a/manage/mcp/index.txt +1 -1
- package/dist/safe-a/manage/permissions/index.html +2 -2
- package/dist/safe-a/manage/permissions/index.txt +1 -1
- package/dist/safe-a/manage/skills/index.html +2 -2
- package/dist/safe-a/manage/skills/index.txt +1 -1
- package/dist/safe-a/manage/task/index.html +2 -2
- package/dist/safe-a/manage/task/index.txt +1 -1
- package/dist/safe-a/manage/teams/index.html +2 -2
- package/dist/safe-a/manage/teams/index.txt +1 -1
- package/dist/safe-a/manage/tools/index.html +2 -2
- package/dist/safe-a/manage/tools/index.txt +1 -1
- package/dist/ws-test/agent-teams.html +1400 -0
- package/dist/ws-test/team-chat.js +760 -0
- package/dist/ws-test/ws-test.css +613 -6
- package/dist/ws-test/ws-test.html +23 -7
- package/dist/ws-test/ws-test.js +303 -86
- package/mcps-runtime/claude-tuitui-channel/server/index.mjs +5 -0
- package/package.json +6 -6
- package/tools-runtime/git-tool/index.cjs +32 -31
- package/tools-runtime/git-tool/src/workspace.ts +42 -5
- package/tools-runtime/git-tool/src/wsInit.ts +13 -2
- /package/dist/safe-a/_next/static/{tLBo5EqCFXrKR3ERjvMIi → O9azldpveh8Nr32O4nBb7}/_buildManifest.js +0 -0
- /package/dist/safe-a/_next/static/{tLBo5EqCFXrKR3ERjvMIi → O9azldpveh8Nr32O4nBb7}/_clientMiddlewareManifest.json +0 -0
- /package/dist/safe-a/_next/static/{tLBo5EqCFXrKR3ERjvMIi → O9azldpveh8Nr32O4nBb7}/_ssgManifest.js +0 -0
package/dist/ws-test/ws-test.js
CHANGED
|
@@ -167,6 +167,63 @@
|
|
|
167
167
|
const mcpPackageImportInput = $('mcpPackageImportInput')
|
|
168
168
|
const sessionListEl = $('sessionList')
|
|
169
169
|
const sessionListMetaEl = $('sessionListMeta')
|
|
170
|
+
/** 侧栏会话来源:ws / tuitui / geelib / team / legacy */
|
|
171
|
+
var SESSION_KIND_LABELS = {
|
|
172
|
+
ws: '网页',
|
|
173
|
+
tuitui: '推推',
|
|
174
|
+
geelib: 'GeeLib',
|
|
175
|
+
team: '群聊',
|
|
176
|
+
legacy: '会话',
|
|
177
|
+
}
|
|
178
|
+
function resolveSessionKindForItem(s) {
|
|
179
|
+
if (!s || typeof s !== 'object') return 'ws'
|
|
180
|
+
var kind = s.sessionKind
|
|
181
|
+
if (kind && SESSION_KIND_LABELS[kind]) return kind
|
|
182
|
+
if (kind === 'user') return 'ws'
|
|
183
|
+
var sid = typeof s.sessionId === 'string' ? s.sessionId : ''
|
|
184
|
+
if (sid.indexOf('team-') === 0) return 'team'
|
|
185
|
+
if (sid.indexOf('tuitui-') === 0) return 'tuitui'
|
|
186
|
+
if (sid.indexOf('geelib-') === 0) return 'geelib'
|
|
187
|
+
if (sid.indexOf('ws-') === 0) return 'ws'
|
|
188
|
+
return 'legacy'
|
|
189
|
+
}
|
|
190
|
+
var SESSION_KIND_ICON_SVG = {
|
|
191
|
+
ws:
|
|
192
|
+
'<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">' +
|
|
193
|
+
'<rect x="3" y="4" width="18" height="14" rx="2"/>' +
|
|
194
|
+
'<path d="M8 20h8"/>' +
|
|
195
|
+
'</svg>',
|
|
196
|
+
tuitui:
|
|
197
|
+
'<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">' +
|
|
198
|
+
'<path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/>' +
|
|
199
|
+
'<path d="M13.73 21a2 2 0 0 1-3.46 0"/>' +
|
|
200
|
+
'</svg>',
|
|
201
|
+
geelib:
|
|
202
|
+
'<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">' +
|
|
203
|
+
'<path d="M4 4h16v16H4z"/>' +
|
|
204
|
+
'<path d="M4 9h16M9 4v16"/>' +
|
|
205
|
+
'</svg>',
|
|
206
|
+
team:
|
|
207
|
+
'<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">' +
|
|
208
|
+
'<circle cx="8" cy="8" r="2.8"/>' +
|
|
209
|
+
'<circle cx="16.2" cy="9.2" r="2.4"/>' +
|
|
210
|
+
'<path d="M3.2 18c.8-2.7 2.8-4.2 4.8-4.2s4 1.5 4.8 4.2"/>' +
|
|
211
|
+
'<path d="M13.2 18c.6-2 2.2-3.2 4-3.2 1.6 0 3.1 1 3.8 2.7"/>' +
|
|
212
|
+
'</svg>',
|
|
213
|
+
legacy:
|
|
214
|
+
'<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">' +
|
|
215
|
+
'<path d="M21 11.5a8.4 8.4 0 0 1-9 8.4 8.4 8.4 0 0 1-3.8-.9L3 20l1.9-5.2A8.4 8.4 0 1 1 21 11.5z"/>' +
|
|
216
|
+
'</svg>',
|
|
217
|
+
}
|
|
218
|
+
function createSessionKindIcon(kind) {
|
|
219
|
+
var resolved = SESSION_KIND_LABELS[kind] ? kind : 'ws'
|
|
220
|
+
var icon = document.createElement('span')
|
|
221
|
+
icon.className = 'sidebar-session-kind-icon sidebar-session-kind-icon--' + resolved
|
|
222
|
+
icon.setAttribute('aria-hidden', 'true')
|
|
223
|
+
icon.title = SESSION_KIND_LABELS[resolved]
|
|
224
|
+
icon.innerHTML = SESSION_KIND_ICON_SVG[resolved]
|
|
225
|
+
return icon
|
|
226
|
+
}
|
|
170
227
|
/** 侧栏会话列表运行时状态轮询定时器 */
|
|
171
228
|
let sessionRuntimePollTimer = null
|
|
172
229
|
/** 当前附着 session 的 turn 是否进行中(由 query.progress 驱动) */
|
|
@@ -280,18 +337,21 @@
|
|
|
280
337
|
const composerToolAskSelect = $('composerToolAskSelect')
|
|
281
338
|
const btnSaveAgentConfig = $('btnSaveAgentConfig')
|
|
282
339
|
const pickerManageView = $('pickerManageView')
|
|
283
|
-
const pickerNavPanel = $('pickerNavPanel')
|
|
284
|
-
const pickerNavList = $('pickerNavList')
|
|
285
340
|
const pickerSearch = $('pickerSearch')
|
|
286
341
|
const btnPickerMcpJson = $('btnPickerMcpJson')
|
|
287
342
|
const btnPickerImport = $('btnPickerImport')
|
|
343
|
+
const btnPickerSkillStore = $('btnPickerSkillStore')
|
|
288
344
|
const btnPickerCancel = $('btnPickerCancel')
|
|
289
345
|
const btnPickerSave = $('btnPickerSave')
|
|
290
346
|
const pickerEntriesTable = $('pickerEntriesTable')
|
|
291
347
|
const pickerTableHeadRow = $('pickerTableHeadRow')
|
|
292
348
|
const pickerEntriesBody = $('pickerEntriesBody')
|
|
293
|
-
const pickerCloudPanel = $('pickerCloudPanel')
|
|
294
349
|
const pickerContentState = $('pickerContentState')
|
|
350
|
+
const skillStoreModal = $('skillStoreModal')
|
|
351
|
+
const skillStoreModalBackdrop = $('skillStoreModalBackdrop')
|
|
352
|
+
const skillStoreModalBody = $('skillStoreModalBody')
|
|
353
|
+
const btnSkillStoreModalClose = $('btnSkillStoreModalClose')
|
|
354
|
+
const btnSkillStoreClose = $('btnSkillStoreClose')
|
|
295
355
|
const pickerImportInput = $('pickerImportInput')
|
|
296
356
|
const mcpJsonInputModal = $('mcpJsonInputModal')
|
|
297
357
|
const mcpJsonInputModalBackdrop = $('mcpJsonInputModalBackdrop')
|
|
@@ -362,6 +422,7 @@
|
|
|
362
422
|
let refreshToolPickerRows = null
|
|
363
423
|
let refreshMcpPickerRows = null
|
|
364
424
|
let refreshSkillPickerRows = null
|
|
425
|
+
let openSkillStoreModalFn = null
|
|
365
426
|
let pickerRenderContent = null
|
|
366
427
|
let remoteMcpServers = []
|
|
367
428
|
const WS_PERMISSION_MODE_KEY = 'WS_PERMISSION_MODE'
|
|
@@ -720,6 +781,8 @@
|
|
|
720
781
|
let renderScheduled = false
|
|
721
782
|
/** HTTP 历史回放进行中:暂存实时 conversation.delta,避免与回放竞态写乱 transcript 下标 */
|
|
722
783
|
let sessionReplayInProgress = false
|
|
784
|
+
/** 递增以作废进行中的 HTTP 历史回放,避免快速切换 session 时旧内容回填 */
|
|
785
|
+
let hydrateSessionGeneration = 0
|
|
723
786
|
const pendingConversationDeltaEnvelopes = []
|
|
724
787
|
/**
|
|
725
788
|
* 用户点击发送后、服务端 conversation.delta 到达前的本地回显。
|
|
@@ -767,6 +830,7 @@
|
|
|
767
830
|
source: source,
|
|
768
831
|
runId: runId,
|
|
769
832
|
correlationId: correlationId,
|
|
833
|
+
turnId: typeof item.turnId === 'string' ? item.turnId : '',
|
|
770
834
|
text: body,
|
|
771
835
|
status: status,
|
|
772
836
|
scheduledTrigger: item.scheduledTrigger === true,
|
|
@@ -1500,6 +1564,84 @@
|
|
|
1500
1564
|
bodyEl.insertAdjacentElement('afterend', btn)
|
|
1501
1565
|
}
|
|
1502
1566
|
|
|
1567
|
+
/**
|
|
1568
|
+
* 业务语义:HTTP 回放/初始化 turnId 为 replay|init,需按 user 消息再切分;
|
|
1569
|
+
* 实时 turn 每轮 prompt 有独立 UUID turnId,直接按 turnId 分组。
|
|
1570
|
+
*/
|
|
1571
|
+
function shouldSplitTurnOnUserMessage(turnId) {
|
|
1572
|
+
const tid = typeof turnId === 'string' ? turnId.trim() : ''
|
|
1573
|
+
return !tid || tid === 'replay' || tid === 'init'
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1576
|
+
function isRealUserPromptMessage(m) {
|
|
1577
|
+
if (!m || m.type !== 'user') return false
|
|
1578
|
+
if (!shouldShowWsUserMessage(m)) return false
|
|
1579
|
+
const blocks = getMessageContentBlocks(m)
|
|
1580
|
+
const nonToolBlocks = blocks.filter(function (b) {
|
|
1581
|
+
return b && b.type !== 'tool_result'
|
|
1582
|
+
})
|
|
1583
|
+
if (nonToolBlocks.length === 0) return false
|
|
1584
|
+
const rawBody = contentToPlainText(nonToolBlocks).trim()
|
|
1585
|
+
return !!unwrapChannelWrappedText(rawBody).body.trim()
|
|
1586
|
+
}
|
|
1587
|
+
|
|
1588
|
+
function isTimelineUserTurnStart(ev) {
|
|
1589
|
+
if (!ev || ev.kind !== 'conversation') return false
|
|
1590
|
+
const item = ev.payload
|
|
1591
|
+
const m = item && item.message
|
|
1592
|
+
return isRealUserPromptMessage(m)
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1595
|
+
function isToolResultOnlyEvent(ev) {
|
|
1596
|
+
if (!ev || ev.kind !== 'conversation') return false
|
|
1597
|
+
const m = ev.payload && ev.payload.message
|
|
1598
|
+
if (!m || m.type !== 'user') return false
|
|
1599
|
+
const blocks = getMessageContentBlocks(m)
|
|
1600
|
+
if (!blocks.length) return false
|
|
1601
|
+
return blocks.every(function (b) {
|
|
1602
|
+
return b && b.type === 'tool_result'
|
|
1603
|
+
})
|
|
1604
|
+
}
|
|
1605
|
+
|
|
1606
|
+
function coalesceToolResultTurns(turns) {
|
|
1607
|
+
for (let i = 1; i < turns.length; i++) {
|
|
1608
|
+
const turn = turns[i]
|
|
1609
|
+
if (turn.items.length > 0 && turn.items.every(isToolResultOnlyEvent)) {
|
|
1610
|
+
turns[i - 1].items.push.apply(turns[i - 1].items, turn.items)
|
|
1611
|
+
turns.splice(i, 1)
|
|
1612
|
+
i -= 1
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
return turns
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1618
|
+
function groupItemsByTurn(blockItems) {
|
|
1619
|
+
const turns = []
|
|
1620
|
+
for (let i = 0; i < blockItems.length; i++) {
|
|
1621
|
+
const ev = blockItems[i]
|
|
1622
|
+
const turnId = typeof ev.turnId === 'string' ? ev.turnId.trim() : ''
|
|
1623
|
+
const splitOnUser = shouldSplitTurnOnUserMessage(turnId)
|
|
1624
|
+
const isUserStart = splitOnUser && isTimelineUserTurnStart(ev)
|
|
1625
|
+
let targetTurn = turns.length > 0 ? turns[turns.length - 1] : null
|
|
1626
|
+
|
|
1627
|
+
if (splitOnUser) {
|
|
1628
|
+
if (isUserStart || !targetTurn) {
|
|
1629
|
+
targetTurn = { turnId: turnId || 'unknown', items: [] }
|
|
1630
|
+
turns.push(targetTurn)
|
|
1631
|
+
}
|
|
1632
|
+
targetTurn.items.push(ev)
|
|
1633
|
+
continue
|
|
1634
|
+
}
|
|
1635
|
+
|
|
1636
|
+
if (!targetTurn || targetTurn.turnId !== turnId) {
|
|
1637
|
+
targetTurn = { turnId: turnId, items: [] }
|
|
1638
|
+
turns.push(targetTurn)
|
|
1639
|
+
}
|
|
1640
|
+
targetTurn.items.push(ev)
|
|
1641
|
+
}
|
|
1642
|
+
return coalesceToolResultTurns(turns)
|
|
1643
|
+
}
|
|
1644
|
+
|
|
1503
1645
|
function renderChat() {
|
|
1504
1646
|
/**
|
|
1505
1647
|
* 业务语义:run 折叠头需要展示“最后一条消息前三行”预览。
|
|
@@ -1714,6 +1856,7 @@
|
|
|
1714
1856
|
Number.isInteger(item.arrivalSeq) ? item.arrivalSeq : Number.MAX_SAFE_INTEGER,
|
|
1715
1857
|
fallbackOrder: timelineFallbackOrder++,
|
|
1716
1858
|
runId: runId,
|
|
1859
|
+
turnId: typeof item.turnId === 'string' ? item.turnId : '',
|
|
1717
1860
|
sourceAgent: resolveRunDisplayAgent(runId, item.sourceAgent),
|
|
1718
1861
|
scheduledTrigger: item.scheduledTrigger === true,
|
|
1719
1862
|
kind: 'conversation',
|
|
@@ -1734,6 +1877,7 @@
|
|
|
1734
1877
|
Number.isInteger(item.arrivalSeq) ? item.arrivalSeq : Number.MAX_SAFE_INTEGER,
|
|
1735
1878
|
fallbackOrder: timelineFallbackOrder++,
|
|
1736
1879
|
runId: rid,
|
|
1880
|
+
turnId: typeof item.turnId === 'string' ? item.turnId : '',
|
|
1737
1881
|
sourceAgent: resolveRunDisplayAgent(rid, item.source),
|
|
1738
1882
|
scheduledTrigger: item.scheduledTrigger === true,
|
|
1739
1883
|
kind: 'source',
|
|
@@ -1822,16 +1966,24 @@
|
|
|
1822
1966
|
const groupContainer = document.createElement('div')
|
|
1823
1967
|
groupContainer.className = 'chat-run-group' + (blockAllScheduled ? ' chat-run-group--scheduled' : '')
|
|
1824
1968
|
if (runId === 'main') {
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1969
|
+
groupContainer.classList.add('chat-run-group--main')
|
|
1970
|
+
const turnGroups = groupItemsByTurn(blockItems)
|
|
1971
|
+
for (let t = 0; t < turnGroups.length; t++) {
|
|
1972
|
+
const turn = turnGroups[t]
|
|
1973
|
+
if (!turn.items.length) continue
|
|
1974
|
+
const isLastTurn = t === turnGroups.length - 1
|
|
1975
|
+
const isActiveTurn = isLastTurn && sessionTurnActive
|
|
1976
|
+
const turnSection = document.createElement('section')
|
|
1977
|
+
turnSection.className =
|
|
1978
|
+
'chat-turn' +
|
|
1979
|
+
(isActiveTurn ? ' chat-turn--active' : '') +
|
|
1980
|
+
(blockAllScheduled ? ' chat-turn--scheduled' : '')
|
|
1981
|
+
const turnBody = document.createElement('div')
|
|
1982
|
+
turnBody.className = 'chat-turn-body'
|
|
1983
|
+
appendRunItemsToContainer(turnBody, turn.items, runId, defaultSourceAgent)
|
|
1984
|
+
turnSection.appendChild(turnBody)
|
|
1985
|
+
groupContainer.appendChild(turnSection)
|
|
1986
|
+
}
|
|
1835
1987
|
} else {
|
|
1836
1988
|
const summaryCard = document.createElement('div')
|
|
1837
1989
|
summaryCard.className =
|
|
@@ -1865,9 +2017,12 @@
|
|
|
1865
2017
|
chatThreadEl.appendChild(groupContainer)
|
|
1866
2018
|
}
|
|
1867
2019
|
if (pendingUserEcho) {
|
|
1868
|
-
const echoWrap = document.createElement('
|
|
1869
|
-
echoWrap.className = 'chat-
|
|
1870
|
-
|
|
2020
|
+
const echoWrap = document.createElement('section')
|
|
2021
|
+
echoWrap.className = 'chat-turn chat-turn--active chat-turn--pending-echo'
|
|
2022
|
+
const echoBody = document.createElement('div')
|
|
2023
|
+
echoBody.className = 'chat-turn-body'
|
|
2024
|
+
appendPendingUserEchoToContainer(echoBody)
|
|
2025
|
+
echoWrap.appendChild(echoBody)
|
|
1871
2026
|
chatThreadEl.appendChild(echoWrap)
|
|
1872
2027
|
}
|
|
1873
2028
|
if (streamEntries.length > 0) {
|
|
@@ -2163,6 +2318,7 @@
|
|
|
2163
2318
|
const runMessage = {
|
|
2164
2319
|
message: msg,
|
|
2165
2320
|
sourceAgent: sourceAgent,
|
|
2321
|
+
turnId: typeof data.turnId === 'string' ? data.turnId : '',
|
|
2166
2322
|
scheduledTrigger: payload.scheduledTrigger === true,
|
|
2167
2323
|
ts:
|
|
2168
2324
|
typeof data.ts === 'string' && data.ts
|
|
@@ -2205,6 +2361,7 @@
|
|
|
2205
2361
|
source: source,
|
|
2206
2362
|
runId: runId,
|
|
2207
2363
|
correlationId: corr,
|
|
2364
|
+
turnId: typeof data.turnId === 'string' ? data.turnId : '',
|
|
2208
2365
|
status: payload.status === 'resolved' ? 'resolved' : 'failed',
|
|
2209
2366
|
text: text,
|
|
2210
2367
|
scheduledTrigger: payload.scheduledTrigger === true,
|
|
@@ -2286,6 +2443,7 @@
|
|
|
2286
2443
|
source: source,
|
|
2287
2444
|
runId: runId,
|
|
2288
2445
|
correlationId: '',
|
|
2446
|
+
turnId: typeof data.turnId === 'string' ? data.turnId : '',
|
|
2289
2447
|
status: type === 'session.error' ? 'failed' : 'resolved',
|
|
2290
2448
|
text: payloadText,
|
|
2291
2449
|
key: typeof data.eventId === 'string' ? data.eventId : '',
|
|
@@ -2307,6 +2465,17 @@
|
|
|
2307
2465
|
if (payload.agent) updateBrandAgent(payload.agent)
|
|
2308
2466
|
setStatus('已就绪', 'ready')
|
|
2309
2467
|
void loadPendingPrompts()
|
|
2468
|
+
const mc =
|
|
2469
|
+
typeof payload.messageCount === 'number' ? payload.messageCount : 0
|
|
2470
|
+
const sid =
|
|
2471
|
+
typeof payload.sessionId === 'string' && payload.sessionId.trim()
|
|
2472
|
+
? payload.sessionId.trim()
|
|
2473
|
+
: sessionIdInput.value.trim()
|
|
2474
|
+
if (mc === 0) {
|
|
2475
|
+
resetChatUi()
|
|
2476
|
+
} else if (sid) {
|
|
2477
|
+
void hydrateSessionHistoryFromHttp(sid)
|
|
2478
|
+
}
|
|
2310
2479
|
return true
|
|
2311
2480
|
}
|
|
2312
2481
|
if (type === 'session.meta') {
|
|
@@ -2356,6 +2525,7 @@
|
|
|
2356
2525
|
}
|
|
2357
2526
|
void loadSessions({ silent: true })
|
|
2358
2527
|
}
|
|
2528
|
+
requestRenderChat()
|
|
2359
2529
|
return true
|
|
2360
2530
|
}
|
|
2361
2531
|
if (type === 'session.error') {
|
|
@@ -2626,6 +2796,60 @@
|
|
|
2626
2796
|
return u.toString()
|
|
2627
2797
|
}
|
|
2628
2798
|
|
|
2799
|
+
/**
|
|
2800
|
+
* HTTP replay 信封中需跳过的类型:replay.start 会把 serverReady 置 false 并重新打开全屏 loading。
|
|
2801
|
+
*/
|
|
2802
|
+
function shouldSkipHttpReplayEnvelope(ev) {
|
|
2803
|
+
if (!ev || typeof ev !== 'object') return true
|
|
2804
|
+
const replayType = typeof ev.type === 'string' ? ev.type : ''
|
|
2805
|
+
if (replayType === 'history.replay') return true
|
|
2806
|
+
if (replayType !== 'run.lifecycle') return false
|
|
2807
|
+
const payload = ev.data && typeof ev.data === 'object' ? ev.data : {}
|
|
2808
|
+
const state = typeof payload.state === 'string' ? payload.state : ''
|
|
2809
|
+
return state === 'replay.start' || state === 'replay.end'
|
|
2810
|
+
}
|
|
2811
|
+
|
|
2812
|
+
/**
|
|
2813
|
+
* meta-only snapshot 后异步拉 HTTP replay 补全聊天区,不阻塞 session.ready 与 prompt 发送。
|
|
2814
|
+
*/
|
|
2815
|
+
async function hydrateSessionHistoryFromHttp(sessionId) {
|
|
2816
|
+
const sid = typeof sessionId === 'string' ? sessionId.trim() : ''
|
|
2817
|
+
if (!sid) return
|
|
2818
|
+
const generation = hydrateSessionGeneration
|
|
2819
|
+
const wasReady = serverReady
|
|
2820
|
+
try {
|
|
2821
|
+
resetChatUi()
|
|
2822
|
+
sessionReplayInProgress = true
|
|
2823
|
+
pendingConversationDeltaEnvelopes.length = 0
|
|
2824
|
+
const r = await fetch(buildSessionReplayUrl(sid))
|
|
2825
|
+
if (generation !== hydrateSessionGeneration) return
|
|
2826
|
+
if (!r.ok) {
|
|
2827
|
+
logLine('error', 'hydrateSessionHistoryFromHttp: HTTP ' + r.status)
|
|
2828
|
+
return
|
|
2829
|
+
}
|
|
2830
|
+
const data = await r.json()
|
|
2831
|
+
const envelopes = Array.isArray(data.envelopes) ? data.envelopes : []
|
|
2832
|
+
for (let i = 0; i < envelopes.length; i++) {
|
|
2833
|
+
if (generation !== hydrateSessionGeneration) return
|
|
2834
|
+
const ev = envelopes[i]
|
|
2835
|
+
if (shouldSkipHttpReplayEnvelope(ev)) continue
|
|
2836
|
+
applyWsEnvelopeV3(ev)
|
|
2837
|
+
}
|
|
2838
|
+
} catch (e) {
|
|
2839
|
+
logLine('error', 'hydrateSessionHistoryFromHttp: ' + String(e))
|
|
2840
|
+
} finally {
|
|
2841
|
+
if (generation !== hydrateSessionGeneration) return
|
|
2842
|
+
sessionReplayInProgress = false
|
|
2843
|
+
flushPendingConversationDeltas()
|
|
2844
|
+
requestRenderChat()
|
|
2845
|
+
if (wasReady || serverReady) {
|
|
2846
|
+
serverReady = true
|
|
2847
|
+
setStatus('已就绪', 'ready')
|
|
2848
|
+
updateButtons()
|
|
2849
|
+
}
|
|
2850
|
+
}
|
|
2851
|
+
}
|
|
2852
|
+
|
|
2629
2853
|
/** UI 不展示 resume 合成 assistant 占位(与 messages.SYNTHETIC_MESSAGES 对齐) */
|
|
2630
2854
|
const WS_SYNTHETIC_ASSISTANT_TEXTS = new Set(['No response requested.'])
|
|
2631
2855
|
|
|
@@ -3277,12 +3501,10 @@
|
|
|
3277
3501
|
return (pickerSearch && pickerSearch.value.trim().toLowerCase()) || ''
|
|
3278
3502
|
}
|
|
3279
3503
|
|
|
3280
|
-
/**
|
|
3281
|
-
function setPickerContentMode(
|
|
3282
|
-
|
|
3283
|
-
if (
|
|
3284
|
-
if (pickerCloudPanel) pickerCloudPanel.hidden = !isCloud
|
|
3285
|
-
if (!isCloud && pickerContentState) {
|
|
3504
|
+
/** 切换 Picker 内容为表格模式 */
|
|
3505
|
+
function setPickerContentMode() {
|
|
3506
|
+
if (pickerEntriesTable) pickerEntriesTable.hidden = false
|
|
3507
|
+
if (pickerContentState) {
|
|
3286
3508
|
pickerContentState.hidden = true
|
|
3287
3509
|
pickerContentState.textContent = ''
|
|
3288
3510
|
}
|
|
@@ -3329,34 +3551,6 @@
|
|
|
3329
3551
|
return td
|
|
3330
3552
|
}
|
|
3331
3553
|
|
|
3332
|
-
/** 控制 Picker 左侧分类栏显隐(仅 Skill 页保留分类,其余合并为单表) */
|
|
3333
|
-
function setPickerNavPanelVisible(visible) {
|
|
3334
|
-
if (!pickerNavPanel) return
|
|
3335
|
-
pickerNavPanel.hidden = !visible
|
|
3336
|
-
if (!visible && pickerNavList) pickerNavList.innerHTML = ''
|
|
3337
|
-
}
|
|
3338
|
-
|
|
3339
|
-
/** 渲染 Picker 左侧分类导航 */
|
|
3340
|
-
function renderPickerNavTabs(tabDefs, activeId, onChange) {
|
|
3341
|
-
if (!pickerNavList) return
|
|
3342
|
-
pickerNavList.innerHTML = ''
|
|
3343
|
-
pickerManageState.activeTab = activeId
|
|
3344
|
-
for (let i = 0; i < tabDefs.length; i++) {
|
|
3345
|
-
const tab = tabDefs[i]
|
|
3346
|
-
const btn = document.createElement('button')
|
|
3347
|
-
btn.type = 'button'
|
|
3348
|
-
btn.className = 'picker-nav-item' + (tab.id === activeId ? ' is-selected' : '')
|
|
3349
|
-
btn.setAttribute('role', 'tab')
|
|
3350
|
-
btn.setAttribute('aria-selected', tab.id === activeId ? 'true' : 'false')
|
|
3351
|
-
btn.textContent = tab.label
|
|
3352
|
-
btn.addEventListener('click', function () {
|
|
3353
|
-
if (tab.id === activeId) return
|
|
3354
|
-
onChange(tab.id)
|
|
3355
|
-
})
|
|
3356
|
-
pickerNavList.appendChild(btn)
|
|
3357
|
-
}
|
|
3358
|
-
}
|
|
3359
|
-
|
|
3360
3554
|
/** 设置 entries/history 面板加载或错误态 */
|
|
3361
3555
|
function setRepoPanelState(el, message, isError) {
|
|
3362
3556
|
if (!el) return
|
|
@@ -4914,6 +5108,13 @@
|
|
|
4914
5108
|
skillPackageModal.setAttribute('aria-hidden', 'true')
|
|
4915
5109
|
document.body.style.overflow = ''
|
|
4916
5110
|
}
|
|
5111
|
+
|
|
5112
|
+
function closeSkillStoreModal() {
|
|
5113
|
+
if (!skillStoreModal) return
|
|
5114
|
+
skillStoreModal.classList.remove('is-open')
|
|
5115
|
+
skillStoreModal.setAttribute('aria-hidden', 'true')
|
|
5116
|
+
document.body.style.overflow = ''
|
|
5117
|
+
}
|
|
4917
5118
|
function closeRunGroupModal() {
|
|
4918
5119
|
if (!runGroupModal) return
|
|
4919
5120
|
runGroupModal.classList.remove('is-open')
|
|
@@ -5458,7 +5659,7 @@
|
|
|
5458
5659
|
if (!list.length) {
|
|
5459
5660
|
const empty = document.createElement('span')
|
|
5460
5661
|
empty.className = 'session-tabs-empty'
|
|
5461
|
-
empty.textContent = '
|
|
5662
|
+
empty.textContent = '暂无会话'
|
|
5462
5663
|
sessionListEl.appendChild(empty)
|
|
5463
5664
|
return
|
|
5464
5665
|
}
|
|
@@ -5484,6 +5685,7 @@
|
|
|
5484
5685
|
const mainBtn = document.createElement('button')
|
|
5485
5686
|
mainBtn.type = 'button'
|
|
5486
5687
|
mainBtn.className = 'sidebar-session-main'
|
|
5688
|
+
mainBtn.appendChild(createSessionKindIcon(resolveSessionKindForItem(s)))
|
|
5487
5689
|
if (isRunning) {
|
|
5488
5690
|
const runBadge = document.createElement('span')
|
|
5489
5691
|
runBadge.className = 'sidebar-session-running-badge'
|
|
@@ -5572,7 +5774,7 @@
|
|
|
5572
5774
|
return u.toString()
|
|
5573
5775
|
}
|
|
5574
5776
|
|
|
5575
|
-
/** 列表里是否存在运行中 session
|
|
5777
|
+
/** 列表里是否存在运行中 session(主 run query 进行中或当前页 turn 进行中) */
|
|
5576
5778
|
function sessionListHasRunning(sessions) {
|
|
5577
5779
|
if (!Array.isArray(sessions)) return false
|
|
5578
5780
|
const current = sessionIdInput ? sessionIdInput.value.trim() : ''
|
|
@@ -5713,6 +5915,9 @@
|
|
|
5713
5915
|
}
|
|
5714
5916
|
sessionIdInput.value = nextSid
|
|
5715
5917
|
currentSessionContextPercent = null
|
|
5918
|
+
sessionTurnActive = false
|
|
5919
|
+
hydrateSessionGeneration += 1
|
|
5920
|
+
resetChatUi()
|
|
5716
5921
|
void loadPendingPrompts()
|
|
5717
5922
|
if (nextSid) {
|
|
5718
5923
|
void loadSessionOverridesIntoComposer()
|
|
@@ -7420,15 +7625,18 @@
|
|
|
7420
7625
|
kind === 'mcp' ? '导入 MCP' : kind === 'skills' ? '导入 Skill' : '导入 zip'
|
|
7421
7626
|
btnPickerImport.disabled = false
|
|
7422
7627
|
}
|
|
7628
|
+
if (btnPickerSkillStore) {
|
|
7629
|
+
btnPickerSkillStore.hidden = kind !== 'skills'
|
|
7630
|
+
btnPickerSkillStore.disabled = false
|
|
7631
|
+
}
|
|
7423
7632
|
if (btnPickerMcpJson) {
|
|
7424
7633
|
btnPickerMcpJson.hidden = kind !== 'mcp'
|
|
7425
7634
|
btnPickerMcpJson.disabled = false
|
|
7426
7635
|
}
|
|
7427
7636
|
if (btnPickerCancel) btnPickerCancel.hidden = kind === 'skills' || kind === 'mcp'
|
|
7428
7637
|
if (btnPickerSave) btnPickerSave.hidden = kind === 'skills' || kind === 'mcp'
|
|
7429
|
-
setPickerNavPanelVisible(kind === 'skills')
|
|
7430
7638
|
setPickerContentState('加载中…', false)
|
|
7431
|
-
setPickerContentMode(
|
|
7639
|
+
setPickerContentMode()
|
|
7432
7640
|
clearPickerTableBody()
|
|
7433
7641
|
|
|
7434
7642
|
if (kind === 'tools') {
|
|
@@ -7553,7 +7761,7 @@
|
|
|
7553
7761
|
return tr
|
|
7554
7762
|
}
|
|
7555
7763
|
const renderToolsRows = function () {
|
|
7556
|
-
setPickerContentMode(
|
|
7764
|
+
setPickerContentMode()
|
|
7557
7765
|
setPickerTableHead(['名称', '类型', '详细信息', '操作'])
|
|
7558
7766
|
clearPickerTableBody()
|
|
7559
7767
|
setPickerContentState('', false)
|
|
@@ -7727,7 +7935,7 @@
|
|
|
7727
7935
|
return tr
|
|
7728
7936
|
}
|
|
7729
7937
|
const renderMcpRows = function () {
|
|
7730
|
-
setPickerContentMode(
|
|
7938
|
+
setPickerContentMode()
|
|
7731
7939
|
setPickerTableHead(['名称', '来源', '操作'])
|
|
7732
7940
|
clearPickerTableBody()
|
|
7733
7941
|
setPickerContentState('', false)
|
|
@@ -7828,7 +8036,7 @@
|
|
|
7828
8036
|
return (tags.length ? tags.join(' ') : '—') + (summary ? ' — ' + summary : '')
|
|
7829
8037
|
}
|
|
7830
8038
|
const renderAgentTeamsRows = function () {
|
|
7831
|
-
setPickerContentMode(
|
|
8039
|
+
setPickerContentMode()
|
|
7832
8040
|
setPickerTableHead(['成员', '配置', '操作'])
|
|
7833
8041
|
clearPickerTableBody()
|
|
7834
8042
|
setPickerContentState('', false)
|
|
@@ -7881,7 +8089,6 @@
|
|
|
7881
8089
|
})
|
|
7882
8090
|
} else {
|
|
7883
8091
|
const skillPickerState = {
|
|
7884
|
-
activeTab: 'list',
|
|
7885
8092
|
baseRows: [],
|
|
7886
8093
|
installedRows: [],
|
|
7887
8094
|
cloudRows: [],
|
|
@@ -7995,8 +8202,8 @@
|
|
|
7995
8202
|
return tr
|
|
7996
8203
|
}
|
|
7997
8204
|
const renderCloudSkillPanel = function () {
|
|
7998
|
-
if (!
|
|
7999
|
-
|
|
8205
|
+
if (!skillStoreModalBody) return
|
|
8206
|
+
skillStoreModalBody.innerHTML = ''
|
|
8000
8207
|
const cloudSearch = document.createElement('input')
|
|
8001
8208
|
cloudSearch.type = 'search'
|
|
8002
8209
|
cloudSearch.className = 'agent-picker-cloud-search'
|
|
@@ -8007,13 +8214,13 @@
|
|
|
8007
8214
|
skillPickerState.cloudPage = 1
|
|
8008
8215
|
void loadCloudSkillRows()
|
|
8009
8216
|
}
|
|
8010
|
-
|
|
8217
|
+
skillStoreModalBody.appendChild(cloudSearch)
|
|
8011
8218
|
const meta = document.createElement('div')
|
|
8012
8219
|
meta.className = 'agent-picker-cloud-meta'
|
|
8013
8220
|
if (skillPickerState.cloudLoading) meta.textContent = '加载中…'
|
|
8014
8221
|
else if (skillPickerState.cloudError) meta.textContent = '加载失败:' + skillPickerState.cloudError
|
|
8015
8222
|
else meta.textContent = '展示前 ' + skillPickerState.cloudRows.length + ' 项'
|
|
8016
|
-
|
|
8223
|
+
skillStoreModalBody.appendChild(meta)
|
|
8017
8224
|
if (!skillPickerState.cloudError && skillPickerState.cloudRows.length) {
|
|
8018
8225
|
for (let i = 0; i < skillPickerState.cloudRows.length; i++) {
|
|
8019
8226
|
const item = skillPickerState.cloudRows[i]
|
|
@@ -8031,7 +8238,7 @@
|
|
|
8031
8238
|
installing ? '处理中…' : installed ? '卸载' : '安装', '', function () {
|
|
8032
8239
|
if (installBtn.disabled) return
|
|
8033
8240
|
skillPickerState.installingMap[item.id] = true
|
|
8034
|
-
|
|
8241
|
+
renderCloudSkillPanel()
|
|
8035
8242
|
const request = installed
|
|
8036
8243
|
? fetch(buildRuntimeSkillDeleteUrl(item.packageId), { method: 'DELETE' })
|
|
8037
8244
|
: fetch(buildCloudSkillInstallUrl(), {
|
|
@@ -8049,21 +8256,23 @@
|
|
|
8049
8256
|
else pickerSelected.add(item.skillName || item.id)
|
|
8050
8257
|
setStatus('云端技能已' + (installed ? '卸载' : '安装') + ':' + item.title, serverReady ? 'ready' : '')
|
|
8051
8258
|
return persistSkillSelectionNow().then(function () {
|
|
8052
|
-
return refreshSkillPickerRows()
|
|
8259
|
+
return refreshSkillPickerRows().then(function () {
|
|
8260
|
+
return loadCloudSkillRows()
|
|
8261
|
+
})
|
|
8053
8262
|
})
|
|
8054
8263
|
})
|
|
8055
8264
|
.catch(function (e) { window.alert((installed ? '卸载' : '安装') + '失败: ' + e) })
|
|
8056
8265
|
.finally(function () {
|
|
8057
8266
|
delete skillPickerState.installingMap[item.id]
|
|
8058
|
-
|
|
8267
|
+
renderCloudSkillPanel()
|
|
8059
8268
|
})
|
|
8060
8269
|
}, { disabled: installing },
|
|
8061
8270
|
)
|
|
8062
8271
|
actions.appendChild(installBtn)
|
|
8063
8272
|
row.appendChild(actions)
|
|
8064
|
-
|
|
8273
|
+
skillStoreModalBody.appendChild(row)
|
|
8065
8274
|
}
|
|
8066
|
-
|
|
8275
|
+
skillStoreModalBody.appendChild(createCloudPager({
|
|
8067
8276
|
page: skillPickerState.cloudPage,
|
|
8068
8277
|
totalPages: skillPickerState.cloudTotalPages,
|
|
8069
8278
|
loading: skillPickerState.cloudLoading,
|
|
@@ -8075,24 +8284,11 @@
|
|
|
8075
8284
|
const empty = document.createElement('div')
|
|
8076
8285
|
empty.className = 'agent-picker-empty'
|
|
8077
8286
|
empty.textContent = skillPickerState.cloudLoading ? '(技能商店加载中)' : '(无匹配项)'
|
|
8078
|
-
|
|
8287
|
+
skillStoreModalBody.appendChild(empty)
|
|
8079
8288
|
}
|
|
8080
8289
|
}
|
|
8081
8290
|
const renderSkillRows = function () {
|
|
8082
|
-
|
|
8083
|
-
[
|
|
8084
|
-
{ id: 'list', label: 'Skill' },
|
|
8085
|
-
{ id: 'cloud', label: 'skill商店' },
|
|
8086
|
-
],
|
|
8087
|
-
skillPickerState.activeTab,
|
|
8088
|
-
function (id) { skillPickerState.activeTab = id; renderSkillRows() },
|
|
8089
|
-
)
|
|
8090
|
-
if (skillPickerState.activeTab === 'cloud') {
|
|
8091
|
-
setPickerContentMode('cloud')
|
|
8092
|
-
renderCloudSkillPanel()
|
|
8093
|
-
return
|
|
8094
|
-
}
|
|
8095
|
-
setPickerContentMode('table')
|
|
8291
|
+
setPickerContentMode()
|
|
8096
8292
|
setPickerTableHead(['名称', '描述', '操作'])
|
|
8097
8293
|
clearPickerTableBody()
|
|
8098
8294
|
setPickerContentState('', false)
|
|
@@ -8118,7 +8314,7 @@
|
|
|
8118
8314
|
skillPickerState.cloudSeq = seq
|
|
8119
8315
|
skillPickerState.cloudLoading = true
|
|
8120
8316
|
skillPickerState.cloudError = ''
|
|
8121
|
-
|
|
8317
|
+
renderCloudSkillPanel()
|
|
8122
8318
|
return fetch(buildCloudSkillCatalogUrl(skillPickerState.cloudQuery, skillPickerState.cloudPage, skillPickerState.cloudPageSize))
|
|
8123
8319
|
.then(function (r) {
|
|
8124
8320
|
return r.json().then(function (b) {
|
|
@@ -8131,21 +8327,28 @@
|
|
|
8131
8327
|
skillPickerState.cloudRows = Array.isArray(x.b.items) ? x.b.items : []
|
|
8132
8328
|
skillPickerState.cloudTotalPages = Number(x.b.totalPages || 0)
|
|
8133
8329
|
skillPickerState.cloudLoading = false
|
|
8134
|
-
|
|
8330
|
+
renderCloudSkillPanel()
|
|
8135
8331
|
})
|
|
8136
8332
|
.catch(function (e) {
|
|
8137
8333
|
if (seq !== skillPickerState.cloudSeq) return
|
|
8138
8334
|
skillPickerState.cloudRows = []
|
|
8139
8335
|
skillPickerState.cloudLoading = false
|
|
8140
8336
|
skillPickerState.cloudError = String(e)
|
|
8141
|
-
|
|
8337
|
+
renderCloudSkillPanel()
|
|
8142
8338
|
})
|
|
8143
8339
|
}
|
|
8340
|
+
openSkillStoreModalFn = function () {
|
|
8341
|
+
if (!skillStoreModal) return
|
|
8342
|
+
skillStoreModal.classList.add('is-open')
|
|
8343
|
+
skillStoreModal.setAttribute('aria-hidden', 'false')
|
|
8344
|
+
document.body.style.overflow = 'hidden'
|
|
8345
|
+
skillPickerState.cloudPage = 1
|
|
8346
|
+
void loadCloudSkillRows()
|
|
8347
|
+
}
|
|
8144
8348
|
refreshSkillPickerRows = function () {
|
|
8145
8349
|
return Promise.all([
|
|
8146
8350
|
fetchSkillRows(buildSkillBaseListUrl),
|
|
8147
8351
|
fetchSkillRows(buildSkillInstalledListUrl),
|
|
8148
|
-
loadCloudSkillRows(),
|
|
8149
8352
|
])
|
|
8150
8353
|
.then(function (allRows) {
|
|
8151
8354
|
skillPickerState.baseRows = allRows[0]
|
|
@@ -9100,6 +9303,20 @@
|
|
|
9100
9303
|
openSkillPackageModal()
|
|
9101
9304
|
})
|
|
9102
9305
|
}
|
|
9306
|
+
if (btnPickerSkillStore) {
|
|
9307
|
+
btnPickerSkillStore.addEventListener('click', function () {
|
|
9308
|
+
if (typeof openSkillStoreModalFn === 'function') openSkillStoreModalFn()
|
|
9309
|
+
})
|
|
9310
|
+
}
|
|
9311
|
+
if (btnSkillStoreModalClose) {
|
|
9312
|
+
btnSkillStoreModalClose.addEventListener('click', closeSkillStoreModal)
|
|
9313
|
+
}
|
|
9314
|
+
if (btnSkillStoreClose) {
|
|
9315
|
+
btnSkillStoreClose.addEventListener('click', closeSkillStoreModal)
|
|
9316
|
+
}
|
|
9317
|
+
if (skillStoreModalBackdrop) {
|
|
9318
|
+
skillStoreModalBackdrop.addEventListener('click', closeSkillStoreModal)
|
|
9319
|
+
}
|
|
9103
9320
|
if (btnSkillPackageModalClose) {
|
|
9104
9321
|
btnSkillPackageModalClose.addEventListener('click', closeSkillPackageModal)
|
|
9105
9322
|
}
|