@auto-ai/agent 2.1.221 → 2.1.223

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/safe-a/404/index.html +1 -1
  2. package/dist/safe-a/404.html +1 -1
  3. package/dist/safe-a/index.html +2 -2
  4. package/dist/safe-a/index.txt +1 -1
  5. package/dist/safe-a/manage/about/index.html +2 -2
  6. package/dist/safe-a/manage/about/index.txt +1 -1
  7. package/dist/safe-a/manage/env/index.html +2 -2
  8. package/dist/safe-a/manage/env/index.txt +1 -1
  9. package/dist/safe-a/manage/geelib/index.html +2 -2
  10. package/dist/safe-a/manage/geelib/index.txt +1 -1
  11. package/dist/safe-a/manage/general/index.html +2 -2
  12. package/dist/safe-a/manage/general/index.txt +1 -1
  13. package/dist/safe-a/manage/git/index.html +2 -2
  14. package/dist/safe-a/manage/git/index.txt +1 -1
  15. package/dist/safe-a/manage/im/index.html +2 -2
  16. package/dist/safe-a/manage/im/index.txt +1 -1
  17. package/dist/safe-a/manage/index.html +2 -2
  18. package/dist/safe-a/manage/index.txt +1 -1
  19. package/dist/safe-a/manage/library/index.html +2 -2
  20. package/dist/safe-a/manage/library/index.txt +1 -1
  21. package/dist/safe-a/manage/mcp/index.html +2 -2
  22. package/dist/safe-a/manage/mcp/index.txt +1 -1
  23. package/dist/safe-a/manage/permissions/index.html +2 -2
  24. package/dist/safe-a/manage/permissions/index.txt +1 -1
  25. package/dist/safe-a/manage/skills/index.html +2 -2
  26. package/dist/safe-a/manage/skills/index.txt +1 -1
  27. package/dist/safe-a/manage/task/index.html +2 -2
  28. package/dist/safe-a/manage/task/index.txt +1 -1
  29. package/dist/safe-a/manage/teams/index.html +2 -2
  30. package/dist/safe-a/manage/teams/index.txt +1 -1
  31. package/dist/safe-a/manage/tools/index.html +2 -2
  32. package/dist/safe-a/manage/tools/index.txt +1 -1
  33. package/dist/ws-test/agent-teams.html +1400 -0
  34. package/dist/ws-test/team-chat.js +760 -0
  35. package/dist/ws-test/ws-test.css +613 -6
  36. package/dist/ws-test/ws-test.html +23 -7
  37. package/dist/ws-test/ws-test.js +275 -89
  38. package/package.json +6 -6
  39. /package/dist/safe-a/_next/static/{1lVS2YCkhJeMjvIi_ropq → UA2zKbiNyTrZsAV1wjY-_}/_buildManifest.js +0 -0
  40. /package/dist/safe-a/_next/static/{1lVS2YCkhJeMjvIi_ropq → UA2zKbiNyTrZsAV1wjY-_}/_clientMiddlewareManifest.json +0 -0
  41. /package/dist/safe-a/_next/static/{1lVS2YCkhJeMjvIi_ropq → UA2zKbiNyTrZsAV1wjY-_}/_ssgManifest.js +0 -0
@@ -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'
@@ -769,6 +830,7 @@
769
830
  source: source,
770
831
  runId: runId,
771
832
  correlationId: correlationId,
833
+ turnId: typeof item.turnId === 'string' ? item.turnId : '',
772
834
  text: body,
773
835
  status: status,
774
836
  scheduledTrigger: item.scheduledTrigger === true,
@@ -1502,6 +1564,84 @@
1502
1564
  bodyEl.insertAdjacentElement('afterend', btn)
1503
1565
  }
1504
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
+
1505
1645
  function renderChat() {
1506
1646
  /**
1507
1647
  * 业务语义:run 折叠头需要展示“最后一条消息前三行”预览。
@@ -1716,6 +1856,7 @@
1716
1856
  Number.isInteger(item.arrivalSeq) ? item.arrivalSeq : Number.MAX_SAFE_INTEGER,
1717
1857
  fallbackOrder: timelineFallbackOrder++,
1718
1858
  runId: runId,
1859
+ turnId: typeof item.turnId === 'string' ? item.turnId : '',
1719
1860
  sourceAgent: resolveRunDisplayAgent(runId, item.sourceAgent),
1720
1861
  scheduledTrigger: item.scheduledTrigger === true,
1721
1862
  kind: 'conversation',
@@ -1736,6 +1877,7 @@
1736
1877
  Number.isInteger(item.arrivalSeq) ? item.arrivalSeq : Number.MAX_SAFE_INTEGER,
1737
1878
  fallbackOrder: timelineFallbackOrder++,
1738
1879
  runId: rid,
1880
+ turnId: typeof item.turnId === 'string' ? item.turnId : '',
1739
1881
  sourceAgent: resolveRunDisplayAgent(rid, item.source),
1740
1882
  scheduledTrigger: item.scheduledTrigger === true,
1741
1883
  kind: 'source',
@@ -1824,16 +1966,24 @@
1824
1966
  const groupContainer = document.createElement('div')
1825
1967
  groupContainer.className = 'chat-run-group' + (blockAllScheduled ? ' chat-run-group--scheduled' : '')
1826
1968
  if (runId === 'main') {
1827
- const fixedHeader = document.createElement('div')
1828
- fixedHeader.className = 'chat-msg-label'
1829
- fixedHeader.textContent = blockAllScheduled
1830
- ? '⏱ 定时任务 · ' + summaryText
1831
- : summaryText
1832
- groupContainer.appendChild(fixedHeader)
1833
- const groupBody = document.createElement('div')
1834
- groupBody.className = 'chat-run-group-body'
1835
- appendRunItemsToContainer(groupBody, blockItems, runId, defaultSourceAgent)
1836
- groupContainer.appendChild(groupBody)
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
+ }
1837
1987
  } else {
1838
1988
  const summaryCard = document.createElement('div')
1839
1989
  summaryCard.className =
@@ -1867,9 +2017,12 @@
1867
2017
  chatThreadEl.appendChild(groupContainer)
1868
2018
  }
1869
2019
  if (pendingUserEcho) {
1870
- const echoWrap = document.createElement('div')
1871
- echoWrap.className = 'chat-run-group chat-run-group--pending-echo'
1872
- appendPendingUserEchoToContainer(echoWrap)
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)
1873
2026
  chatThreadEl.appendChild(echoWrap)
1874
2027
  }
1875
2028
  if (streamEntries.length > 0) {
@@ -2165,6 +2318,7 @@
2165
2318
  const runMessage = {
2166
2319
  message: msg,
2167
2320
  sourceAgent: sourceAgent,
2321
+ turnId: typeof data.turnId === 'string' ? data.turnId : '',
2168
2322
  scheduledTrigger: payload.scheduledTrigger === true,
2169
2323
  ts:
2170
2324
  typeof data.ts === 'string' && data.ts
@@ -2207,6 +2361,7 @@
2207
2361
  source: source,
2208
2362
  runId: runId,
2209
2363
  correlationId: corr,
2364
+ turnId: typeof data.turnId === 'string' ? data.turnId : '',
2210
2365
  status: payload.status === 'resolved' ? 'resolved' : 'failed',
2211
2366
  text: text,
2212
2367
  scheduledTrigger: payload.scheduledTrigger === true,
@@ -2288,6 +2443,7 @@
2288
2443
  source: source,
2289
2444
  runId: runId,
2290
2445
  correlationId: '',
2446
+ turnId: typeof data.turnId === 'string' ? data.turnId : '',
2291
2447
  status: type === 'session.error' ? 'failed' : 'resolved',
2292
2448
  text: payloadText,
2293
2449
  key: typeof data.eventId === 'string' ? data.eventId : '',
@@ -2307,8 +2463,6 @@
2307
2463
  if (type === 'session.ready') {
2308
2464
  serverReady = true
2309
2465
  if (payload.agent) updateBrandAgent(payload.agent)
2310
- setStatus('已就绪', 'ready')
2311
- void loadPendingPrompts()
2312
2466
  const mc =
2313
2467
  typeof payload.messageCount === 'number' ? payload.messageCount : 0
2314
2468
  const sid =
@@ -2320,6 +2474,13 @@
2320
2474
  } else if (sid) {
2321
2475
  void hydrateSessionHistoryFromHttp(sid)
2322
2476
  }
2477
+ void loadPendingPrompts()
2478
+ void loadSessions({ silent: true }).then(function () {
2479
+ if (!syncRunningStatusForCurrentSession(window.__lastSessions)) {
2480
+ setStatus('已就绪', 'ready')
2481
+ }
2482
+ updateButtons()
2483
+ })
2323
2484
  return true
2324
2485
  }
2325
2486
  if (type === 'session.meta') {
@@ -2369,6 +2530,7 @@
2369
2530
  }
2370
2531
  void loadSessions({ silent: true })
2371
2532
  }
2533
+ requestRenderChat()
2372
2534
  return true
2373
2535
  }
2374
2536
  if (type === 'session.error') {
@@ -3344,12 +3506,10 @@
3344
3506
  return (pickerSearch && pickerSearch.value.trim().toLowerCase()) || ''
3345
3507
  }
3346
3508
 
3347
- /** 切换表格与云端面板显示 */
3348
- function setPickerContentMode(mode) {
3349
- const isCloud = mode === 'cloud'
3350
- if (pickerEntriesTable) pickerEntriesTable.hidden = isCloud
3351
- if (pickerCloudPanel) pickerCloudPanel.hidden = !isCloud
3352
- if (!isCloud && pickerContentState) {
3509
+ /** 切换 Picker 内容为表格模式 */
3510
+ function setPickerContentMode() {
3511
+ if (pickerEntriesTable) pickerEntriesTable.hidden = false
3512
+ if (pickerContentState) {
3353
3513
  pickerContentState.hidden = true
3354
3514
  pickerContentState.textContent = ''
3355
3515
  }
@@ -3396,34 +3556,6 @@
3396
3556
  return td
3397
3557
  }
3398
3558
 
3399
- /** 控制 Picker 左侧分类栏显隐(仅 Skill 页保留分类,其余合并为单表) */
3400
- function setPickerNavPanelVisible(visible) {
3401
- if (!pickerNavPanel) return
3402
- pickerNavPanel.hidden = !visible
3403
- if (!visible && pickerNavList) pickerNavList.innerHTML = ''
3404
- }
3405
-
3406
- /** 渲染 Picker 左侧分类导航 */
3407
- function renderPickerNavTabs(tabDefs, activeId, onChange) {
3408
- if (!pickerNavList) return
3409
- pickerNavList.innerHTML = ''
3410
- pickerManageState.activeTab = activeId
3411
- for (let i = 0; i < tabDefs.length; i++) {
3412
- const tab = tabDefs[i]
3413
- const btn = document.createElement('button')
3414
- btn.type = 'button'
3415
- btn.className = 'picker-nav-item' + (tab.id === activeId ? ' is-selected' : '')
3416
- btn.setAttribute('role', 'tab')
3417
- btn.setAttribute('aria-selected', tab.id === activeId ? 'true' : 'false')
3418
- btn.textContent = tab.label
3419
- btn.addEventListener('click', function () {
3420
- if (tab.id === activeId) return
3421
- onChange(tab.id)
3422
- })
3423
- pickerNavList.appendChild(btn)
3424
- }
3425
- }
3426
-
3427
3559
  /** 设置 entries/history 面板加载或错误态 */
3428
3560
  function setRepoPanelState(el, message, isError) {
3429
3561
  if (!el) return
@@ -4981,6 +5113,13 @@
4981
5113
  skillPackageModal.setAttribute('aria-hidden', 'true')
4982
5114
  document.body.style.overflow = ''
4983
5115
  }
5116
+
5117
+ function closeSkillStoreModal() {
5118
+ if (!skillStoreModal) return
5119
+ skillStoreModal.classList.remove('is-open')
5120
+ skillStoreModal.setAttribute('aria-hidden', 'true')
5121
+ document.body.style.overflow = ''
5122
+ }
4984
5123
  function closeRunGroupModal() {
4985
5124
  if (!runGroupModal) return
4986
5125
  runGroupModal.classList.remove('is-open')
@@ -5525,7 +5664,7 @@
5525
5664
  if (!list.length) {
5526
5665
  const empty = document.createElement('span')
5527
5666
  empty.className = 'session-tabs-empty'
5528
- empty.textContent = '暂无历史会话'
5667
+ empty.textContent = '暂无会话'
5529
5668
  sessionListEl.appendChild(empty)
5530
5669
  return
5531
5670
  }
@@ -5551,6 +5690,7 @@
5551
5690
  const mainBtn = document.createElement('button')
5552
5691
  mainBtn.type = 'button'
5553
5692
  mainBtn.className = 'sidebar-session-main'
5693
+ mainBtn.appendChild(createSessionKindIcon(resolveSessionKindForItem(s)))
5554
5694
  if (isRunning) {
5555
5695
  const runBadge = document.createElement('span')
5556
5696
  runBadge.className = 'sidebar-session-running-badge'
@@ -5654,6 +5794,28 @@
5654
5794
  })
5655
5795
  }
5656
5796
 
5797
+ /**
5798
+ * 将会话列表中的 running 同步到顶栏与 sessionTurnActive(刷新重连后 WS 可能尚未收到 query.progress)。
5799
+ */
5800
+ function syncRunningStatusForCurrentSession(sessions) {
5801
+ const sid = sessionIdInput ? sessionIdInput.value.trim() : ''
5802
+ if (!sid || !Array.isArray(sessions)) return false
5803
+ const cur = sessions.find(function (s) {
5804
+ return s && s.sessionId === sid
5805
+ })
5806
+ if (!cur || cur.running !== true) return false
5807
+ sessionTurnActive = true
5808
+ if (serverReady) {
5809
+ setStatus('任务进行中…', 'loading')
5810
+ }
5811
+ if (window.__lastSessions) {
5812
+ renderSessionList(window.__lastSessions)
5813
+ }
5814
+ kickSessionRuntimePoll()
5815
+ requestRenderChat()
5816
+ return true
5817
+ }
5818
+
5657
5819
  /** 轮询间隔:有运行中或本页 turn 时 1.5s,否则 4s */
5658
5820
  function sessionRuntimePollDelayMs() {
5659
5821
  if (sessionTurnActive || sessionListHasRunning(window.__lastSessions)) {
@@ -7490,15 +7652,18 @@
7490
7652
  kind === 'mcp' ? '导入 MCP' : kind === 'skills' ? '导入 Skill' : '导入 zip'
7491
7653
  btnPickerImport.disabled = false
7492
7654
  }
7655
+ if (btnPickerSkillStore) {
7656
+ btnPickerSkillStore.hidden = kind !== 'skills'
7657
+ btnPickerSkillStore.disabled = false
7658
+ }
7493
7659
  if (btnPickerMcpJson) {
7494
7660
  btnPickerMcpJson.hidden = kind !== 'mcp'
7495
7661
  btnPickerMcpJson.disabled = false
7496
7662
  }
7497
7663
  if (btnPickerCancel) btnPickerCancel.hidden = kind === 'skills' || kind === 'mcp'
7498
7664
  if (btnPickerSave) btnPickerSave.hidden = kind === 'skills' || kind === 'mcp'
7499
- setPickerNavPanelVisible(kind === 'skills')
7500
7665
  setPickerContentState('加载中…', false)
7501
- setPickerContentMode('table')
7666
+ setPickerContentMode()
7502
7667
  clearPickerTableBody()
7503
7668
 
7504
7669
  if (kind === 'tools') {
@@ -7623,7 +7788,7 @@
7623
7788
  return tr
7624
7789
  }
7625
7790
  const renderToolsRows = function () {
7626
- setPickerContentMode('table')
7791
+ setPickerContentMode()
7627
7792
  setPickerTableHead(['名称', '类型', '详细信息', '操作'])
7628
7793
  clearPickerTableBody()
7629
7794
  setPickerContentState('', false)
@@ -7797,7 +7962,7 @@
7797
7962
  return tr
7798
7963
  }
7799
7964
  const renderMcpRows = function () {
7800
- setPickerContentMode('table')
7965
+ setPickerContentMode()
7801
7966
  setPickerTableHead(['名称', '来源', '操作'])
7802
7967
  clearPickerTableBody()
7803
7968
  setPickerContentState('', false)
@@ -7898,7 +8063,7 @@
7898
8063
  return (tags.length ? tags.join(' ') : '—') + (summary ? ' — ' + summary : '')
7899
8064
  }
7900
8065
  const renderAgentTeamsRows = function () {
7901
- setPickerContentMode('table')
8066
+ setPickerContentMode()
7902
8067
  setPickerTableHead(['成员', '配置', '操作'])
7903
8068
  clearPickerTableBody()
7904
8069
  setPickerContentState('', false)
@@ -7951,7 +8116,6 @@
7951
8116
  })
7952
8117
  } else {
7953
8118
  const skillPickerState = {
7954
- activeTab: 'list',
7955
8119
  baseRows: [],
7956
8120
  installedRows: [],
7957
8121
  cloudRows: [],
@@ -8065,8 +8229,8 @@
8065
8229
  return tr
8066
8230
  }
8067
8231
  const renderCloudSkillPanel = function () {
8068
- if (!pickerCloudPanel) return
8069
- pickerCloudPanel.innerHTML = ''
8232
+ if (!skillStoreModalBody) return
8233
+ skillStoreModalBody.innerHTML = ''
8070
8234
  const cloudSearch = document.createElement('input')
8071
8235
  cloudSearch.type = 'search'
8072
8236
  cloudSearch.className = 'agent-picker-cloud-search'
@@ -8077,13 +8241,13 @@
8077
8241
  skillPickerState.cloudPage = 1
8078
8242
  void loadCloudSkillRows()
8079
8243
  }
8080
- pickerCloudPanel.appendChild(cloudSearch)
8244
+ skillStoreModalBody.appendChild(cloudSearch)
8081
8245
  const meta = document.createElement('div')
8082
8246
  meta.className = 'agent-picker-cloud-meta'
8083
8247
  if (skillPickerState.cloudLoading) meta.textContent = '加载中…'
8084
8248
  else if (skillPickerState.cloudError) meta.textContent = '加载失败:' + skillPickerState.cloudError
8085
8249
  else meta.textContent = '展示前 ' + skillPickerState.cloudRows.length + ' 项'
8086
- pickerCloudPanel.appendChild(meta)
8250
+ skillStoreModalBody.appendChild(meta)
8087
8251
  if (!skillPickerState.cloudError && skillPickerState.cloudRows.length) {
8088
8252
  for (let i = 0; i < skillPickerState.cloudRows.length; i++) {
8089
8253
  const item = skillPickerState.cloudRows[i]
@@ -8101,7 +8265,7 @@
8101
8265
  installing ? '处理中…' : installed ? '卸载' : '安装', '', function () {
8102
8266
  if (installBtn.disabled) return
8103
8267
  skillPickerState.installingMap[item.id] = true
8104
- renderSkillRows()
8268
+ renderCloudSkillPanel()
8105
8269
  const request = installed
8106
8270
  ? fetch(buildRuntimeSkillDeleteUrl(item.packageId), { method: 'DELETE' })
8107
8271
  : fetch(buildCloudSkillInstallUrl(), {
@@ -8119,21 +8283,23 @@
8119
8283
  else pickerSelected.add(item.skillName || item.id)
8120
8284
  setStatus('云端技能已' + (installed ? '卸载' : '安装') + ':' + item.title, serverReady ? 'ready' : '')
8121
8285
  return persistSkillSelectionNow().then(function () {
8122
- return refreshSkillPickerRows()
8286
+ return refreshSkillPickerRows().then(function () {
8287
+ return loadCloudSkillRows()
8288
+ })
8123
8289
  })
8124
8290
  })
8125
8291
  .catch(function (e) { window.alert((installed ? '卸载' : '安装') + '失败: ' + e) })
8126
8292
  .finally(function () {
8127
8293
  delete skillPickerState.installingMap[item.id]
8128
- renderSkillRows()
8294
+ renderCloudSkillPanel()
8129
8295
  })
8130
8296
  }, { disabled: installing },
8131
8297
  )
8132
8298
  actions.appendChild(installBtn)
8133
8299
  row.appendChild(actions)
8134
- pickerCloudPanel.appendChild(row)
8300
+ skillStoreModalBody.appendChild(row)
8135
8301
  }
8136
- pickerCloudPanel.appendChild(createCloudPager({
8302
+ skillStoreModalBody.appendChild(createCloudPager({
8137
8303
  page: skillPickerState.cloudPage,
8138
8304
  totalPages: skillPickerState.cloudTotalPages,
8139
8305
  loading: skillPickerState.cloudLoading,
@@ -8145,24 +8311,11 @@
8145
8311
  const empty = document.createElement('div')
8146
8312
  empty.className = 'agent-picker-empty'
8147
8313
  empty.textContent = skillPickerState.cloudLoading ? '(技能商店加载中)' : '(无匹配项)'
8148
- pickerCloudPanel.appendChild(empty)
8314
+ skillStoreModalBody.appendChild(empty)
8149
8315
  }
8150
8316
  }
8151
8317
  const renderSkillRows = function () {
8152
- renderPickerNavTabs(
8153
- [
8154
- { id: 'list', label: 'Skill' },
8155
- { id: 'cloud', label: 'skill商店' },
8156
- ],
8157
- skillPickerState.activeTab,
8158
- function (id) { skillPickerState.activeTab = id; renderSkillRows() },
8159
- )
8160
- if (skillPickerState.activeTab === 'cloud') {
8161
- setPickerContentMode('cloud')
8162
- renderCloudSkillPanel()
8163
- return
8164
- }
8165
- setPickerContentMode('table')
8318
+ setPickerContentMode()
8166
8319
  setPickerTableHead(['名称', '描述', '操作'])
8167
8320
  clearPickerTableBody()
8168
8321
  setPickerContentState('', false)
@@ -8188,7 +8341,7 @@
8188
8341
  skillPickerState.cloudSeq = seq
8189
8342
  skillPickerState.cloudLoading = true
8190
8343
  skillPickerState.cloudError = ''
8191
- renderSkillRows()
8344
+ renderCloudSkillPanel()
8192
8345
  return fetch(buildCloudSkillCatalogUrl(skillPickerState.cloudQuery, skillPickerState.cloudPage, skillPickerState.cloudPageSize))
8193
8346
  .then(function (r) {
8194
8347
  return r.json().then(function (b) {
@@ -8201,21 +8354,28 @@
8201
8354
  skillPickerState.cloudRows = Array.isArray(x.b.items) ? x.b.items : []
8202
8355
  skillPickerState.cloudTotalPages = Number(x.b.totalPages || 0)
8203
8356
  skillPickerState.cloudLoading = false
8204
- renderSkillRows()
8357
+ renderCloudSkillPanel()
8205
8358
  })
8206
8359
  .catch(function (e) {
8207
8360
  if (seq !== skillPickerState.cloudSeq) return
8208
8361
  skillPickerState.cloudRows = []
8209
8362
  skillPickerState.cloudLoading = false
8210
8363
  skillPickerState.cloudError = String(e)
8211
- renderSkillRows()
8364
+ renderCloudSkillPanel()
8212
8365
  })
8213
8366
  }
8367
+ openSkillStoreModalFn = function () {
8368
+ if (!skillStoreModal) return
8369
+ skillStoreModal.classList.add('is-open')
8370
+ skillStoreModal.setAttribute('aria-hidden', 'false')
8371
+ document.body.style.overflow = 'hidden'
8372
+ skillPickerState.cloudPage = 1
8373
+ void loadCloudSkillRows()
8374
+ }
8214
8375
  refreshSkillPickerRows = function () {
8215
8376
  return Promise.all([
8216
8377
  fetchSkillRows(buildSkillBaseListUrl),
8217
8378
  fetchSkillRows(buildSkillInstalledListUrl),
8218
- loadCloudSkillRows(),
8219
8379
  ])
8220
8380
  .then(function (allRows) {
8221
8381
  skillPickerState.baseRows = allRows[0]
@@ -9170,6 +9330,20 @@
9170
9330
  openSkillPackageModal()
9171
9331
  })
9172
9332
  }
9333
+ if (btnPickerSkillStore) {
9334
+ btnPickerSkillStore.addEventListener('click', function () {
9335
+ if (typeof openSkillStoreModalFn === 'function') openSkillStoreModalFn()
9336
+ })
9337
+ }
9338
+ if (btnSkillStoreModalClose) {
9339
+ btnSkillStoreModalClose.addEventListener('click', closeSkillStoreModal)
9340
+ }
9341
+ if (btnSkillStoreClose) {
9342
+ btnSkillStoreClose.addEventListener('click', closeSkillStoreModal)
9343
+ }
9344
+ if (skillStoreModalBackdrop) {
9345
+ skillStoreModalBackdrop.addEventListener('click', closeSkillStoreModal)
9346
+ }
9173
9347
  if (btnSkillPackageModalClose) {
9174
9348
  btnSkillPackageModalClose.addEventListener('click', closeSkillPackageModal)
9175
9349
  }
@@ -9523,8 +9697,20 @@
9523
9697
  async function bootstrapSessionSelection() {
9524
9698
  await loadSessions({ activateFirstIfEmpty: true })
9525
9699
  kickSessionRuntimePoll()
9526
- if (!sessionIdInput || sessionIdInput.value.trim()) return
9527
- switchToSession('')
9700
+ const sid = sessionIdInput ? sessionIdInput.value.trim() : ''
9701
+ if (!sid) {
9702
+ switchToSession('')
9703
+ return
9704
+ }
9705
+ syncRunningStatusForCurrentSession(window.__lastSessions)
9706
+ // 刷新后 sessionId 已有值但 WS 未建连时须 attach
9707
+ if (
9708
+ !socket ||
9709
+ socket.readyState === WebSocket.CLOSED ||
9710
+ socket.readyState === WebSocket.CLOSING
9711
+ ) {
9712
+ switchToSession(sid)
9713
+ }
9528
9714
  }
9529
9715
 
9530
9716
  document.addEventListener('visibilitychange', function () {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@auto-ai/agent",
3
- "version": "2.1.221",
3
+ "version": "2.1.223",
4
4
  "description": "Auto AI Agent 网关 CLI(WebSocket,独立二进制,无需 Bun)",
5
5
  "type": "module",
6
6
  "maintainers": [
@@ -32,11 +32,11 @@
32
32
  "zod": "^4.3.6"
33
33
  },
34
34
  "optionalDependencies": {
35
- "@auto-ai/agent-linux-x64": "2.1.221",
36
- "@auto-ai/agent-linux-arm64": "2.1.221",
37
- "@auto-ai/agent-darwin-x64": "2.1.221",
38
- "@auto-ai/agent-darwin-arm64": "2.1.221",
39
- "@auto-ai/agent-win-x64": "2.1.221"
35
+ "@auto-ai/agent-linux-x64": "2.1.223",
36
+ "@auto-ai/agent-linux-arm64": "2.1.223",
37
+ "@auto-ai/agent-darwin-x64": "2.1.223",
38
+ "@auto-ai/agent-darwin-arm64": "2.1.223",
39
+ "@auto-ai/agent-win-x64": "2.1.223"
40
40
  },
41
41
  "scripts": {
42
42
  "prepare": "node ../../scripts/sync-launcher-env.js",