@jingyi0605/codingns4dsh 0.2.1-beta.4 → 0.2.1-beta.6

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 (459) hide show
  1. package/README.en.md +134 -159
  2. package/README.md +128 -261
  3. package/assets/provider-icons/doubao.png +0 -0
  4. package/data/build/dist/client/account-bar.d.ts +1 -1
  5. package/data/build/dist/client/account-bar.d.ts.map +1 -1
  6. package/data/build/dist/client/account-bar.js +22 -14
  7. package/data/build/dist/client/account-bar.js.map +1 -1
  8. package/data/build/dist/client/adapter-catalog-watch.d.ts +8 -0
  9. package/data/build/dist/client/adapter-catalog-watch.d.ts.map +1 -0
  10. package/data/build/dist/client/adapter-catalog-watch.js +79 -0
  11. package/data/build/dist/client/adapter-catalog-watch.js.map +1 -0
  12. package/data/build/dist/client/avatar/catalog-panel.d.ts +1 -1
  13. package/data/build/dist/client/avatar/catalog-panel.d.ts.map +1 -1
  14. package/data/build/dist/client/avatar/catalog-panel.js +13 -11
  15. package/data/build/dist/client/avatar/catalog-panel.js.map +1 -1
  16. package/data/build/dist/client/avatar/engine.d.ts.map +1 -1
  17. package/data/build/dist/client/avatar/engine.js +26 -7
  18. package/data/build/dist/client/avatar/engine.js.map +1 -1
  19. package/data/build/dist/client/avatar/live2d.d.ts +2 -0
  20. package/data/build/dist/client/avatar/live2d.d.ts.map +1 -1
  21. package/data/build/dist/client/avatar/live2d.js +16 -6
  22. package/data/build/dist/client/avatar/live2d.js.map +1 -1
  23. package/data/build/dist/client/avatar/manager.d.ts.map +1 -1
  24. package/data/build/dist/client/avatar/manager.js +8 -2
  25. package/data/build/dist/client/avatar/manager.js.map +1 -1
  26. package/data/build/dist/client/avatar/slot.d.ts.map +1 -1
  27. package/data/build/dist/client/avatar/slot.js +4 -1
  28. package/data/build/dist/client/avatar/slot.js.map +1 -1
  29. package/data/build/dist/client/bundle.js +48459 -98385
  30. package/data/build/dist/client/bundle.js.map +1 -1
  31. package/data/build/dist/client/cli-catalog.d.ts +5 -0
  32. package/data/build/dist/client/cli-catalog.d.ts.map +1 -1
  33. package/data/build/dist/client/cli-catalog.js +15 -0
  34. package/data/build/dist/client/cli-catalog.js.map +1 -1
  35. package/data/build/dist/client/cli-slots.d.ts.map +1 -1
  36. package/data/build/dist/client/cli-slots.js +7 -45
  37. package/data/build/dist/client/cli-slots.js.map +1 -1
  38. package/data/build/dist/client/client.assistant-configuration-view.js +4526 -0
  39. package/data/build/dist/client/client.assistant-configuration-view.js.map +1 -0
  40. package/data/build/dist/client/client.assistant-debug-workbench.js +764 -0
  41. package/data/build/dist/client/client.assistant-debug-workbench.js.map +1 -0
  42. package/data/build/dist/client/client.assistant-prompt-editor.js +76 -0
  43. package/data/build/dist/client/client.assistant-prompt-editor.js.map +1 -0
  44. package/data/build/dist/client/client.assistant-prompts.js +44 -0
  45. package/data/build/dist/client/client.assistant-prompts.js.map +1 -0
  46. package/data/build/dist/client/client.assistant-voice-sessions.js +144 -0
  47. package/data/build/dist/client/client.assistant-voice-sessions.js.map +1 -0
  48. package/data/build/dist/client/client.assistant-workbench.js +2929 -0
  49. package/data/build/dist/client/client.assistant-workbench.js.map +1 -0
  50. package/data/build/dist/client/client.delegate-command.js +1315 -0
  51. package/data/build/dist/client/client.delegate-command.js.map +1 -0
  52. package/data/build/dist/client/client.editor-engine.js +32486 -0
  53. package/data/build/dist/client/client.editor-engine.js.map +1 -0
  54. package/data/build/dist/client/client.manager.js +3454 -0
  55. package/data/build/dist/client/client.manager.js.map +1 -0
  56. package/data/build/dist/client/client.model-catalog-cache.js +543 -0
  57. package/data/build/dist/client/client.model-catalog-cache.js.map +1 -0
  58. package/data/build/dist/client/client.native-workspace-store.js +689 -0
  59. package/data/build/dist/client/client.native-workspace-store.js.map +1 -0
  60. package/data/build/dist/client/client.primitives-adapter.js +333 -0
  61. package/data/build/dist/client/client.primitives-adapter.js.map +1 -0
  62. package/data/build/dist/client/client.react-dom.js +7286 -0
  63. package/data/build/dist/client/client.react-dom.js.map +1 -0
  64. package/data/build/dist/client/client.rolldown-runtime.js +59 -0
  65. package/data/build/dist/client/client.theme.js +386 -0
  66. package/data/build/dist/client/client.theme.js.map +1 -0
  67. package/data/build/dist/client/client.transport.js +3323 -0
  68. package/data/build/dist/client/client.transport.js.map +1 -0
  69. package/data/build/dist/client/client.xterm-engine.js +13064 -0
  70. package/data/build/dist/client/client.xterm-engine.js.map +1 -0
  71. package/data/build/dist/client/debug/ui.d.ts.map +1 -1
  72. package/data/build/dist/client/debug/ui.js +14 -5
  73. package/data/build/dist/client/debug/ui.js.map +1 -1
  74. package/data/build/dist/client/desktop-assistant.js +19 -5
  75. package/data/build/dist/client/editor-engine.d.ts +4 -0
  76. package/data/build/dist/client/editor-engine.d.ts.map +1 -0
  77. package/data/build/dist/client/editor-engine.js +50 -0
  78. package/data/build/dist/client/editor-engine.js.map +1 -0
  79. package/data/build/dist/client/engine-loader.d.ts +5 -0
  80. package/data/build/dist/client/engine-loader.d.ts.map +1 -0
  81. package/data/build/dist/client/engine-loader.js +35 -0
  82. package/data/build/dist/client/engine-loader.js.map +1 -0
  83. package/data/build/dist/client/features/assistant-configuration-loader.d.ts +14 -0
  84. package/data/build/dist/client/features/assistant-configuration-loader.d.ts.map +1 -0
  85. package/data/build/dist/client/features/assistant-configuration-loader.js +13 -0
  86. package/data/build/dist/client/features/assistant-configuration-loader.js.map +1 -0
  87. package/data/build/dist/client/features/assistant-configuration-session.d.ts.map +1 -1
  88. package/data/build/dist/client/features/assistant-configuration-session.js +13 -4
  89. package/data/build/dist/client/features/assistant-configuration-session.js.map +1 -1
  90. package/data/build/dist/client/features/assistant-configuration-view.d.ts +66 -0
  91. package/data/build/dist/client/features/assistant-configuration-view.d.ts.map +1 -0
  92. package/data/build/dist/client/features/assistant-configuration-view.js +133 -0
  93. package/data/build/dist/client/features/assistant-configuration-view.js.map +1 -0
  94. package/data/build/dist/client/features/assistant-debug-workbench.d.ts +4 -11
  95. package/data/build/dist/client/features/assistant-debug-workbench.d.ts.map +1 -1
  96. package/data/build/dist/client/features/assistant-debug-workbench.js +41 -68
  97. package/data/build/dist/client/features/assistant-debug-workbench.js.map +1 -1
  98. package/data/build/dist/client/features/assistant-display-store.d.ts +57 -0
  99. package/data/build/dist/client/features/assistant-display-store.d.ts.map +1 -0
  100. package/data/build/dist/client/features/assistant-display-store.js +189 -0
  101. package/data/build/dist/client/features/assistant-display-store.js.map +1 -0
  102. package/data/build/dist/client/features/assistant-prompt-editor.d.ts +12 -0
  103. package/data/build/dist/client/features/assistant-prompt-editor.d.ts.map +1 -0
  104. package/data/build/dist/client/features/assistant-prompt-editor.js +14 -0
  105. package/data/build/dist/client/features/assistant-prompt-editor.js.map +1 -0
  106. package/data/build/dist/client/features/assistant-view-loader.d.ts +17 -0
  107. package/data/build/dist/client/features/assistant-view-loader.d.ts.map +1 -0
  108. package/data/build/dist/client/features/assistant-view-loader.js +49 -0
  109. package/data/build/dist/client/features/assistant-view-loader.js.map +1 -0
  110. package/data/build/dist/client/features/assistant-workbench.d.ts +1 -60
  111. package/data/build/dist/client/features/assistant-workbench.d.ts.map +1 -1
  112. package/data/build/dist/client/features/assistant-workbench.js +41 -169
  113. package/data/build/dist/client/features/assistant-workbench.js.map +1 -1
  114. package/data/build/dist/client/features/cli-adapters.d.ts.map +1 -1
  115. package/data/build/dist/client/features/cli-adapters.js +44 -13
  116. package/data/build/dist/client/features/cli-adapters.js.map +1 -1
  117. package/data/build/dist/client/features/global-voice-assistant.d.ts.map +1 -1
  118. package/data/build/dist/client/features/global-voice-assistant.js +33 -27
  119. package/data/build/dist/client/features/global-voice-assistant.js.map +1 -1
  120. package/data/build/dist/client/features/peer-host.d.ts +2 -1
  121. package/data/build/dist/client/features/peer-host.d.ts.map +1 -1
  122. package/data/build/dist/client/features/peer-host.js +124 -58
  123. package/data/build/dist/client/features/peer-host.js.map +1 -1
  124. package/data/build/dist/client/features/workspace-session-enhancement.d.ts.map +1 -1
  125. package/data/build/dist/client/features/workspace-session-enhancement.js +37 -10
  126. package/data/build/dist/client/features/workspace-session-enhancement.js.map +1 -1
  127. package/data/build/dist/client/file-management-dom.d.ts +3 -1
  128. package/data/build/dist/client/file-management-dom.d.ts.map +1 -1
  129. package/data/build/dist/client/file-management-dom.js +85 -79
  130. package/data/build/dist/client/file-management-dom.js.map +1 -1
  131. package/data/build/dist/client/git-management.d.ts +1 -1
  132. package/data/build/dist/client/git-management.d.ts.map +1 -1
  133. package/data/build/dist/client/git-management.js +46 -27
  134. package/data/build/dist/client/git-management.js.map +1 -1
  135. package/data/build/dist/client/locale.d.ts.map +1 -1
  136. package/data/build/dist/client/locale.js +10 -0
  137. package/data/build/dist/client/locale.js.map +1 -1
  138. package/data/build/dist/client/locales/assistantAvatar.d.ts +1 -1
  139. package/data/build/dist/client/locales/assistantAvatar.js +2 -2
  140. package/data/build/dist/client/locales/assistantAvatar.js.map +1 -1
  141. package/data/build/dist/client/locales/fileWorkspace.d.ts.map +1 -1
  142. package/data/build/dist/client/locales/fileWorkspace.js +2 -0
  143. package/data/build/dist/client/locales/fileWorkspace.js.map +1 -1
  144. package/data/build/dist/client/locales/peerHost.d.ts.map +1 -1
  145. package/data/build/dist/client/locales/peerHost.js +4 -0
  146. package/data/build/dist/client/locales/peerHost.js.map +1 -1
  147. package/data/build/dist/client/locales/peerHostWorkspace.js +2 -2
  148. package/data/build/dist/client/locales/peerHostWorkspace.js.map +1 -1
  149. package/data/build/dist/client/locales/usage.d.ts.map +1 -1
  150. package/data/build/dist/client/locales/usage.js +4 -0
  151. package/data/build/dist/client/locales/usage.js.map +1 -1
  152. package/data/build/dist/client/model-catalog-cache.d.ts.map +1 -1
  153. package/data/build/dist/client/model-catalog-cache.js +9 -2
  154. package/data/build/dist/client/model-catalog-cache.js.map +1 -1
  155. package/data/build/dist/client/peer-host-management-api.d.ts +2 -2
  156. package/data/build/dist/client/peer-host-management-api.d.ts.map +1 -1
  157. package/data/build/dist/client/peer-host-management-api.js +8 -5
  158. package/data/build/dist/client/peer-host-management-api.js.map +1 -1
  159. package/data/build/dist/client/provider-icon-assets.js +5 -39
  160. package/data/build/dist/client/provider-icon-assets.js.map +1 -1
  161. package/data/build/dist/client/provider-icon-bridge.d.ts +6 -0
  162. package/data/build/dist/client/provider-icon-bridge.d.ts.map +1 -0
  163. package/data/build/dist/client/provider-icon-bridge.js +65 -0
  164. package/data/build/dist/client/provider-icon-bridge.js.map +1 -0
  165. package/data/build/dist/client/provider-icons.d.ts +1 -0
  166. package/data/build/dist/client/provider-icons.d.ts.map +1 -1
  167. package/data/build/dist/client/provider-icons.js +2 -1
  168. package/data/build/dist/client/provider-icons.js.map +1 -1
  169. package/data/build/dist/client/remote-web-context.d.ts +2 -0
  170. package/data/build/dist/client/remote-web-context.d.ts.map +1 -1
  171. package/data/build/dist/client/remote-web-context.js +50 -2
  172. package/data/build/dist/client/remote-web-context.js.map +1 -1
  173. package/data/build/dist/client/rpc-call.d.ts +4 -0
  174. package/data/build/dist/client/rpc-call.d.ts.map +1 -0
  175. package/data/build/dist/client/rpc-call.js +23 -0
  176. package/data/build/dist/client/rpc-call.js.map +1 -0
  177. package/data/build/dist/client/serial-polling.d.ts +15 -0
  178. package/data/build/dist/client/serial-polling.d.ts.map +1 -0
  179. package/data/build/dist/client/serial-polling.js +48 -0
  180. package/data/build/dist/client/serial-polling.js.map +1 -0
  181. package/data/build/dist/client/session-adapter-cache.d.ts.map +1 -1
  182. package/data/build/dist/client/session-adapter-cache.js +11 -1
  183. package/data/build/dist/client/session-adapter-cache.js.map +1 -1
  184. package/data/build/dist/client/settings-section.js +8 -2
  185. package/data/build/dist/client/settings-section.js.map +1 -1
  186. package/data/build/dist/client/sherpa-voice-adapter.d.ts.map +1 -1
  187. package/data/build/dist/client/sherpa-voice-adapter.js +8 -8
  188. package/data/build/dist/client/sherpa-voice-adapter.js.map +1 -1
  189. package/data/build/dist/client/subscription-slot.d.ts +11 -0
  190. package/data/build/dist/client/subscription-slot.d.ts.map +1 -1
  191. package/data/build/dist/client/subscription-slot.js +42 -15
  192. package/data/build/dist/client/subscription-slot.js.map +1 -1
  193. package/data/build/dist/client/terminal/xterm-engine.d.ts +4 -0
  194. package/data/build/dist/client/terminal/xterm-engine.d.ts.map +1 -0
  195. package/data/build/dist/client/terminal/xterm-engine.js +5 -0
  196. package/data/build/dist/client/terminal/xterm-engine.js.map +1 -0
  197. package/data/build/dist/client/terminal/xterm-view.d.ts.map +1 -1
  198. package/data/build/dist/client/terminal/xterm-view.js +33 -25
  199. package/data/build/dist/client/terminal/xterm-view.js.map +1 -1
  200. package/data/build/dist/host/avatar/temporary-previews.d.ts +3 -1
  201. package/data/build/dist/host/avatar/temporary-previews.d.ts.map +1 -1
  202. package/data/build/dist/host/avatar/temporary-previews.js +7 -2
  203. package/data/build/dist/host/avatar/temporary-previews.js.map +1 -1
  204. package/data/build/dist/host/cli-adapters/acp-cli-driver.d.ts +1 -1
  205. package/data/build/dist/host/cli-adapters/acp-cli-driver.d.ts.map +1 -1
  206. package/data/build/dist/host/cli-adapters/acp-cli-driver.js +3 -10
  207. package/data/build/dist/host/cli-adapters/acp-cli-driver.js.map +1 -1
  208. package/data/build/dist/host/cli-adapters/antigravity-driver.d.ts.map +1 -1
  209. package/data/build/dist/host/cli-adapters/antigravity-driver.js +2 -2
  210. package/data/build/dist/host/cli-adapters/antigravity-driver.js.map +1 -1
  211. package/data/build/dist/host/cli-adapters/antigravity-subscription.d.ts.map +1 -1
  212. package/data/build/dist/host/cli-adapters/antigravity-subscription.js +10 -10
  213. package/data/build/dist/host/cli-adapters/antigravity-subscription.js.map +1 -1
  214. package/data/build/dist/host/cli-adapters/binary-detection.d.ts +19 -0
  215. package/data/build/dist/host/cli-adapters/binary-detection.d.ts.map +1 -0
  216. package/data/build/dist/host/cli-adapters/binary-detection.js +71 -0
  217. package/data/build/dist/host/cli-adapters/binary-detection.js.map +1 -0
  218. package/data/build/dist/host/cli-adapters/claude-driver.d.ts +2 -0
  219. package/data/build/dist/host/cli-adapters/claude-driver.d.ts.map +1 -1
  220. package/data/build/dist/host/cli-adapters/claude-driver.js +11 -5
  221. package/data/build/dist/host/cli-adapters/claude-driver.js.map +1 -1
  222. package/data/build/dist/host/cli-adapters/claude-model-options.d.ts.map +1 -1
  223. package/data/build/dist/host/cli-adapters/claude-model-options.js +2 -1
  224. package/data/build/dist/host/cli-adapters/claude-model-options.js.map +1 -1
  225. package/data/build/dist/host/cli-adapters/claude-process.d.ts +7 -0
  226. package/data/build/dist/host/cli-adapters/claude-process.d.ts.map +1 -0
  227. package/data/build/dist/host/cli-adapters/claude-process.js +59 -0
  228. package/data/build/dist/host/cli-adapters/claude-process.js.map +1 -0
  229. package/data/build/dist/host/cli-adapters/codebuddy-driver.d.ts +3 -0
  230. package/data/build/dist/host/cli-adapters/codebuddy-driver.d.ts.map +1 -1
  231. package/data/build/dist/host/cli-adapters/codebuddy-driver.js +26 -12
  232. package/data/build/dist/host/cli-adapters/codebuddy-driver.js.map +1 -1
  233. package/data/build/dist/host/cli-adapters/command-code-driver.d.ts +0 -1
  234. package/data/build/dist/host/cli-adapters/command-code-driver.d.ts.map +1 -1
  235. package/data/build/dist/host/cli-adapters/command-code-driver.js +10 -32
  236. package/data/build/dist/host/cli-adapters/command-code-driver.js.map +1 -1
  237. package/data/build/dist/host/cli-adapters/cursor-driver.d.ts.map +1 -1
  238. package/data/build/dist/host/cli-adapters/cursor-driver.js +4 -3
  239. package/data/build/dist/host/cli-adapters/cursor-driver.js.map +1 -1
  240. package/data/build/dist/host/cli-adapters/delegate-dispatch.js +1 -1
  241. package/data/build/dist/host/cli-adapters/delegate-dispatch.js.map +1 -1
  242. package/data/build/dist/host/cli-adapters/delegation-mention-rewrite.d.ts +2 -0
  243. package/data/build/dist/host/cli-adapters/delegation-mention-rewrite.d.ts.map +1 -1
  244. package/data/build/dist/host/cli-adapters/delegation-mention-rewrite.js +5 -0
  245. package/data/build/dist/host/cli-adapters/delegation-mention-rewrite.js.map +1 -1
  246. package/data/build/dist/host/cli-adapters/desktop-app-runtime.d.ts.map +1 -1
  247. package/data/build/dist/host/cli-adapters/desktop-app-runtime.js +2 -4
  248. package/data/build/dist/host/cli-adapters/desktop-app-runtime.js.map +1 -1
  249. package/data/build/dist/host/cli-adapters/doubao-app.d.ts +27 -0
  250. package/data/build/dist/host/cli-adapters/doubao-app.d.ts.map +1 -0
  251. package/data/build/dist/host/cli-adapters/doubao-app.js +110 -0
  252. package/data/build/dist/host/cli-adapters/doubao-app.js.map +1 -0
  253. package/data/build/dist/host/cli-adapters/doubao-artifact-store.d.ts +16 -0
  254. package/data/build/dist/host/cli-adapters/doubao-artifact-store.d.ts.map +1 -0
  255. package/data/build/dist/host/cli-adapters/doubao-artifact-store.js +142 -0
  256. package/data/build/dist/host/cli-adapters/doubao-artifact-store.js.map +1 -0
  257. package/data/build/dist/host/cli-adapters/doubao-artifacts.d.ts +16 -0
  258. package/data/build/dist/host/cli-adapters/doubao-artifacts.d.ts.map +1 -0
  259. package/data/build/dist/host/cli-adapters/doubao-artifacts.js +34 -0
  260. package/data/build/dist/host/cli-adapters/doubao-artifacts.js.map +1 -0
  261. package/data/build/dist/host/cli-adapters/doubao-cdp.d.ts +49 -0
  262. package/data/build/dist/host/cli-adapters/doubao-cdp.d.ts.map +1 -0
  263. package/data/build/dist/host/cli-adapters/doubao-cdp.js +177 -0
  264. package/data/build/dist/host/cli-adapters/doubao-cdp.js.map +1 -0
  265. package/data/build/dist/host/cli-adapters/doubao-driver.d.ts +33 -0
  266. package/data/build/dist/host/cli-adapters/doubao-driver.d.ts.map +1 -0
  267. package/data/build/dist/host/cli-adapters/doubao-driver.js +291 -0
  268. package/data/build/dist/host/cli-adapters/doubao-driver.js.map +1 -0
  269. package/data/build/dist/host/cli-adapters/doubao-events.d.ts +21 -0
  270. package/data/build/dist/host/cli-adapters/doubao-events.d.ts.map +1 -0
  271. package/data/build/dist/host/cli-adapters/doubao-events.js +126 -0
  272. package/data/build/dist/host/cli-adapters/doubao-events.js.map +1 -0
  273. package/data/build/dist/host/cli-adapters/doubao-runtime.d.ts +6 -0
  274. package/data/build/dist/host/cli-adapters/doubao-runtime.d.ts.map +1 -0
  275. package/data/build/dist/host/cli-adapters/doubao-runtime.js +176 -0
  276. package/data/build/dist/host/cli-adapters/doubao-runtime.js.map +1 -0
  277. package/data/build/dist/host/cli-adapters/doubao-tools.d.ts +8 -0
  278. package/data/build/dist/host/cli-adapters/doubao-tools.d.ts.map +1 -0
  279. package/data/build/dist/host/cli-adapters/doubao-tools.js +139 -0
  280. package/data/build/dist/host/cli-adapters/doubao-tools.js.map +1 -0
  281. package/data/build/dist/host/cli-adapters/driver.d.ts +4 -3
  282. package/data/build/dist/host/cli-adapters/driver.d.ts.map +1 -1
  283. package/data/build/dist/host/cli-adapters/feature.d.ts.map +1 -1
  284. package/data/build/dist/host/cli-adapters/feature.js +30 -36
  285. package/data/build/dist/host/cli-adapters/feature.js.map +1 -1
  286. package/data/build/dist/host/cli-adapters/grok-driver.d.ts.map +1 -1
  287. package/data/build/dist/host/cli-adapters/grok-driver.js +2 -1
  288. package/data/build/dist/host/cli-adapters/grok-driver.js.map +1 -1
  289. package/data/build/dist/host/cli-adapters/json-rpc-process.d.ts.map +1 -1
  290. package/data/build/dist/host/cli-adapters/json-rpc-process.js +3 -1
  291. package/data/build/dist/host/cli-adapters/json-rpc-process.js.map +1 -1
  292. package/data/build/dist/host/cli-adapters/kimi-driver.d.ts.map +1 -1
  293. package/data/build/dist/host/cli-adapters/kimi-driver.js +4 -3
  294. package/data/build/dist/host/cli-adapters/kimi-driver.js.map +1 -1
  295. package/data/build/dist/host/cli-adapters/legacy-session-adapter.d.ts +2 -0
  296. package/data/build/dist/host/cli-adapters/legacy-session-adapter.d.ts.map +1 -1
  297. package/data/build/dist/host/cli-adapters/legacy-session-adapter.js +11 -0
  298. package/data/build/dist/host/cli-adapters/legacy-session-adapter.js.map +1 -1
  299. package/data/build/dist/host/cli-adapters/log-files.d.ts +3 -0
  300. package/data/build/dist/host/cli-adapters/log-files.d.ts.map +1 -0
  301. package/data/build/dist/host/cli-adapters/log-files.js +32 -0
  302. package/data/build/dist/host/cli-adapters/log-files.js.map +1 -0
  303. package/data/build/dist/host/cli-adapters/model-catalog.d.ts +2 -0
  304. package/data/build/dist/host/cli-adapters/model-catalog.d.ts.map +1 -1
  305. package/data/build/dist/host/cli-adapters/model-catalog.js +10 -0
  306. package/data/build/dist/host/cli-adapters/model-catalog.js.map +1 -1
  307. package/data/build/dist/host/cli-adapters/native-team-subagent.js +1 -1
  308. package/data/build/dist/host/cli-adapters/native-team-subagent.js.map +1 -1
  309. package/data/build/dist/host/cli-adapters/opencode-driver.d.ts +11 -0
  310. package/data/build/dist/host/cli-adapters/opencode-driver.d.ts.map +1 -1
  311. package/data/build/dist/host/cli-adapters/opencode-driver.js +132 -49
  312. package/data/build/dist/host/cli-adapters/opencode-driver.js.map +1 -1
  313. package/data/build/dist/host/cli-adapters/opencode-v2-protocol.d.ts +29 -0
  314. package/data/build/dist/host/cli-adapters/opencode-v2-protocol.d.ts.map +1 -0
  315. package/data/build/dist/host/cli-adapters/opencode-v2-protocol.js +471 -0
  316. package/data/build/dist/host/cli-adapters/opencode-v2-protocol.js.map +1 -0
  317. package/data/build/dist/host/cli-adapters/pi-driver.d.ts.map +1 -1
  318. package/data/build/dist/host/cli-adapters/pi-driver.js +2 -1
  319. package/data/build/dist/host/cli-adapters/pi-driver.js.map +1 -1
  320. package/data/build/dist/host/cli-adapters/process-utils.d.ts +12 -4
  321. package/data/build/dist/host/cli-adapters/process-utils.d.ts.map +1 -1
  322. package/data/build/dist/host/cli-adapters/process-utils.js +151 -17
  323. package/data/build/dist/host/cli-adapters/process-utils.js.map +1 -1
  324. package/data/build/dist/host/cli-adapters/qoder-driver.d.ts.map +1 -1
  325. package/data/build/dist/host/cli-adapters/qoder-driver.js +63 -100
  326. package/data/build/dist/host/cli-adapters/qoder-driver.js.map +1 -1
  327. package/data/build/dist/host/cli-adapters/qoder-subscription.d.ts +6 -1
  328. package/data/build/dist/host/cli-adapters/qoder-subscription.d.ts.map +1 -1
  329. package/data/build/dist/host/cli-adapters/qoder-subscription.js +37 -10
  330. package/data/build/dist/host/cli-adapters/qoder-subscription.js.map +1 -1
  331. package/data/build/dist/host/cli-adapters/registry.d.ts +13 -21
  332. package/data/build/dist/host/cli-adapters/registry.d.ts.map +1 -1
  333. package/data/build/dist/host/cli-adapters/registry.js +102 -131
  334. package/data/build/dist/host/cli-adapters/registry.js.map +1 -1
  335. package/data/build/dist/host/cli-adapters/rpc-driver-utils.d.ts +2 -10
  336. package/data/build/dist/host/cli-adapters/rpc-driver-utils.d.ts.map +1 -1
  337. package/data/build/dist/host/cli-adapters/rpc-driver-utils.js +1 -28
  338. package/data/build/dist/host/cli-adapters/rpc-driver-utils.js.map +1 -1
  339. package/data/build/dist/host/cli-adapters/session-store.d.ts +5 -1
  340. package/data/build/dist/host/cli-adapters/session-store.d.ts.map +1 -1
  341. package/data/build/dist/host/cli-adapters/session-store.js +68 -11
  342. package/data/build/dist/host/cli-adapters/session-store.js.map +1 -1
  343. package/data/build/dist/host/cli-adapters/standard-stream-driver.d.ts +3 -3
  344. package/data/build/dist/host/cli-adapters/standard-stream-driver.d.ts.map +1 -1
  345. package/data/build/dist/host/cli-adapters/standard-stream-driver.js +14 -38
  346. package/data/build/dist/host/cli-adapters/standard-stream-driver.js.map +1 -1
  347. package/data/build/dist/host/cli-adapters/windows-command-environment.d.ts +12 -0
  348. package/data/build/dist/host/cli-adapters/windows-command-environment.d.ts.map +1 -0
  349. package/data/build/dist/host/cli-adapters/windows-command-environment.js +53 -0
  350. package/data/build/dist/host/cli-adapters/windows-command-environment.js.map +1 -0
  351. package/data/build/dist/host/cli-bridge/dispatch.js +1 -1
  352. package/data/build/dist/host/cli-bridge/dispatch.js.map +1 -1
  353. package/data/build/dist/host/debug.d.ts.map +1 -1
  354. package/data/build/dist/host/debug.js +5 -4
  355. package/data/build/dist/host/debug.js.map +1 -1
  356. package/data/build/dist/host/dsh-runtime-version.d.ts +1 -1
  357. package/data/build/dist/host/dsh-runtime-version.d.ts.map +1 -1
  358. package/data/build/dist/host/dsh-runtime-version.js +22 -17
  359. package/data/build/dist/host/dsh-runtime-version.js.map +1 -1
  360. package/data/build/dist/host/features/assistant-avatar-runtime.d.ts.map +1 -1
  361. package/data/build/dist/host/features/assistant-avatar-runtime.js +43 -19
  362. package/data/build/dist/host/features/assistant-avatar-runtime.js.map +1 -1
  363. package/data/build/dist/host/features/assistant-background.d.ts +44 -0
  364. package/data/build/dist/host/features/assistant-background.d.ts.map +1 -0
  365. package/data/build/dist/host/features/assistant-background.js +116 -0
  366. package/data/build/dist/host/features/assistant-background.js.map +1 -0
  367. package/data/build/dist/host/features/assistant-index-updates.d.ts +5 -0
  368. package/data/build/dist/host/features/assistant-index-updates.d.ts.map +1 -1
  369. package/data/build/dist/host/features/assistant-index-updates.js +29 -6
  370. package/data/build/dist/host/features/assistant-index-updates.js.map +1 -1
  371. package/data/build/dist/host/features/assistant-source-cache.d.ts +12 -0
  372. package/data/build/dist/host/features/assistant-source-cache.d.ts.map +1 -0
  373. package/data/build/dist/host/features/assistant-source-cache.js +58 -0
  374. package/data/build/dist/host/features/assistant-source-cache.js.map +1 -0
  375. package/data/build/dist/host/features/global-voice-coordinator.d.ts.map +1 -1
  376. package/data/build/dist/host/features/global-voice-coordinator.js +15 -10
  377. package/data/build/dist/host/features/global-voice-coordinator.js.map +1 -1
  378. package/data/build/dist/host/features/global-voice-rpc.d.ts.map +1 -1
  379. package/data/build/dist/host/features/global-voice-rpc.js +288 -114
  380. package/data/build/dist/host/features/global-voice-rpc.js.map +1 -1
  381. package/data/build/dist/host/features/peer-host.d.ts.map +1 -1
  382. package/data/build/dist/host/features/peer-host.js +61 -21
  383. package/data/build/dist/host/features/peer-host.js.map +1 -1
  384. package/data/build/dist/host/features/sherpa-voice-worker.d.ts +18 -0
  385. package/data/build/dist/host/features/sherpa-voice-worker.d.ts.map +1 -0
  386. package/data/build/dist/host/features/sherpa-voice-worker.js +40 -0
  387. package/data/build/dist/host/features/sherpa-voice-worker.js.map +1 -0
  388. package/data/build/dist/host/features/sherpa-worker-runtime.d.ts +41 -0
  389. package/data/build/dist/host/features/sherpa-worker-runtime.d.ts.map +1 -0
  390. package/data/build/dist/host/features/sherpa-worker-runtime.js +200 -0
  391. package/data/build/dist/host/features/sherpa-worker-runtime.js.map +1 -0
  392. package/data/build/dist/host/features/types.d.ts +6 -4
  393. package/data/build/dist/host/features/types.d.ts.map +1 -1
  394. package/data/build/dist/host/index.d.ts +1 -1
  395. package/data/build/dist/host/index.d.ts.map +1 -1
  396. package/data/build/dist/host/index.js +31 -21
  397. package/data/build/dist/host/index.js.map +1 -1
  398. package/data/build/dist/host/lan-access-dsh.d.ts.map +1 -1
  399. package/data/build/dist/host/lan-access-dsh.js +5 -22
  400. package/data/build/dist/host/lan-access-dsh.js.map +1 -1
  401. package/data/build/dist/host/modules/peer-host/host-api-proxy-service.d.ts +6 -46
  402. package/data/build/dist/host/modules/peer-host/host-api-proxy-service.d.ts.map +1 -1
  403. package/data/build/dist/host/modules/peer-host/host-api-proxy-service.js +48 -28
  404. package/data/build/dist/host/modules/peer-host/host-api-proxy-service.js.map +1 -1
  405. package/data/build/dist/host/modules/peer-host/peer-host-diagnostics.d.ts.map +1 -1
  406. package/data/build/dist/host/modules/peer-host/peer-host-diagnostics.js +1 -0
  407. package/data/build/dist/host/modules/peer-host/peer-host-diagnostics.js.map +1 -1
  408. package/data/build/dist/host/modules/peer-host/peer-host-handshake.d.ts.map +1 -1
  409. package/data/build/dist/host/modules/peer-host/peer-host-handshake.js +4 -1
  410. package/data/build/dist/host/modules/peer-host/peer-host-handshake.js.map +1 -1
  411. package/data/build/dist/host/modules/peer-host/peer-host-session.d.ts +7 -1
  412. package/data/build/dist/host/modules/peer-host/peer-host-session.d.ts.map +1 -1
  413. package/data/build/dist/host/modules/peer-host/peer-host-session.js +40 -13
  414. package/data/build/dist/host/modules/peer-host/peer-host-session.js.map +1 -1
  415. package/data/build/dist/host/provider-icon-assets.d.ts +5 -0
  416. package/data/build/dist/host/provider-icon-assets.d.ts.map +1 -0
  417. package/data/build/dist/host/provider-icon-assets.js +61 -0
  418. package/data/build/dist/host/provider-icon-assets.js.map +1 -0
  419. package/data/build/dist/host/rpc.js +2 -2
  420. package/data/build/dist/host/rpc.js.map +1 -1
  421. package/data/build/dist/host/session-migration-repair.d.ts +4 -0
  422. package/data/build/dist/host/session-migration-repair.d.ts.map +1 -1
  423. package/data/build/dist/host/session-migration-repair.js +75 -2
  424. package/data/build/dist/host/session-migration-repair.js.map +1 -1
  425. package/data/build/dist/host/terminal/backends/tmux-backend.d.ts +1 -1
  426. package/data/build/dist/host/terminal/backends/tmux-backend.d.ts.map +1 -1
  427. package/data/build/dist/host/terminal/backends/tmux-backend.js +15 -14
  428. package/data/build/dist/host/terminal/backends/tmux-backend.js.map +1 -1
  429. package/data/build/dist/shared/assistant-avatar-engine.d.ts +5 -0
  430. package/data/build/dist/shared/assistant-avatar-engine.d.ts.map +1 -1
  431. package/data/build/dist/shared/assistant-avatar-engine.js +14 -0
  432. package/data/build/dist/shared/assistant-avatar-engine.js.map +1 -1
  433. package/data/build/dist/shared/contracts/cli-adapter.d.ts +6 -0
  434. package/data/build/dist/shared/contracts/cli-adapter.d.ts.map +1 -1
  435. package/data/build/dist/shared/contracts/errors.d.ts +1 -0
  436. package/data/build/dist/shared/contracts/errors.d.ts.map +1 -1
  437. package/data/build/dist/shared/contracts/errors.js +1 -0
  438. package/data/build/dist/shared/contracts/errors.js.map +1 -1
  439. package/data/build/dist/shared/contracts/peer-host.d.ts +1 -0
  440. package/data/build/dist/shared/contracts/peer-host.d.ts.map +1 -1
  441. package/data/build/dist/shared/contracts/peer-host.js +1 -0
  442. package/data/build/dist/shared/contracts/peer-host.js.map +1 -1
  443. package/data/build/dist/shared/contracts/version.d.ts +3 -1
  444. package/data/build/dist/shared/contracts/version.d.ts.map +1 -1
  445. package/data/build/dist/shared/contracts/version.js +20 -7
  446. package/data/build/dist/shared/contracts/version.js.map +1 -1
  447. package/data/build/dist/shared/peer-host-http-routes.d.ts +62 -0
  448. package/data/build/dist/shared/peer-host-http-routes.d.ts.map +1 -0
  449. package/data/build/dist/shared/peer-host-http-routes.js +31 -0
  450. package/data/build/dist/shared/peer-host-http-routes.js.map +1 -0
  451. package/data/build/dist/shared/provider-icon-resources.d.ts +4 -0
  452. package/data/build/dist/shared/provider-icon-resources.d.ts.map +1 -0
  453. package/data/build/dist/shared/provider-icon-resources.js +24 -0
  454. package/data/build/dist/shared/provider-icon-resources.js.map +1 -0
  455. package/package.json +2 -2
  456. package/profile/README.md +2 -2
  457. package/profile/package.json +2 -2
  458. package/profile/version.json +1 -1
  459. package/version.json +1 -1
@@ -1,11 +1,12 @@
1
1
  import { randomUUID } from 'node:crypto';
2
- import { createAssistantScope } from './assistant-scope.js';
2
+ import { createAssistantScope, getAssistantScopeState } from './assistant-scope.js';
3
3
  import { AssistantDispatcher } from './assistant-dispatch.js';
4
4
  import { AssistantVoiceTurnRouter } from './assistant-voice-turn.js';
5
5
  import { buildAssistantSessionIndex } from './assistant-session-index.js';
6
6
  import { sanitizeSpeechText, summarizeAssistantEntries } from './assistant-summary.js';
7
7
  import { parseAssistantIntent } from './assistant-intent.js';
8
- import { AssistantIndexUpdates, assistantSessionKey } from './assistant-index-updates.js';
8
+ import { AssistantIndexUpdates, assistantSessionKey, isAssistantIndexEvent } from './assistant-index-updates.js';
9
+ import { AssistantBackground } from './assistant-background.js';
9
10
  import { readAssistantPrompts } from '../../shared/assistant-prompts.js';
10
11
  import { createAssistantChatSystem } from './assistant-prompts.js';
11
12
  import { speakAssistantStructuredIndex } from './assistant-structured-index.js';
@@ -25,7 +26,7 @@ import { createAssistantVoiceActionBridge } from './voice-agent-actions.js';
25
26
  import { AssistantWaitingState } from './assistant-waiting-state.js';
26
27
  import { debugInfo } from '../../shared/debug.js';
27
28
  import { createAssistantVoiceStreamHandler } from './assistant-voice-stream.js';
28
- import { SherpaVoiceRuntime } from './sherpa-voice-runtime.js';
29
+ import { SherpaWorkerRuntime } from './sherpa-worker-runtime.js';
29
30
  import { buildAssistantVoiceHotwords, readAssistantVoiceHotwords } from './assistant-voice-hotwords.js';
30
31
  import { DEFAULT_ASSISTANT_SETTINGS, DEFAULT_ASSISTANT_VOICE_SETTINGS } from '../../shared/contracts/config.js';
31
32
  import { AssistantVoiceModelManager } from './voice-model-management.js';
@@ -38,6 +39,7 @@ import { configureAssistantSettings } from './assistant-lifecycle-settings.js';
38
39
  import { AssistantVoiceInitialization } from './assistant-voice-initialization.js';
39
40
  import { installVoiceDiagnostics } from '../voice-diagnostics.js';
40
41
  import { measureVoice, traceVoice, sanitizeVoiceDiagnosticFields } from '../../shared/voice-diagnostics.js';
42
+ import { assistantSourceCache } from './assistant-source-cache.js';
41
43
  /**
42
44
  * 全局智能助理 Host 边界。
43
45
  *
@@ -59,12 +61,17 @@ export function createGlobalVoiceRpcFeature(options = {}) {
59
61
  if (diagnostics !== undefined)
60
62
  context.resources.add(diagnostics.dispose);
61
63
  let resetting = false;
64
+ let disposed = false;
65
+ let statusRevision = 0;
66
+ let indexAbort = new AbortController();
62
67
  // 每次读取当前档案,资源准备与旧配置都不能隐式创建助理。
63
68
  const assistantProfile = () => readAssistantProfile(context.services.settings?.get().assistant ?? DEFAULT_ASSISTANT_SETTINGS);
69
+ const automaticEnabled = () => !disposed && !resetting && context.services.settings?.get().modules.globalVoiceAssistant === true
70
+ && assistantProfile().initialized && (context.services.settings?.get().assistant.managedWorkspaceIds.length ?? 0) > 0;
64
71
  let lifecycleRevision = 0;
65
72
  const tts = new AssistantTtsService(context.services, { isVoiceActive: () => coordinator.snapshot().active });
66
73
  context.resources.add(() => tts.dispose());
67
- const runtime = new SherpaVoiceRuntime({
74
+ const runtime = new SherpaWorkerRuntime({
68
75
  env: buildSherpaRuntimeEnvironment(readAssistantVoiceSettings(context.services)),
69
76
  });
70
77
  const agent = new VoiceAgentService({
@@ -91,6 +98,7 @@ export function createGlobalVoiceRpcFeature(options = {}) {
91
98
  const router = new AssistantVoiceTurnRouter(dispatcher);
92
99
  const waitingState = new AssistantWaitingState();
93
100
  let lastSnapshot = null;
101
+ const indexedEntries = new Map();
94
102
  let lastArchivedSessionIds = [];
95
103
  let buildingIndex;
96
104
  let buildingIndexRevision = 0;
@@ -101,13 +109,20 @@ export function createGlobalVoiceRpcFeature(options = {}) {
101
109
  dispatcher,
102
110
  snapshot: (signal) => readManagementSnapshot(signal),
103
111
  read: async (entry, signal) => {
112
+ const revision = lifecycleRevision;
104
113
  const managed = assistantSettings().managedWorkspaceIds;
105
- const source = await readAssistantSource(context.services, managed, waitingState);
114
+ const source = await readAssistantSource(context.services, managed, waitingState, signal);
106
115
  signal.throwIfAborted();
116
+ if (resetting || revision !== lifecycleRevision)
117
+ throw new Error('助理管理范围已变化,请重新查询');
107
118
  const current = source.sessions.find((item) => item.hostId === entry.hostId && item.sessionId === entry.sessionId && item.workspaceId === entry.workspaceId);
108
119
  if (current === undefined || source.archivedSessionIds.includes(entry.sessionId))
109
120
  throw new Error('目标会话已退出助理管理范围');
110
- return await source.readSummary?.(current) ?? null;
121
+ const summary = await source.readSummary?.(current, signal) ?? null;
122
+ signal.throwIfAborted();
123
+ if (resetting || revision !== lifecycleRevision)
124
+ throw new Error('助理管理范围已变化,请重新查询');
125
+ return summary;
111
126
  },
112
127
  });
113
128
  const managementAgent = createAssistantAgentAdapter(context.services.dshContext, context.services.dshVersion ?? minimumSupportedDshVersion(), llm, managementTools);
@@ -130,14 +145,15 @@ export function createGlobalVoiceRpcFeature(options = {}) {
130
145
  return entry.activity ?? (entry.running ? 'running' : entry.completed || entry.error === true ? 'idle' : 'unknown');
131
146
  };
132
147
  const updates = new AssistantIndexUpdates(async () => {
133
- if (resetting || !assistantProfile().initialized)
148
+ if (!automaticEnabled())
134
149
  return;
135
150
  if (indexAnalysis.read()?.state === 'running' || buildingIndex !== undefined && buildingIndexRevision === indexRevision)
136
151
  return;
137
- const snapshot = await buildIndex();
138
- if (updates.hasReady(snapshot.entries) || indexAnalysis.read()?.generation !== snapshot.generation)
139
- startIndexAnalysis(snapshot);
152
+ const snapshot = await buildIndex('automatic');
153
+ if (automaticEnabled() && (updates.hasReady(snapshot.entries) || indexAnalysis.read()?.generation !== snapshot.generation))
154
+ startIndexAnalysis(snapshot, false, true);
140
155
  }, liveActivity);
156
+ updates.setEnabled(automaticEnabled());
141
157
  context.resources.add(() => textChat.dispose());
142
158
  context.resources.add(() => indexAnalysis.dispose());
143
159
  context.resources.add(() => updates.dispose());
@@ -160,8 +176,8 @@ export function createGlobalVoiceRpcFeature(options = {}) {
160
176
  };
161
177
  const cancelIndexAnalysis = () => indexAnalysis.cancelActive();
162
178
  // 正文索引立即返回,LLM 在后台生成;轮询现有调试接口即可读取进度与结果。
163
- const startIndexAnalysis = (snapshot, retryFailures = false) => {
164
- if (resetting || lastSnapshot !== snapshot)
179
+ const startIndexAnalysis = (snapshot, retryFailures = false, automatic = false) => {
180
+ if (disposed || resetting || lastSnapshot !== snapshot || automatic && !automaticEnabled())
165
181
  return withIndexAnalysis(snapshot);
166
182
  if (snapshot.entries.length === 0) {
167
183
  cancelIndexAnalysis();
@@ -169,9 +185,10 @@ export function createGlobalVoiceRpcFeature(options = {}) {
169
185
  }
170
186
  const revision = indexRevision;
171
187
  const prompts = readAssistantPrompts(context.services.settings?.get().assistant.prompts);
172
- indexAnalysis.start(snapshot, indexSelection, prompts.index, () => lastSnapshot === snapshot && sameManagedScope(snapshot, context.services.settings?.get().assistant.managedWorkspaceIds ?? []), (run) => {
188
+ indexAnalysis.start(snapshot, indexSelection, prompts.index, () => !disposed && (!automatic || automaticEnabled()) && lastSnapshot === snapshot && sameManagedScope(snapshot, context.services.settings?.get().assistant.managedWorkspaceIds ?? []), (run) => {
173
189
  if (resetting || revision !== indexRevision || lastSnapshot !== snapshot)
174
190
  return;
191
+ statusRevision++;
175
192
  journal.updateAnalysis(run);
176
193
  for (const task of run.tasks ?? []) {
177
194
  if (task.state === 'completed')
@@ -189,9 +206,14 @@ export function createGlobalVoiceRpcFeature(options = {}) {
189
206
  return updates.canIndex(entry);
190
207
  // 远端没有本地完成事件:每个真实模型请求前重新确认空闲和版本。
191
208
  const managed = context.services.settings?.get().assistant.managedWorkspaceIds ?? [];
192
- const source = await readAssistantSource(context.services, managed, waitingState);
209
+ const source = await readAssistantSource(context.services, managed, waitingState, signal);
193
210
  signal.throwIfAborted();
211
+ if (disposed || resetting || revision !== indexRevision || automatic && !automaticEnabled())
212
+ return false;
194
213
  const metadata = await buildAssistantSessionIndex({ sessions: source.sessions, scope: createAssistantScope(managed), archivedSessionIds: source.archivedSessionIds });
214
+ signal.throwIfAborted();
215
+ if (revision !== indexRevision)
216
+ return false;
195
217
  observeVersions(metadata.entries);
196
218
  const current = metadata.entries.find((item) => assistantSessionKey(item) === assistantSessionKey(entry));
197
219
  return current !== undefined && current.activity === 'idle' && current.updatedAt === entry.updatedAt && updates.canIndex(entry);
@@ -216,12 +238,15 @@ export function createGlobalVoiceRpcFeature(options = {}) {
216
238
  textChat.cancelActive();
217
239
  voiceChat.clear();
218
240
  updates.reset();
241
+ statusRevision++;
219
242
  };
220
243
  // 刷新可以清空缓存,但索引代次必须持续递增,不能每次回到 1。
221
244
  let indexGeneration = 0;
222
245
  let indexRevision = 0;
223
246
  const observeVersions = (entries) => {
224
247
  const changed = updates.observe(entries);
248
+ if (changed)
249
+ statusRevision++;
225
250
  if (indexAnalysis.read()?.state !== 'running')
226
251
  return changed;
227
252
  for (const entry of lastSnapshot?.entries ?? [])
@@ -229,21 +254,26 @@ export function createGlobalVoiceRpcFeature(options = {}) {
229
254
  indexAnalysis.deferSession(assistantSessionKey(entry));
230
255
  return changed;
231
256
  };
232
- const buildIndex = async (trigger = 'automatic') => {
233
- if (resetting)
234
- throw new Error('助理正在重置,请稍后操作');
257
+ const buildIndex = async (trigger = 'manual') => {
258
+ if (disposed || resetting || trigger === 'automatic' && !automaticEnabled())
259
+ throw new Error('助理后台索引已停止');
235
260
  const managed = context.services.settings?.get().assistant?.managedWorkspaceIds ?? [];
236
261
  const revision = indexRevision;
262
+ const signal = indexAbort.signal;
237
263
  if (buildingIndex !== undefined && buildingIndexRevision === revision)
238
264
  return buildingIndex;
239
- const source = await readAssistantSource(context.services, managed, waitingState);
265
+ if (buildingIndex !== undefined) {
266
+ await buildingIndex.catch(() => undefined);
267
+ signal.throwIfAborted();
268
+ }
269
+ const { source, metadata } = (await background.read(trigger === 'manual' || metadataDirty)).value;
270
+ signal.throwIfAborted();
240
271
  if (resetting || revision !== indexRevision)
241
272
  throw new Error('索引任务已撤销');
242
273
  if (JSON.stringify(managed) !== JSON.stringify(context.services.settings?.get().assistant.managedWorkspaceIds ?? []))
243
- return buildIndex(trigger);
274
+ throw new Error('索引范围已变化');
244
275
  if (buildingIndex !== undefined && buildingIndexRevision === revision)
245
276
  return buildingIndex;
246
- const metadata = await buildAssistantSessionIndex({ sessions: source.sessions, scope: createAssistantScope(managed), archivedSessionIds: source.archivedSessionIds });
247
277
  if (resetting || revision !== indexRevision)
248
278
  throw new Error('索引任务已撤销');
249
279
  observeVersions(metadata.entries);
@@ -255,6 +285,7 @@ export function createGlobalVoiceRpcFeature(options = {}) {
255
285
  if (trigger !== 'manual' && lastSnapshot !== null && sameIndexMembership(lastSnapshot, metadata) && updates.matches(lastSnapshot) && materialKeys.size === 0)
256
286
  return lastSnapshot;
257
287
  const recordId = journal.begin(trigger, managed);
288
+ statusRevision++;
258
289
  const failures = new Map();
259
290
  const task = (async () => {
260
291
  lastArchivedSessionIds = source.archivedSessionIds;
@@ -272,7 +303,9 @@ export function createGlobalVoiceRpcFeature(options = {}) {
272
303
  if (cached !== undefined && cached.version === session.sourceVersion)
273
304
  return cached.summary;
274
305
  try {
275
- const summary = await source.readSummary(session);
306
+ signal.throwIfAborted();
307
+ const summary = await source.readSummary(session, signal);
308
+ signal.throwIfAborted();
276
309
  if (revision === indexRevision && session.sourceVersion !== undefined && updates.canIndex(entry))
277
310
  materials.set(key, { version: session.sourceVersion, summary });
278
311
  return summary;
@@ -282,41 +315,147 @@ export function createGlobalVoiceRpcFeature(options = {}) {
282
315
  throw error;
283
316
  }
284
317
  } }),
285
- ...(source.readWaiting === undefined ? {} : { readWaiting: (session) => materialKeys.has(assistantSessionKey(session)) ? source.readWaiting(session) : session.waiting }),
318
+ ...(source.readWaiting === undefined ? {} : { readWaiting: (session) => materialKeys.has(assistantSessionKey(session)) ? source.readWaiting(session, signal) : session.waiting }),
286
319
  });
287
320
  // 构建期间若源数据已经变化,保留记录,但不能把结果误标为最新。
288
- if (revision !== indexRevision)
289
- return snapshot;
321
+ signal.throwIfAborted();
322
+ if (revision !== indexRevision || disposed)
323
+ throw new Error('索引任务已撤销');
290
324
  lastSnapshot = snapshot;
325
+ indexedEntries.clear();
326
+ for (const entry of snapshot.entries)
327
+ indexedEntries.set(assistantSessionKey(entry), entry);
328
+ statusRevision++;
291
329
  journal.complete(recordId, snapshot, source.warnings, failures);
292
330
  return snapshot;
293
- })().catch((error) => { if (revision === indexRevision)
294
- journal.fail(recordId, error); throw error; }).finally(() => { if (buildingIndex === task)
295
- buildingIndex = undefined; });
331
+ })().catch((error) => { journal.fail(recordId, error); throw error; }).finally(() => { if (buildingIndex === task) {
332
+ buildingIndex = undefined;
333
+ statusRevision++;
334
+ } });
296
335
  buildingIndexRevision = revision;
297
336
  buildingIndex = task;
298
337
  return task;
299
338
  };
300
- const invalidateIndex = () => { cancelIndexAnalysis(); textChat.cancelActive(); voiceChat.clear(); indexRevision += 1; lastSnapshot = null; updates.reset(); };
339
+ const cancelIndexWork = () => {
340
+ indexRevision++;
341
+ indexAbort.abort(new Error('索引任务已撤销'));
342
+ indexAbort = new AbortController();
343
+ cancelIndexAnalysis();
344
+ // 保留取消证据,但不把因模块停用而撤销的版本标成已尝试。
345
+ const run = indexAnalysis.read();
346
+ if (run !== undefined)
347
+ journal.updateAnalysis(run);
348
+ statusRevision++;
349
+ };
350
+ const invalidateIndex = () => { cancelIndexWork(); textChat.cancelActive(); voiceChat.clear(); lastSnapshot = null; updates.reset(); };
351
+ let metadataDirty = true;
352
+ let membershipDirty = true;
353
+ const localSessionKeys = new Map();
354
+ const waitingOverrides = new Map();
355
+ const refreshMembership = () => {
356
+ if (!membershipDirty)
357
+ return;
358
+ membershipDirty = false;
359
+ localSessionKeys.clear();
360
+ const managed = context.services.settings?.get().assistant.managedWorkspaceIds ?? [];
361
+ const archived = new Set(readStringArray(readOptionalService(context.services.dshContext, 'workspaceRegistry')?.archivedSessionIds));
362
+ for (const workspace of readWorkspaceRecords(context.services.dshContext)) {
363
+ if (!managed.some((selected) => assistantWorkspaceMatches(selected, localHostId, workspace.id, true)))
364
+ continue;
365
+ for (const id of workspace.sessionIds)
366
+ if (!archived.has(id))
367
+ localSessionKeys.set(id, assistantSessionKey({ hostId: localHostId, sessionId: id }));
368
+ }
369
+ };
370
+ let metadataEventRevision = 0;
371
+ const background = new AssistantBackground({
372
+ read: async (signal) => {
373
+ const eventRevision = metadataEventRevision;
374
+ const managed = [...context.services.settings?.get().assistant.managedWorkspaceIds ?? []];
375
+ let source = await readAssistantSource(context.services, managed, waitingState, signal);
376
+ signal.throwIfAborted();
377
+ if (source.failed) {
378
+ // 短暂断线不是删除成员。保留同一范围已知远端元数据,但撤销空闲证明,
379
+ // 从而保留材料与成功结果,同时禁止把离线来源当作最新事实送进模型。
380
+ const current = new Set(source.sessions.map(assistantSessionKey));
381
+ const missing = (background.snapshot()?.value.source.sessions ?? []).filter((entry) => entry.hostId !== localHostId && !current.has(assistantSessionKey(entry)));
382
+ source = { ...source, sessions: [...source.sessions, ...missing.map((entry) => ({ ...entry, running: false, completed: false, activity: 'unknown' }))] };
383
+ }
384
+ const metadata = await buildAssistantSessionIndex({ sessions: source.sessions, scope: createAssistantScope(managed), archivedSessionIds: source.archivedSessionIds });
385
+ signal.throwIfAborted();
386
+ return { source, metadata, eventRevision };
387
+ },
388
+ publish: ({ metadata, eventRevision }) => {
389
+ metadataDirty = metadataEventRevision !== eventRevision;
390
+ // 成员表随成功元数据快照更新;常规会话事件不再遍历工作区和会话列表。
391
+ localSessionKeys.clear();
392
+ for (const entry of metadata.entries)
393
+ if (entry.hostId === localHostId)
394
+ localSessionKeys.set(entry.sessionId, assistantSessionKey(entry));
395
+ membershipDirty = metadataDirty;
396
+ const key = readDefaultModelKey();
397
+ if (key !== defaultModelKey) {
398
+ defaultModelKey = key;
399
+ if (indexSelection.provider === undefined)
400
+ invalidateIndex();
401
+ }
402
+ observeVersions(metadata.entries);
403
+ if (updates.hasReady(metadata.entries) || lastSnapshot !== null && !sameIndexMembership(lastSnapshot, metadata))
404
+ updates.schedule(false);
405
+ },
406
+ cadence: ({ source, metadata }) => ({
407
+ remote: source.volatile === true || source.failed === true || metadata.entries.some((entry) => entry.hostId !== localHostId),
408
+ active: metadata.entries.some((entry) => entry.hostId !== localHostId && (entry.activity !== 'idle' || entry.waiting !== null)),
409
+ failed: source.failed === true,
410
+ }),
411
+ });
412
+ let backgroundEnabled = automaticEnabled();
413
+ const syncBackground = () => {
414
+ const enabled = automaticEnabled();
415
+ if (backgroundEnabled && !enabled)
416
+ cancelIndexWork();
417
+ backgroundEnabled = enabled;
418
+ updates.setEnabled(enabled);
419
+ background.setEnabled(enabled);
420
+ };
421
+ const markMetadataChanged = (members = false) => {
422
+ metadataDirty = true;
423
+ metadataEventRevision++;
424
+ statusRevision++;
425
+ membershipDirty ||= members;
426
+ background.request(5_000);
427
+ };
428
+ background.setEnabled(backgroundEnabled);
429
+ context.resources.add(() => { disposed = true; cancelIndexWork(); background.dispose(); updates.dispose(); });
301
430
  const eventDisposers = [];
302
431
  for (const eventName of ['workspace/archive', 'workspace/unarchive', 'workspace/changed']) {
303
- const disposer = context.services.events?.on(eventName, () => updates.schedule());
432
+ const disposer = context.services.events?.on(eventName, () => { markMetadataChanged(true); updates.schedule(); });
304
433
  if (typeof disposer === 'function')
305
434
  eventDisposers.push(disposer);
306
435
  }
307
436
  const sessionKey = (args) => {
437
+ if (!automaticEnabled() && lastSnapshot === null && background.snapshot() === undefined)
438
+ return null;
308
439
  const id = readIndexSessionId(args);
309
- const managed = context.services.settings?.get().assistant.managedWorkspaceIds ?? [];
310
- const workspace = readWorkspaceRecords(context.services.dshContext).find((item) => item.sessionIds.includes(id ?? '') && managed.some((selected) => assistantWorkspaceMatches(selected, localHostId, item.id, true)));
311
- const archived = readStringArray(readOptionalService(context.services.dshContext, 'workspaceRegistry')?.archivedSessionIds);
312
- return id === null || workspace === undefined || archived.includes(id) ? null : assistantSessionKey({ hostId: localHostId, sessionId: id });
440
+ if (id === null)
441
+ return null;
442
+ refreshMembership();
443
+ return localSessionKeys.get(id) ?? null;
313
444
  };
314
445
  const changedSession = (args) => { const key = sessionKey(args); if (key !== null) {
446
+ markMetadataChanged();
315
447
  updates.changed(key);
316
448
  indexAnalysis.deferSession(key);
317
449
  } };
318
450
  for (const eventName of ['session/update', 'session/title']) {
319
- const disposer = context.services.events?.on(eventName, (...args) => changedSession(args));
451
+ const disposer = context.services.events?.on(eventName, (...args) => {
452
+ if (eventName === 'session/title') {
453
+ const id = readIndexSessionId(args);
454
+ if (id !== null)
455
+ assistantSourceCache(context.services).invalidateTitle(id);
456
+ }
457
+ changedSession(args);
458
+ });
320
459
  if (typeof disposer === 'function')
321
460
  eventDisposers.push(disposer);
322
461
  }
@@ -326,10 +465,13 @@ export function createGlobalVoiceRpcFeature(options = {}) {
326
465
  const status = readIndexRunning(eventName, args);
327
466
  if (key === null || status === null)
328
467
  return;
468
+ markMetadataChanged();
329
469
  if (eventName === 'session/complete') {
330
470
  const id = readIndexSessionId(args);
331
- if (id !== null)
471
+ if (id !== null) {
332
472
  waitingState.resolve(id);
473
+ waitingOverrides.set(id, null);
474
+ }
333
475
  updates.changed(key);
334
476
  }
335
477
  updates.status(key, status);
@@ -349,8 +491,10 @@ export function createGlobalVoiceRpcFeature(options = {}) {
349
491
  for (const [eventName, kind] of waitingRequests) {
350
492
  const disposer = context.services.events?.on(eventName, (...args) => {
351
493
  const sessionId = readWaitingSessionId(args);
352
- if (sessionId !== null)
494
+ if (sessionId !== null) {
353
495
  waitingState.request({ sessionId, kind });
496
+ waitingOverrides.set(sessionId, kind);
497
+ }
354
498
  changedSession(args);
355
499
  });
356
500
  if (typeof disposer === 'function')
@@ -359,18 +503,27 @@ export function createGlobalVoiceRpcFeature(options = {}) {
359
503
  for (const eventName of ['approval/resolve', 'approval/resolved', 'user-questions/resolve', 'user-questions/resolved', 'user-question/resolve', 'user-question/answered']) {
360
504
  const disposer = context.services.events?.on(eventName, (...args) => {
361
505
  const sessionId = readWaitingSessionId(args);
362
- if (sessionId !== null)
506
+ if (sessionId !== null) {
363
507
  waitingState.resolve(sessionId);
508
+ waitingOverrides.set(sessionId, null);
509
+ }
364
510
  changedSession(args);
365
511
  });
366
512
  if (typeof disposer === 'function')
367
513
  eventDisposers.push(disposer);
368
514
  }
369
515
  const onSessionEvent = (session, event) => {
516
+ if (!isAssistantIndexEvent(event))
517
+ return;
518
+ const record = asRecord(session);
519
+ const sessionId = readText(record, ['id', 'sessionId']) ?? readText(asRecord(record?.header), ['id', 'sessionId']);
520
+ if (sessionId !== null && asRecord(event)?.type === 'session/title')
521
+ assistantSourceCache(context.services).invalidateTitle(sessionId);
370
522
  const key = sessionKey([session]);
371
523
  if (key === null)
372
524
  return;
373
- const entry = lastSnapshot?.entries.find((item) => assistantSessionKey(item) === key);
525
+ markMetadataChanged();
526
+ const entry = indexedEntries.get(key);
374
527
  const before = entry === undefined ? undefined : updates.stamp(entry).sourceVersion;
375
528
  updates.event(key, event);
376
529
  if (entry !== undefined && before !== updates.stamp(entry).sourceVersion)
@@ -400,6 +553,7 @@ export function createGlobalVoiceRpcFeature(options = {}) {
400
553
  managedScopeKey = nextKey;
401
554
  currentPrompts = nextPrompts;
402
555
  configuredModelKey = nextModelKey;
556
+ syncBackground();
403
557
  return;
404
558
  }
405
559
  const scopeChanged = nextKey !== managedScopeKey;
@@ -423,8 +577,9 @@ export function createGlobalVoiceRpcFeature(options = {}) {
423
577
  voiceChat.clear();
424
578
  }
425
579
  if (scopeChanged) {
426
- cancelIndexAnalysis();
427
- indexRevision++;
580
+ cancelIndexWork();
581
+ background.invalidate();
582
+ markMetadataChanged(true);
428
583
  lastSnapshot = null;
429
584
  updates.schedule();
430
585
  }
@@ -433,37 +588,12 @@ export function createGlobalVoiceRpcFeature(options = {}) {
433
588
  managedScopeKey = nextKey;
434
589
  currentPrompts = nextPrompts;
435
590
  configuredModelKey = nextModelKey;
591
+ syncBackground();
592
+ if (scopeChanged)
593
+ background.request();
436
594
  });
437
595
  if (typeof disposeSettingsWatch === 'function')
438
596
  eventDisposers.push(disposeSettingsWatch);
439
- // 没有本地事件总线的远端也通过元数据版本发现变化;这里只读取列表,不读正文。
440
- let refreshingVersions = false;
441
- const refreshVersions = async () => {
442
- if (resetting || !assistantProfile().initialized)
443
- return;
444
- if (refreshingVersions)
445
- return;
446
- refreshingVersions = true;
447
- try {
448
- const key = readDefaultModelKey();
449
- if (key !== defaultModelKey) {
450
- defaultModelKey = key;
451
- if (indexSelection.provider === undefined)
452
- invalidateIndex();
453
- }
454
- const managed = context.services.settings?.get().assistant.managedWorkspaceIds ?? [];
455
- const source = await readAssistantSource(context.services, managed, waitingState);
456
- const metadata = await buildAssistantSessionIndex({ sessions: source.sessions, scope: createAssistantScope(managed), archivedSessionIds: source.archivedSessionIds });
457
- const changed = observeVersions(metadata.entries);
458
- if (updates.hasReady(metadata.entries) || lastSnapshot !== null && !sameIndexMembership(lastSnapshot, metadata))
459
- updates.schedule(changed);
460
- }
461
- finally {
462
- refreshingVersions = false;
463
- }
464
- };
465
- const versionTimer = setInterval(() => { void refreshVersions().catch(() => { }); }, 5000);
466
- context.resources.add(() => clearInterval(versionTimer));
467
597
  updates.schedule();
468
598
  context.resources.add(() => { for (const dispose of eventDisposers.splice(0))
469
599
  dispose(); });
@@ -491,6 +621,8 @@ export function createGlobalVoiceRpcFeature(options = {}) {
491
621
  }));
492
622
  // 两种入口共用完整结构化索引门禁,语音不能绕过待更新或失败的会话。
493
623
  const readChatContext = () => {
624
+ if (background.snapshot()?.value.source.failed)
625
+ throw new Error('远端索引状态暂不可确认,请等待连接恢复');
494
626
  const index = journal.snapshot().index;
495
627
  const managed = context.services.settings?.get().assistant.managedWorkspaceIds ?? [];
496
628
  if (index === undefined || lastSnapshot !== index || !sameManagedScope(index, managed) || !updates.matches(index))
@@ -527,10 +659,10 @@ export function createGlobalVoiceRpcFeature(options = {}) {
527
659
  requireInitialized();
528
660
  const revision = lifecycleRevision;
529
661
  const managed = assistantSettings().managedWorkspaceIds;
530
- const source = await readAssistantSource(context.services, managed, waitingState);
662
+ const source = await readAssistantSource(context.services, managed, waitingState, signal);
531
663
  signal.throwIfAborted();
532
664
  const index = await buildAssistantSessionIndex({ sessions: source.sessions.filter((entry) => !managementAgent.sessionIds.has(entry.sessionId)), scope: createAssistantScope(managed), archivedSessionIds: source.archivedSessionIds, generation: indexGeneration });
533
- const workspaces = [...readWorkspaceRecords(context.services.dshContext).map((item) => ({ workspaceId: item.id, name: item.name, path: item.path })), ...await readRemoteWorkspaces()];
665
+ const workspaces = source.workspaces;
534
666
  signal.throwIfAborted();
535
667
  if (resetting || revision !== lifecycleRevision || JSON.stringify(managed) !== JSON.stringify(assistantSettings().managedWorkspaceIds))
536
668
  throw new Error('助理管理范围已变化,请重新查询');
@@ -697,6 +829,7 @@ export function createGlobalVoiceRpcFeature(options = {}) {
697
829
  context.resources.add(async () => {
698
830
  await actionBridge.dispose();
699
831
  coordinator.dispose();
832
+ runtime.dispose();
700
833
  });
701
834
  let configuring = false;
702
835
  const stopAssistant = async () => {
@@ -761,8 +894,9 @@ export function createGlobalVoiceRpcFeature(options = {}) {
761
894
  resetting = true;
762
895
  lifecycleRevision++;
763
896
  indexRevision++;
764
- updates.pause();
765
- cancelIndexAnalysis();
897
+ syncBackground();
898
+ background.invalidate();
899
+ cancelIndexWork();
766
900
  modelAbort.abort(new Error('助理已重置'));
767
901
  try {
768
902
  await stopAssistant();
@@ -773,6 +907,7 @@ export function createGlobalVoiceRpcFeature(options = {}) {
773
907
  indexAnalysis.clear();
774
908
  updates.clear();
775
909
  materials.clear();
910
+ waitingOverrides.clear();
776
911
  lastSnapshot = null;
777
912
  lastArchivedSessionIds = [];
778
913
  indexSelection = {};
@@ -783,8 +918,31 @@ export function createGlobalVoiceRpcFeature(options = {}) {
783
918
  finally {
784
919
  modelAbort = new AbortController();
785
920
  resetting = false;
921
+ syncBackground();
786
922
  }
787
923
  };
924
+ const readIndexView = () => {
925
+ const cached = background.snapshot();
926
+ const managed = context.services.settings?.get().assistant.managedWorkspaceIds ?? [];
927
+ const base = cached?.value.metadata ?? { generation: indexGeneration, scope: getAssistantScopeState(createAssistantScope(managed)), entries: [], unreadableCount: 0 };
928
+ const metadata = { ...base, entries: base.entries.map((entry) => ({ ...entry, ...(entry.hostId === localHostId && waitingOverrides.has(entry.sessionId) ? { waiting: waitingOverrides.get(entry.sessionId) } : {}) })) };
929
+ const history = journal.snapshot();
930
+ const matching = history.index !== undefined && sameManagedScope(history.index, managed) && sameIndexMembership(history.index, metadata);
931
+ const index = matching ? withIndexAnalysis(history.index, metadata.entries) : metadata;
932
+ return { cached, metadata, history, matching, index,
933
+ indexState: cached?.value.source.failed ? 'incomplete' : readDebugIndexState(index, { building: buildingIndex !== undefined && buildingIndexRevision === indexRevision, exists: history.index !== undefined, current: lastSnapshot === history.index && matching && updates.matches(index) }),
934
+ indexedAt: matching ? history.indexedAt : null, };
935
+ };
936
+ let cachedStatus;
937
+ const readStatus = () => {
938
+ const revision = statusRevision + background.version();
939
+ if (cachedStatus?.revision === revision)
940
+ return cachedStatus;
941
+ const view = readIndexView();
942
+ cachedStatus = { revision, capturedAt: view.cached?.capturedAt ?? null, indexState: view.indexState,
943
+ indexedAt: view.indexedAt, workspaces: view.cached?.value.source.workspaces ?? [] };
944
+ return cachedStatus;
945
+ };
788
946
  context.resources.add(context.services.rpc.register('assistant', async (action, payload) => {
789
947
  if (resetting && action !== 'lifecycle/read' && action !== 'voice/capabilities' && action !== 'tts/catalog')
790
948
  throw new Error('助理正在重置,请稍后操作');
@@ -796,6 +954,7 @@ export function createGlobalVoiceRpcFeature(options = {}) {
796
954
  return result;
797
955
  }
798
956
  switch (action) {
957
+ case 'status': return readStatus();
799
958
  case 'lifecycle/read': return await lifecycleSnapshot();
800
959
  case 'lifecycle/configure': return await configureAssistant(payload);
801
960
  case 'lifecycle/reset': return await resetAssistant();
@@ -858,32 +1017,22 @@ export function createGlobalVoiceRpcFeature(options = {}) {
858
1017
  }
859
1018
  case 'debug': {
860
1019
  // 查看面板只列元数据,不把“刷新视图”混同为“执行索引”。
861
- const managed = context.services.settings?.get().assistant.managedWorkspaceIds ?? [];
862
- const source = await readAssistantSource(context.services, managed, waitingState);
863
- const metadata = await buildAssistantSessionIndex({ sessions: source.sessions, scope: createAssistantScope(managed), archivedSessionIds: source.archivedSessionIds });
864
- observeVersions(metadata.entries);
865
- const history = journal.snapshot();
866
- // 归档、空白状态或工作区成员关系变化后,旧正文不能继续冒充当前结果。
867
- const matching = history.index !== undefined && sameManagedScope(history.index, managed) && sameIndexMembership(history.index, metadata);
868
- if (history.index !== undefined && !matching) {
869
- textChat.cancelActive();
870
- updates.schedule(false);
871
- }
872
- const index = matching ? withIndexAnalysis(history.index, metadata.entries) : metadata;
1020
+ await background.read(asRecord(payload)?.refresh === true);
1021
+ const { cached, metadata, index, indexState, indexedAt } = readIndexView();
873
1022
  const tasks = new Map((indexAnalysis.read()?.tasks ?? []).map((task) => [assistantSessionKey(task), task]));
874
1023
  const summary = summarizeAssistantEntries(index.entries, index.scope, index.generation, index.unreadableCount, 0);
875
1024
  const query = readOptionalService(context.services.dshContext, 'sessionQuery');
876
1025
  const snapshot = {
877
- capturedAt: Date.now(),
1026
+ capturedAt: cached.capturedAt,
878
1027
  index,
879
1028
  // 调试页不限制播报长度,复用摘要接口的范围状态和分组语义。
880
1029
  summary: index.analysis?.state === 'completed' && index.analysis.result !== undefined ? { ...summary, speechText: sanitizeSpeechText(speakAssistantStructuredIndex(index.analysis.result)) } : summary,
881
- workspaces: [...readWorkspaceRecords(context.services.dshContext).map((workspace) => ({ workspaceId: workspace.id, name: workspace.name, path: workspace.path })), ...await readRemoteWorkspaces()],
1030
+ workspaces: cached.value.source.workspaces,
882
1031
  modelId: readAssistantVoiceSettings(context.services).modelId ?? '',
883
- warnings: source.warnings,
1032
+ warnings: cached.value.source.warnings,
884
1033
  scopeSessions: metadata.entries.map((entry) => updates.stamp(entry, tasks.get(assistantSessionKey(entry)))),
885
- indexState: readDebugIndexState(index, { building: buildingIndex !== undefined && buildingIndexRevision === indexRevision, exists: history.index !== undefined, current: lastSnapshot === history.index && matching && updates.matches(index) }),
886
- indexedAt: matching ? history.indexedAt : null,
1034
+ indexState,
1035
+ indexedAt,
887
1036
  records: journal.snapshot().records,
888
1037
  services: {
889
1038
  workspaceList: typeof readOptionalService(context.services.dshContext, 'workspaceRegistry')?.list === 'function',
@@ -1204,23 +1353,37 @@ async function dispatchPrompt(services, request, signal = new AbortController().
1204
1353
  }
1205
1354
  throw new Error('DSH sessionController.prompt 不可用,无法派发任务');
1206
1355
  }
1207
- async function readAssistantSource(services, managedWorkspaceIds = [], waitingState) {
1356
+ async function readAssistantSource(services, managedWorkspaceIds = [], waitingState, signal) {
1357
+ signal?.throwIfAborted();
1208
1358
  const ctx = services.dshContext;
1209
1359
  const warnings = [];
1210
1360
  const query = readOptionalService(ctx, 'sessionQuery');
1211
- const localSessions = await readLocalAssistantSessions(services, warnings);
1361
+ const cache = assistantSourceCache(services);
1362
+ const localSessions = await readLocalAssistantSessions(services, warnings, signal);
1363
+ signal?.throwIfAborted();
1364
+ let failed = false;
1212
1365
  const gatewayResult = services.assistantGateway === undefined || managedWorkspaceIds.length === 0
1213
1366
  ? undefined
1214
- : await services.assistantGateway.list(managedWorkspaceIds).catch((error) => {
1367
+ : await services.assistantGateway.list(managedWorkspaceIds, signal).catch((error) => {
1368
+ signal?.throwIfAborted();
1369
+ failed = true;
1215
1370
  warnings.push(`远端 Host 状态读取失败:${sanitizeSpeechText(error instanceof Error ? error.message : String(error)).slice(0, 500)}`);
1216
1371
  return undefined;
1217
1372
  });
1373
+ signal?.throwIfAborted();
1374
+ warnings.push(...gatewayResult?.warnings ?? []);
1218
1375
  const sessions = dedupeSessionRecords([
1219
1376
  ...localSessions,
1220
1377
  ...(gatewayResult?.sessions ?? []),
1221
1378
  ]);
1222
1379
  const workspaces = readWorkspaceRecords(ctx);
1223
1380
  const workspaceById = new Map(workspaces.map((workspace) => [workspace.id, workspace]));
1381
+ const workspaceBySession = new Map();
1382
+ for (const workspace of workspaces) {
1383
+ for (const sessionId of workspace.sessionIds)
1384
+ if (!workspaceBySession.has(sessionId))
1385
+ workspaceBySession.set(sessionId, workspace.id);
1386
+ }
1224
1387
  const archived = [...new Set([
1225
1388
  ...readStringArray(readOptionalService(ctx, 'workspaceRegistry')?.archivedSessionIds),
1226
1389
  ...(gatewayResult?.archivedSessionIds ?? []),
@@ -1231,6 +1394,9 @@ async function readAssistantSource(services, managedWorkspaceIds = [], waitingSt
1231
1394
  for (const [sessionId, kind] of waitingState?.snapshot() ?? [])
1232
1395
  waitingBySession.set(sessionId, kind);
1233
1396
  const hostId = process.env.CODINGNS4DSH_HOST_ID?.trim() || 'local-host';
1397
+ const managedByWorkspace = new Map(workspaces.map((workspace) => [workspace.id,
1398
+ managedWorkspaceIds.find((selected) => assistantWorkspaceMatches(selected, hostId, workspace.id, true)) ?? workspace.id,
1399
+ ]));
1234
1400
  let unmappedSessionCount = 0;
1235
1401
  const records = sessions.flatMap((raw) => {
1236
1402
  const value = asRecord(raw);
@@ -1244,14 +1410,14 @@ async function readAssistantSource(services, managedWorkspaceIds = [], waitingSt
1244
1410
  const sourceHostId = readText(value, ['hostId', 'sourceHostId']) ?? hostId;
1245
1411
  // 本地工作区成员关系由 Registry 决定,cwd 相同不意味着它是工作区成员。
1246
1412
  // Gateway 已在远端按同一成员关系投影,保留其 workspaceId/hostId。
1247
- const originalWorkspaceId = sourceHostId === hostId ? findWorkspaceId(sessionId, workspaces) : readText(value, ['workspaceId']);
1413
+ const originalWorkspaceId = sourceHostId === hostId ? workspaceBySession.get(sessionId) ?? null : readText(value, ['workspaceId']);
1248
1414
  // 保留范围外和归档会话的元数据,索引构建器统一决定纳入/排除。
1249
1415
  // 不能提前丢掉这些记录,否则调试页和目标澄清都无法解释排除原因。
1250
1416
  if (originalWorkspaceId === null) {
1251
1417
  unmappedSessionCount += 1;
1252
1418
  return [];
1253
1419
  }
1254
- const workspaceId = sourceHostId === hostId ? managedWorkspaceIds.find((selected) => assistantWorkspaceMatches(selected, hostId, originalWorkspaceId, true)) ?? originalWorkspaceId : originalWorkspaceId;
1420
+ const workspaceId = sourceHostId === hostId ? managedByWorkspace.get(originalWorkspaceId) ?? originalWorkspaceId : originalWorkspaceId;
1255
1421
  const workspace = workspaceById.get(originalWorkspaceId);
1256
1422
  const sourceWorkspaceName = readText(value, ['workspaceName', 'workspaceDisplayName']);
1257
1423
  const agent = sourceHostId === hostId ? readOptionalService(ctx, 'agents')?.get?.(sessionId) : undefined;
@@ -1294,7 +1460,7 @@ async function readAssistantSource(services, managedWorkspaceIds = [], waitingSt
1294
1460
  // 也不能把远端会话误当成本地会话产生一次额外 I/O。
1295
1461
  if (record.hostId !== hostId || !managed.has(record.workspaceId) || archivedSet.has(record.sessionId))
1296
1462
  return record;
1297
- const title = await readSessionTitle(readTitle, record.sessionId);
1463
+ const title = await cache.title(record.sessionId, JSON.stringify([record.title, record.titleEvents]), false, () => readSessionTitle(readTitle, record.sessionId, signal), signal);
1298
1464
  return title === null ? record : { ...record, title };
1299
1465
  }));
1300
1466
  // workspaceRegistry 可能只暴露归档 ID,而 sessionQuery 不再返回归档记录。
@@ -1320,37 +1486,46 @@ async function readAssistantSource(services, managedWorkspaceIds = [], waitingSt
1320
1486
  summary: null,
1321
1487
  }];
1322
1488
  }));
1489
+ signal?.throwIfAborted();
1490
+ const remoteWorkspaces = await services.assistantGateway?.workspaces?.(signal).catch((error) => { signal?.throwIfAborted(); return []; }) ?? [];
1491
+ signal?.throwIfAborted();
1323
1492
  return {
1324
1493
  sessions: [...hydratedRecords, ...archivedStubs],
1325
1494
  archivedSessionIds: archived,
1326
1495
  warnings,
1496
+ failed: failed || gatewayResult?.failed === true,
1497
+ workspaces: [...workspaces.map((workspace) => ({ workspaceId: workspace.id, name: workspace.name, path: workspace.path })), ...remoteWorkspaces],
1327
1498
  ...(gatewayResult?.volatile === true ? { volatile: true } : {}),
1328
1499
  ...((readSurface === undefined && gatewayResult?.readSummary === undefined) ? {} : {
1329
- readSummary: async (session) => {
1500
+ readSummary: async (session, readSignal) => {
1501
+ readSignal?.throwIfAborted();
1330
1502
  if (session.hostId === hostId && readSurface !== undefined)
1331
- return readSurfaceSummary(readSurface, session.sessionId);
1503
+ return readSurfaceSummary(readSurface, session.sessionId, readSignal);
1332
1504
  if (session.hostId !== hostId && gatewayResult?.readSummary !== undefined)
1333
- return gatewayResult.readSummary(session);
1505
+ return gatewayResult.readSummary(session, readSignal);
1334
1506
  return session.summary ?? null;
1335
1507
  },
1336
1508
  }),
1337
1509
  ...((gatewayResult?.readWaiting === undefined) ? {} : {
1338
- readWaiting: async (session) => {
1510
+ readWaiting: async (session, readSignal) => {
1511
+ readSignal?.throwIfAborted();
1339
1512
  if (session.hostId !== hostId)
1340
- return gatewayResult.readWaiting(session);
1513
+ return gatewayResult.readWaiting(session, readSignal);
1341
1514
  return session.waiting ?? null;
1342
1515
  },
1343
1516
  }),
1344
1517
  };
1345
1518
  }
1346
1519
  /** 原生列表提供 blank/origin 投影;原始日志目录只能作为旧版本的能力回退。 */
1347
- async function readLocalAssistantSessions(services, warnings) {
1520
+ async function readLocalAssistantSessions(services, warnings, signal) {
1521
+ signal?.throwIfAborted();
1348
1522
  const controller = readOptionalService(services.dshContext, 'sessionController') ?? services.nativeSessions?.controller;
1349
1523
  if (typeof controller?.list === 'function') {
1350
1524
  try {
1351
- return flattenSessionList(await controller.list({}));
1525
+ return flattenSessionList(await controller.list({}, signal));
1352
1526
  }
1353
1527
  catch {
1528
+ signal?.throwIfAborted();
1354
1529
  // 列表失败或列表为空都不能改用全量历史,否则会重新纳入被侧栏隐藏的会话。
1355
1530
  warnings.push('原生会话列表读取失败,暂不纳入本地会话;请刷新后重试。');
1356
1531
  return [];
@@ -1358,12 +1533,14 @@ async function readLocalAssistantSessions(services, warnings) {
1358
1533
  }
1359
1534
  const query = readOptionalService(services.dshContext, 'sessionQuery');
1360
1535
  if (typeof query?.listSessions === 'function')
1361
- return flattenSessionList(await query.listSessions());
1362
- return services.nativeSessions === undefined ? [] : flattenSessionList(await services.nativeSessions.listRemote());
1536
+ return flattenSessionList(await query.listSessions(signal));
1537
+ return services.nativeSessions === undefined ? [] : flattenSessionList(await services.nativeSessions.listRemote(signal));
1363
1538
  }
1364
- async function readSessionTitle(readTitle, sessionId) {
1539
+ async function readSessionTitle(readTitle, sessionId, signal) {
1365
1540
  try {
1366
- const value = await readTitle(sessionId);
1541
+ signal?.throwIfAborted();
1542
+ const value = await readTitle(sessionId, signal);
1543
+ signal?.throwIfAborted();
1367
1544
  if (typeof value === 'string' && value.trim() !== '')
1368
1545
  return value.trim();
1369
1546
  if (isRecord(value)) {
@@ -1382,12 +1559,15 @@ async function readSessionTitle(readTitle, sessionId) {
1382
1559
  }
1383
1560
  }
1384
1561
  catch {
1562
+ signal?.throwIfAborted();
1385
1563
  // 单个标题查询失败不阻断其余会话索引。
1386
1564
  }
1387
1565
  return null;
1388
1566
  }
1389
- async function readSurfaceSummary(readSurface, sessionId) {
1390
- const value = await readSurface(sessionId);
1567
+ async function readSurfaceSummary(readSurface, sessionId, signal) {
1568
+ signal?.throwIfAborted();
1569
+ const value = await readSurface(sessionId, signal);
1570
+ signal?.throwIfAborted();
1391
1571
  if (typeof value === 'string')
1392
1572
  return value.slice(0, 2000);
1393
1573
  if (!isRecord(value))
@@ -1593,12 +1773,6 @@ function dedupeSessionRecords(values) {
1593
1773
  }
1594
1774
  return result;
1595
1775
  }
1596
- function findWorkspaceId(sessionId, workspaces) {
1597
- for (const workspace of workspaces)
1598
- if (workspace.sessionIds.includes(sessionId))
1599
- return workspace.id;
1600
- return null;
1601
- }
1602
1776
  function sameManagedScope(index, managed) {
1603
1777
  const indexed = index.scope.status === 'empty' ? [] : index.scope.managedWorkspaceIds;
1604
1778
  return JSON.stringify([...new Set(indexed)].sort()) === JSON.stringify([...new Set(managed)].sort());