axon-code 2.5.1 → 2.6.1

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 (189) hide show
  1. package/dist/config/axon-md-parser.d.ts.map +1 -1
  2. package/dist/config/axon-md-parser.js +21 -4
  3. package/dist/config/axon-md-parser.js.map +1 -1
  4. package/dist/config/index.d.ts +9 -6
  5. package/dist/config/index.d.ts.map +1 -1
  6. package/dist/config/index.js +1 -0
  7. package/dist/config/index.js.map +1 -1
  8. package/dist/context/enhanced.d.ts.map +1 -1
  9. package/dist/context/enhanced.js +5 -0
  10. package/dist/context/enhanced.js.map +1 -1
  11. package/dist/core/loop.d.ts +45 -1
  12. package/dist/core/loop.d.ts.map +1 -1
  13. package/dist/core/loop.js +317 -111
  14. package/dist/core/loop.js.map +1 -1
  15. package/dist/core/max-tokens.d.ts.map +1 -1
  16. package/dist/core/max-tokens.js +5 -0
  17. package/dist/core/max-tokens.js.map +1 -1
  18. package/dist/core/session.d.ts.map +1 -1
  19. package/dist/core/session.js +7 -14
  20. package/dist/core/session.js.map +1 -1
  21. package/dist/daemon/config.d.ts +6 -6
  22. package/dist/daemon/executor.d.ts.map +1 -1
  23. package/dist/daemon/executor.js +24 -30
  24. package/dist/daemon/executor.js.map +1 -1
  25. package/dist/mcp/config.d.ts +8 -8
  26. package/dist/media/index.d.ts +1 -1
  27. package/dist/media/index.d.ts.map +1 -1
  28. package/dist/media/index.js +3 -3
  29. package/dist/media/index.js.map +1 -1
  30. package/dist/media/office.d.ts +17 -0
  31. package/dist/media/office.d.ts.map +1 -1
  32. package/dist/media/office.js +227 -2
  33. package/dist/media/office.js.map +1 -1
  34. package/dist/memory/memory-search.d.ts +4 -1
  35. package/dist/memory/memory-search.d.ts.map +1 -1
  36. package/dist/memory/memory-search.js +31 -2
  37. package/dist/memory/memory-search.js.map +1 -1
  38. package/dist/memory/memory-sync.d.ts +7 -0
  39. package/dist/memory/memory-sync.d.ts.map +1 -1
  40. package/dist/memory/memory-sync.js +88 -0
  41. package/dist/memory/memory-sync.js.map +1 -1
  42. package/dist/memory/notebook.d.ts.map +1 -1
  43. package/dist/memory/notebook.js +562 -15
  44. package/dist/memory/notebook.js.map +1 -1
  45. package/dist/models/config.d.ts.map +1 -1
  46. package/dist/models/config.js +7 -4
  47. package/dist/models/config.js.map +1 -1
  48. package/dist/models/index.d.ts +1 -0
  49. package/dist/models/index.d.ts.map +1 -1
  50. package/dist/models/index.js +1 -0
  51. package/dist/models/index.js.map +1 -1
  52. package/dist/models/model-limits.d.ts +13 -0
  53. package/dist/models/model-limits.d.ts.map +1 -0
  54. package/dist/models/model-limits.js +79 -0
  55. package/dist/models/model-limits.js.map +1 -0
  56. package/dist/prompt/attachments.d.ts +1 -0
  57. package/dist/prompt/attachments.d.ts.map +1 -1
  58. package/dist/prompt/attachments.js +17 -2
  59. package/dist/prompt/attachments.js.map +1 -1
  60. package/dist/prompt/cache.d.ts +1 -8
  61. package/dist/prompt/cache.d.ts.map +1 -1
  62. package/dist/prompt/cache.js +37 -9
  63. package/dist/prompt/cache.js.map +1 -1
  64. package/dist/session/index.d.ts +1 -0
  65. package/dist/session/index.d.ts.map +1 -1
  66. package/dist/session/index.js.map +1 -1
  67. package/dist/tools/agent.d.ts +8 -0
  68. package/dist/tools/agent.d.ts.map +1 -1
  69. package/dist/tools/agent.js +66 -2
  70. package/dist/tools/agent.js.map +1 -1
  71. package/dist/tools/file.d.ts.map +1 -1
  72. package/dist/tools/file.js +99 -30
  73. package/dist/tools/file.js.map +1 -1
  74. package/dist/tools/index.d.ts.map +1 -1
  75. package/dist/tools/index.js +7 -4
  76. package/dist/tools/index.js.map +1 -1
  77. package/dist/tools/mcp.d.ts.map +1 -1
  78. package/dist/tools/mcp.js +5 -0
  79. package/dist/tools/mcp.js.map +1 -1
  80. package/dist/tools/memory-search.d.ts +1 -1
  81. package/dist/tools/memory-search.d.ts.map +1 -1
  82. package/dist/tools/memory-search.js +1 -1
  83. package/dist/tools/memory-search.js.map +1 -1
  84. package/dist/tools/notebook-write.d.ts.map +1 -1
  85. package/dist/tools/notebook-write.js +3 -1
  86. package/dist/tools/notebook-write.js.map +1 -1
  87. package/dist/tools/skill.d.ts +0 -6
  88. package/dist/tools/skill.d.ts.map +1 -1
  89. package/dist/tools/skill.js +211 -34
  90. package/dist/tools/skill.js.map +1 -1
  91. package/dist/types/messages.d.ts +1 -5
  92. package/dist/types/messages.d.ts.map +1 -1
  93. package/dist/web/server/api-manager.d.ts +7 -5
  94. package/dist/web/server/api-manager.d.ts.map +1 -1
  95. package/dist/web/server/api-manager.js +140 -146
  96. package/dist/web/server/api-manager.js.map +1 -1
  97. package/dist/web/server/conversation.d.ts.map +1 -1
  98. package/dist/web/server/conversation.js +27 -10
  99. package/dist/web/server/conversation.js.map +1 -1
  100. package/dist/web/server/routes/api.d.ts.map +1 -1
  101. package/dist/web/server/routes/api.js +21 -24
  102. package/dist/web/server/routes/api.js.map +1 -1
  103. package/dist/web/server/routes/axon-cloud.d.ts.map +1 -1
  104. package/dist/web/server/routes/axon-cloud.js +350 -1
  105. package/dist/web/server/routes/axon-cloud.js.map +1 -1
  106. package/dist/web/server/routes/config-api.d.ts.map +1 -1
  107. package/dist/web/server/routes/config-api.js +12 -20
  108. package/dist/web/server/routes/config-api.js.map +1 -1
  109. package/dist/web/server/routes/download-proxy.d.ts.map +1 -1
  110. package/dist/web/server/routes/download-proxy.js +234 -12
  111. package/dist/web/server/routes/download-proxy.js.map +1 -1
  112. package/dist/web/server/runtime/api-connection-test.d.ts +18 -0
  113. package/dist/web/server/runtime/api-connection-test.d.ts.map +1 -0
  114. package/dist/web/server/runtime/api-connection-test.js +62 -0
  115. package/dist/web/server/runtime/api-connection-test.js.map +1 -0
  116. package/dist/web/server/runtime/codex-client.d.ts +5 -0
  117. package/dist/web/server/runtime/codex-client.d.ts.map +1 -1
  118. package/dist/web/server/runtime/codex-client.js +229 -29
  119. package/dist/web/server/runtime/codex-client.js.map +1 -1
  120. package/dist/web/server/runtime/runtime-model-catalog.d.ts +10 -0
  121. package/dist/web/server/runtime/runtime-model-catalog.d.ts.map +1 -0
  122. package/dist/web/server/runtime/runtime-model-catalog.js +85 -0
  123. package/dist/web/server/runtime/runtime-model-catalog.js.map +1 -0
  124. package/dist/web/server/runtime/runtime-model-list.d.ts +24 -0
  125. package/dist/web/server/runtime/runtime-model-list.d.ts.map +1 -0
  126. package/dist/web/server/runtime/runtime-model-list.js +43 -0
  127. package/dist/web/server/runtime/runtime-model-list.js.map +1 -0
  128. package/dist/web/server/runtime/runtime-selection.d.ts +1 -0
  129. package/dist/web/server/runtime/runtime-selection.d.ts.map +1 -1
  130. package/dist/web/server/runtime/runtime-selection.js +5 -3
  131. package/dist/web/server/runtime/runtime-selection.js.map +1 -1
  132. package/dist/web/server/runtime/types.d.ts +5 -0
  133. package/dist/web/server/runtime/types.d.ts.map +1 -1
  134. package/dist/web/server/runtime/utility-client.d.ts.map +1 -1
  135. package/dist/web/server/runtime/utility-client.js +4 -1
  136. package/dist/web/server/runtime/utility-client.js.map +1 -1
  137. package/dist/web/server/services/axon-cloud-service.d.ts +24 -0
  138. package/dist/web/server/services/axon-cloud-service.d.ts.map +1 -1
  139. package/dist/web/server/services/axon-cloud-service.js +93 -0
  140. package/dist/web/server/services/axon-cloud-service.js.map +1 -1
  141. package/dist/web/server/services/config-service.d.ts +2 -1
  142. package/dist/web/server/services/config-service.d.ts.map +1 -1
  143. package/dist/web/server/services/config-service.js +28 -18
  144. package/dist/web/server/services/config-service.js.map +1 -1
  145. package/dist/web/server/session-manager.d.ts +9 -0
  146. package/dist/web/server/session-manager.d.ts.map +1 -1
  147. package/dist/web/server/session-manager.js +38 -0
  148. package/dist/web/server/session-manager.js.map +1 -1
  149. package/dist/web/server/slash-commands.d.ts.map +1 -1
  150. package/dist/web/server/slash-commands.js +79 -19
  151. package/dist/web/server/slash-commands.js.map +1 -1
  152. package/dist/web/server/task-manager.d.ts +4 -15
  153. package/dist/web/server/task-manager.d.ts.map +1 -1
  154. package/dist/web/server/task-manager.js +11 -4
  155. package/dist/web/server/task-manager.js.map +1 -1
  156. package/dist/web/server/web-auth.d.ts.map +1 -1
  157. package/dist/web/server/web-auth.js +32 -28
  158. package/dist/web/server/web-auth.js.map +1 -1
  159. package/dist/web/server/websocket.d.ts.map +1 -1
  160. package/dist/web/server/websocket.js +62 -35
  161. package/dist/web/server/websocket.js.map +1 -1
  162. package/dist/web/shared/auth-summary.d.ts.map +1 -1
  163. package/dist/web/shared/auth-summary.js +5 -2
  164. package/dist/web/shared/auth-summary.js.map +1 -1
  165. package/dist/web/shared/model-catalog.d.ts +3 -2
  166. package/dist/web/shared/model-catalog.d.ts.map +1 -1
  167. package/dist/web/shared/model-catalog.js +29 -37
  168. package/dist/web/shared/model-catalog.js.map +1 -1
  169. package/dist/web/shared/runtime-capabilities.d.ts +37 -0
  170. package/dist/web/shared/runtime-capabilities.d.ts.map +1 -0
  171. package/dist/web/shared/runtime-capabilities.js +101 -0
  172. package/dist/web/shared/runtime-capabilities.js.map +1 -0
  173. package/dist/web/shared/setup-runtime.d.ts +23 -0
  174. package/dist/web/shared/setup-runtime.d.ts.map +1 -1
  175. package/dist/web/shared/setup-runtime.js +119 -19
  176. package/dist/web/shared/setup-runtime.js.map +1 -1
  177. package/dist/web/shared/thinking-config.d.ts.map +1 -1
  178. package/dist/web/shared/thinking-config.js +10 -5
  179. package/dist/web/shared/thinking-config.js.map +1 -1
  180. package/dist/web/shared/types.d.ts +8 -0
  181. package/dist/web/shared/types.d.ts.map +1 -1
  182. package/dist/web/shared/types.js.map +1 -1
  183. package/electron/main.cjs +8 -1
  184. package/package.json +3 -1
  185. package/src/web/client/dist/assets/index-B2M5Nr-5.js +736 -0
  186. package/src/web/client/dist/assets/index-COEqamS-.css +32 -0
  187. package/src/web/client/dist/index.html +2 -2
  188. package/src/web/client/dist/assets/index-B0gwq5PJ.js +0 -727
  189. package/src/web/client/dist/assets/index-CwhuMLtk.css +0 -32
@@ -1942,6 +1942,7 @@ async function prepareChatSession(client, content, attachments, conversationMana
1942
1942
  if (!existingSession) {
1943
1943
  // 当前 sessionId 是临时的(WebSocket 连接时生成的),需要创建持久化会话
1944
1944
  // 官方规范:使用第一条消息的前50个字符作为会话标题
1945
+ const temporarySessionId = sessionId;
1945
1946
  const firstPrompt = content.substring(0, 50);
1946
1947
  console.log(`[WebSocket] Temporary session ${sessionId}, creating persistent session, title: ${firstPrompt}, projectPath: ${client.projectPath || 'global'}`);
1947
1948
  const newSession = sessionManager.createSession({
@@ -1951,6 +1952,7 @@ async function prepareChatSession(client, content, attachments, conversationMana
1951
1952
  tags: ['webui'],
1952
1953
  projectPath: client.projectPath, // 传递项目路径
1953
1954
  });
1955
+ sessionManager.registerTemporarySessionId(newSession.metadata.id, temporarySessionId);
1954
1956
  // 更新 client 的 sessionId
1955
1957
  client.sessionId = newSession.metadata.id;
1956
1958
  sessionId = newSession.metadata.id;
@@ -2547,42 +2549,59 @@ async function handleSessionNew(client, payload, conversationManager) {
2547
2549
  });
2548
2550
  }
2549
2551
  }
2552
+ function resolveSessionRestoreTargetId(conversationManager, requestedSessionId) {
2553
+ const resolvedSessionId = conversationManager.getSessionManager().findSessionIdByTemporarySessionId(requestedSessionId);
2554
+ if (resolvedSessionId && resolvedSessionId !== requestedSessionId) {
2555
+ console.log(`[WebSocket] Resolved temporary session ${requestedSessionId} -> ${resolvedSessionId}`);
2556
+ return resolvedSessionId;
2557
+ }
2558
+ return requestedSessionId;
2559
+ }
2550
2560
  /**
2551
2561
  * 处理切换会话请求
2552
2562
  */
2553
2563
  async function handleSessionSwitch(client, sessionId, conversationManager) {
2554
2564
  const { ws } = client;
2555
2565
  try {
2566
+ let targetSessionId = sessionId;
2556
2567
  // 提前更新 ws:如果目标会话已在内存中(正在处理),立即将其 ws 指向新连接
2557
2568
  // 这样在 await resumeSession() 期间,流式回调就能通过 getActiveWs() 获取到新 ws,
2558
2569
  // 避免消息发送到已关闭的旧连接而丢失
2559
- conversationManager.setWebSocket(sessionId, ws);
2570
+ conversationManager.setWebSocket(targetSessionId, ws);
2560
2571
  // 保存当前会话
2561
2572
  await conversationManager.persistSession(client.sessionId);
2562
2573
  // 恢复目标会话(传入客户端权限模式,确保 YOLO 等模式跨会话持久化)
2563
- const success = await conversationManager.resumeSession(sessionId, client.permissionMode);
2574
+ let success = await conversationManager.resumeSession(targetSessionId, client.permissionMode);
2575
+ if (!success) {
2576
+ const resolvedSessionId = resolveSessionRestoreTargetId(conversationManager, targetSessionId);
2577
+ if (resolvedSessionId !== targetSessionId) {
2578
+ targetSessionId = resolvedSessionId;
2579
+ conversationManager.setWebSocket(targetSessionId, ws);
2580
+ success = await conversationManager.resumeSession(targetSessionId, client.permissionMode);
2581
+ }
2582
+ }
2564
2583
  if (success) {
2565
2584
  // 更新客户端会话ID
2566
- client.sessionId = sessionId;
2585
+ client.sessionId = targetSessionId;
2567
2586
  // 恢复后再次更新 ws(resumeSession 可能从磁盘新建了 SessionState)
2568
- conversationManager.setWebSocket(sessionId, ws);
2587
+ conversationManager.setWebSocket(targetSessionId, ws);
2569
2588
  // 更新客户端项目路径(优化:从内存中的 SessionState 获取,避免重复读磁盘)
2570
- const projectPath = conversationManager.getSessionProjectPath(sessionId);
2589
+ const projectPath = conversationManager.getSessionProjectPath(targetSessionId);
2571
2590
  if (projectPath) {
2572
2591
  client.projectPath = projectPath;
2573
2592
  }
2574
2593
  // 获取会话历史(使用 getLiveHistory:处理中时从 messages 实时构建,确保工具调用中间 turn 不丢失)
2575
- const history = conversationManager.getLiveHistory(sessionId);
2576
- console.log(`[WebSocket] handleSessionSwitch: sessionId=${sessionId}, history.length=${history.length}, isProcessing=${conversationManager.isSessionProcessing(sessionId)}`);
2577
- const sessionName = conversationManager.getSessionName(sessionId);
2578
- const sessionRuntimeBackend = conversationManager.getSessionRuntimeBackend(sessionId) || webAuth.getRuntimeBackend();
2579
- const sessionModel = conversationManager.getSessionModel(sessionId) || getDefaultChatModel(sessionRuntimeBackend);
2594
+ const history = conversationManager.getLiveHistory(targetSessionId);
2595
+ console.log(`[WebSocket] handleSessionSwitch: sessionId=${targetSessionId}, history.length=${history.length}, isProcessing=${conversationManager.isSessionProcessing(targetSessionId)}`);
2596
+ const sessionName = conversationManager.getSessionName(targetSessionId);
2597
+ const sessionRuntimeBackend = conversationManager.getSessionRuntimeBackend(targetSessionId) || webAuth.getRuntimeBackend();
2598
+ const sessionModel = conversationManager.getSessionModel(targetSessionId) || getDefaultChatModel(sessionRuntimeBackend);
2580
2599
  client.model = sessionModel;
2581
2600
  client.runtimeBackend = sessionRuntimeBackend;
2582
2601
  sendMessage(ws, {
2583
2602
  type: 'session_switched',
2584
2603
  payload: {
2585
- sessionId,
2604
+ sessionId: targetSessionId,
2586
2605
  sessionName,
2587
2606
  projectPath: client.projectPath,
2588
2607
  history,
@@ -2591,7 +2610,7 @@ async function handleSessionSwitch(client, sessionId, conversationManager) {
2591
2610
  },
2592
2611
  });
2593
2612
  // 同步权限配置到客户端(刷新后客户端 permissionMode 会重置为 'default',需要从服务端恢复)
2594
- const permConfig = conversationManager.getPermissionConfig(sessionId);
2613
+ const permConfig = conversationManager.getPermissionConfig(targetSessionId);
2595
2614
  if (permConfig) {
2596
2615
  sendMessage(ws, {
2597
2616
  type: 'permission_config_update',
@@ -2605,33 +2624,33 @@ async function handleSessionSwitch(client, sessionId, conversationManager) {
2605
2624
  }
2606
2625
  // 如果会话正在处理中(如页面刷新),恢复流式状态
2607
2626
  // 补发 message_start + 已累积的内容,让客户端立即显示已生成的内容
2608
- const isProcessing = conversationManager.isSessionProcessing(sessionId);
2627
+ const isProcessing = conversationManager.isSessionProcessing(targetSessionId);
2609
2628
  if (isProcessing) {
2610
2629
  const resumeMessageId = `resume-${Date.now()}`;
2611
2630
  // 补发 message_start,客户端收到后会创建 currentMessageRef
2612
2631
  sendMessage(ws, {
2613
2632
  type: 'message_start',
2614
- payload: { messageId: resumeMessageId, sessionId },
2633
+ payload: { messageId: resumeMessageId, sessionId: targetSessionId },
2615
2634
  });
2616
2635
  // 获取已累积的流式中间内容,补发给客户端
2617
2636
  // 这样用户刷新后能立即看到 API 已经生成的内容,而不是空气泡
2618
- const streamingContent = conversationManager.getStreamingContent(sessionId);
2637
+ const streamingContent = conversationManager.getStreamingContent(targetSessionId);
2619
2638
  if (streamingContent) {
2620
2639
  // 补发 thinking 内容(如果有)
2621
2640
  if (streamingContent.thinkingText) {
2622
2641
  sendMessage(ws, {
2623
2642
  type: 'thinking_start',
2624
- payload: { messageId: resumeMessageId, sessionId },
2643
+ payload: { messageId: resumeMessageId, sessionId: targetSessionId },
2625
2644
  });
2626
2645
  sendMessage(ws, {
2627
2646
  type: 'thinking_delta',
2628
- payload: { messageId: resumeMessageId, text: streamingContent.thinkingText, sessionId },
2647
+ payload: { messageId: resumeMessageId, text: streamingContent.thinkingText, sessionId: targetSessionId },
2629
2648
  });
2630
2649
  // 如果已有 text 内容,说明 thinking 已经结束
2631
2650
  if (streamingContent.textContent) {
2632
2651
  sendMessage(ws, {
2633
2652
  type: 'thinking_complete',
2634
- payload: { messageId: resumeMessageId, sessionId },
2653
+ payload: { messageId: resumeMessageId, sessionId: targetSessionId },
2635
2654
  });
2636
2655
  }
2637
2656
  }
@@ -2639,40 +2658,40 @@ async function handleSessionSwitch(client, sessionId, conversationManager) {
2639
2658
  if (streamingContent.textContent) {
2640
2659
  sendMessage(ws, {
2641
2660
  type: 'text_delta',
2642
- payload: { messageId: resumeMessageId, text: streamingContent.textContent, sessionId },
2661
+ payload: { messageId: resumeMessageId, text: streamingContent.textContent, sessionId: targetSessionId },
2643
2662
  });
2644
2663
  }
2645
2664
  }
2646
2665
  sendMessage(ws, {
2647
2666
  type: 'status',
2648
- payload: { status: 'streaming', message: 'Processing conversation...', sessionId },
2667
+ payload: { status: 'streaming', message: 'Processing conversation...', sessionId: targetSessionId },
2649
2668
  });
2650
2669
  // 重发待处理的权限请求和用户问题
2651
2670
  // 会话正在处理中且被阻塞在等待用户响应时,切换回来后需要重新弹出对话框
2652
- const pendingPermissions = conversationManager.getPendingPermissionRequests(sessionId);
2671
+ const pendingPermissions = conversationManager.getPendingPermissionRequests(targetSessionId);
2653
2672
  for (const req of pendingPermissions) {
2654
2673
  sendMessage(ws, {
2655
2674
  type: 'permission_request',
2656
- payload: { ...req, sessionId },
2675
+ payload: { ...req, sessionId: targetSessionId },
2657
2676
  });
2658
2677
  console.log(`[WebSocket] Resending pending permission request: ${req.tool} (${req.requestId})`);
2659
2678
  }
2660
- const pendingQuestions = conversationManager.getUndeliveredPendingUserQuestions(sessionId);
2679
+ const pendingQuestions = conversationManager.getUndeliveredPendingUserQuestions(targetSessionId);
2661
2680
  for (const q of pendingQuestions) {
2662
2681
  sendMessage(ws, {
2663
2682
  type: 'user_question',
2664
- payload: { ...q, sessionId },
2683
+ payload: { ...q, sessionId: targetSessionId },
2665
2684
  });
2666
- conversationManager.markPendingUserQuestionDelivered(sessionId, q.requestId);
2685
+ conversationManager.markPendingUserQuestionDelivered(targetSessionId, q.requestId);
2667
2686
  console.log(`[WebSocket] Resending pending user question: ${q.header} (${q.requestId})`);
2668
2687
  }
2669
2688
  }
2670
- else if (conversationManager.needsContinuation(sessionId)) {
2689
+ else if (conversationManager.needsContinuation(targetSessionId)) {
2671
2690
  // SelfEvolve 重启等场景:工具结果已保存但模型还没来得及继续回复
2672
2691
  // 自动触发对话继续,让模型接着上次中断的地方回复
2673
- console.log(`[WebSocket] Session ${sessionId} needs continuation (last message is tool_result), auto-triggering`);
2692
+ console.log(`[WebSocket] Session ${targetSessionId} needs continuation (last message is tool_result), auto-triggering`);
2674
2693
  const continueMessageId = randomUUID();
2675
- const chatSessionId = sessionId;
2694
+ const chatSessionId = targetSessionId;
2676
2695
  const getActiveWs = () => {
2677
2696
  return conversationManager.getWebSocket(chatSessionId) || ws;
2678
2697
  };
@@ -2983,19 +3002,27 @@ async function handleSessionImport(client, content, format, conversationManager)
2983
3002
  async function handleSessionResume(client, sessionId, conversationManager) {
2984
3003
  const { ws } = client;
2985
3004
  try {
2986
- const success = await conversationManager.resumeSession(sessionId, client.permissionMode);
3005
+ let targetSessionId = sessionId;
3006
+ let success = await conversationManager.resumeSession(targetSessionId, client.permissionMode);
3007
+ if (!success) {
3008
+ const resolvedSessionId = resolveSessionRestoreTargetId(conversationManager, targetSessionId);
3009
+ if (resolvedSessionId !== targetSessionId) {
3010
+ targetSessionId = resolvedSessionId;
3011
+ success = await conversationManager.resumeSession(targetSessionId, client.permissionMode);
3012
+ }
3013
+ }
2987
3014
  if (success) {
2988
- client.sessionId = sessionId;
3015
+ client.sessionId = targetSessionId;
2989
3016
  // 重要:更新会话的 WebSocket 连接,确保 UserInteractionHandler 和 TaskManager 使用新连接
2990
- conversationManager.setWebSocket(sessionId, ws);
2991
- const history = conversationManager.getHistory(sessionId);
2992
- const sessionRuntimeBackend = conversationManager.getSessionRuntimeBackend(sessionId) || webAuth.getRuntimeBackend();
2993
- const sessionModel = conversationManager.getSessionModel(sessionId) || getDefaultChatModel(sessionRuntimeBackend);
3017
+ conversationManager.setWebSocket(targetSessionId, ws);
3018
+ const history = conversationManager.getHistory(targetSessionId);
3019
+ const sessionRuntimeBackend = conversationManager.getSessionRuntimeBackend(targetSessionId) || webAuth.getRuntimeBackend();
3020
+ const sessionModel = conversationManager.getSessionModel(targetSessionId) || getDefaultChatModel(sessionRuntimeBackend);
2994
3021
  client.model = sessionModel;
2995
3022
  client.runtimeBackend = sessionRuntimeBackend;
2996
3023
  sendMessage(ws, {
2997
3024
  type: 'session_switched',
2998
- payload: { sessionId, history, model: sessionModel, runtimeBackend: sessionRuntimeBackend },
3025
+ payload: { sessionId: targetSessionId, history, model: sessionModel, runtimeBackend: sessionRuntimeBackend },
2999
3026
  });
3000
3027
  }
3001
3028
  else {