@co0ontty/wand 4.105.1 → 4.106.0

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 (291) hide show
  1. package/dist/build-info.json +3 -3
  2. package/dist/cli.js +7 -2
  3. package/dist/distribution-manager.d.ts +2 -0
  4. package/dist/distribution-manager.js +23 -0
  5. package/dist/employee-input-scheduling.d.ts +2 -1
  6. package/dist/employee-knowledge-cli.d.ts +1 -1
  7. package/dist/employee-knowledge-cli.js +91 -20
  8. package/dist/employee-knowledge-content.js +1 -1
  9. package/dist/employee-knowledge-types.d.ts +1 -1
  10. package/dist/employee-knowledge-types.js +1 -1
  11. package/dist/employee-knowledge.d.ts +6 -3
  12. package/dist/employee-knowledge.js +54 -58
  13. package/dist/env-utils.js +1 -1
  14. package/dist/html-preview-policy.d.ts +4 -0
  15. package/dist/html-preview-policy.js +4 -0
  16. package/dist/ios-ota.d.ts +5 -0
  17. package/dist/ios-ota.js +11 -1
  18. package/dist/knowledge-skill.d.ts +2 -0
  19. package/dist/knowledge-skill.js +17 -0
  20. package/dist/knowledge-types.d.ts +36 -0
  21. package/dist/knowledge-types.js +8 -0
  22. package/dist/managed-skills-ensure.js +2 -0
  23. package/dist/middleware/api-scope.js +2 -0
  24. package/dist/path-repair.js +28 -6
  25. package/dist/pi-resource-catalog.d.ts +3 -1
  26. package/dist/pi-resource-catalog.js +25 -0
  27. package/dist/pi-session-settings.d.ts +2 -0
  28. package/dist/pi-session-settings.js +25 -0
  29. package/dist/process-manager.d.ts +2 -0
  30. package/dist/process-manager.js +35 -12
  31. package/dist/quick-terminal-session.d.ts +3 -0
  32. package/dist/quick-terminal-session.js +5 -0
  33. package/dist/retention-protection.d.ts +15 -0
  34. package/dist/retention-protection.js +134 -0
  35. package/dist/retention.d.ts +3 -2
  36. package/dist/retention.js +58 -76
  37. package/dist/server-employee-routes.js +1 -1
  38. package/dist/server-file-routes.js +84 -16
  39. package/dist/server-knowledge-routes.d.ts +4 -0
  40. package/dist/server-knowledge-routes.js +61 -0
  41. package/dist/server-local-preview-routes.js +28 -6
  42. package/dist/server-pi-defaults-routes.d.ts +1 -1
  43. package/dist/server-pi-defaults-routes.js +13 -20
  44. package/dist/server-session-lifecycle-routes.js +17 -17
  45. package/dist/server-session-list-routes.js +1 -1
  46. package/dist/server-task-routes.js +6 -0
  47. package/dist/server-update-routes.d.ts +1 -0
  48. package/dist/server-update-routes.js +62 -17
  49. package/dist/server-workspace-routes.js +5 -5
  50. package/dist/server.js +4 -2
  51. package/dist/session-questions.d.ts +7 -0
  52. package/dist/session-questions.js +25 -0
  53. package/dist/session-registry.d.ts +3 -0
  54. package/dist/session-registry.js +17 -0
  55. package/dist/session-request.d.ts +1 -1
  56. package/dist/session-request.js +6 -2
  57. package/dist/session-service.js +1 -1
  58. package/dist/storage/employees-repository.js +5 -2
  59. package/dist/storage/knowledge-repository.d.ts +35 -0
  60. package/dist/storage/knowledge-repository.js +208 -0
  61. package/dist/storage/mappers.js +1 -1
  62. package/dist/storage/migrations.js +51 -0
  63. package/dist/storage/sessions-repository.d.ts +2 -0
  64. package/dist/storage/sessions-repository.js +16 -0
  65. package/dist/storage/tasks-repository.d.ts +7 -0
  66. package/dist/storage/tasks-repository.js +21 -0
  67. package/dist/storage/workspaces-repository.d.ts +1 -0
  68. package/dist/storage/workspaces-repository.js +2 -1
  69. package/dist/storage.d.ts +3 -1
  70. package/dist/storage.js +4 -0
  71. package/dist/structured-session-manager.d.ts +3 -0
  72. package/dist/structured-session-manager.js +13 -4
  73. package/dist/task-action-types.d.ts +22 -0
  74. package/dist/task-action-types.js +1 -0
  75. package/dist/task-actions.d.ts +5 -0
  76. package/dist/task-actions.js +86 -0
  77. package/dist/task-execution-queue.d.ts +1 -1
  78. package/dist/task-execution-queue.js +4 -1
  79. package/dist/task-retention.d.ts +4 -2
  80. package/dist/task-retention.js +2 -0
  81. package/dist/types.d.ts +2 -1
  82. package/dist/web-ui/content/ai-teams.js +12 -12
  83. package/dist/web-ui/content/module-manifest.json +1 -1
  84. package/dist/web-ui/content/modules/00b168a19664439e/dropdown-surface.js +1 -0
  85. package/dist/web-ui/content/modules/059c5fb7f128d340/task-board-host.js +27 -0
  86. package/dist/web-ui/content/modules/07494f5a623e4471/chat-render.js +76 -0
  87. package/dist/web-ui/content/modules/{bc28252270bcc51a → 0a743ad3b4db6874}/chunk.js +1 -1
  88. package/dist/web-ui/content/modules/0d76e582a7a71b2f/chunk.js +1 -0
  89. package/dist/web-ui/content/modules/11af5d14b30e57b6/chunk.js +1 -0
  90. package/dist/web-ui/content/modules/16dab1297efd71a7/chunk.js +10 -0
  91. package/dist/web-ui/content/modules/182929e188c1ab3a/host.js +5 -0
  92. package/dist/web-ui/content/modules/1858670c0f84fec5/employee-profile.js +1 -0
  93. package/dist/web-ui/content/modules/{1cf252d2f64a6279 → 1eab7410d5586038}/chunk.js +1 -1
  94. package/dist/web-ui/content/modules/20c47dc0442f5a04/host.js +1 -0
  95. package/dist/web-ui/content/modules/226241b999d12008/host.js +1 -0
  96. package/dist/web-ui/content/modules/23c4b8d223ec64c5/host.js +61 -0
  97. package/dist/web-ui/content/modules/2882c97388ff4f7b/employee-card.js +1 -0
  98. package/dist/web-ui/content/modules/2a791cd2e14aa1e0/notice-view.js +1 -0
  99. package/dist/web-ui/content/modules/2c90c3be260e6cce/progress.js +1 -0
  100. package/dist/web-ui/content/modules/2d7be9935394f397/workspace-window.js +1 -0
  101. package/dist/web-ui/content/modules/2f801e53dda62770/chunk.js +1 -0
  102. package/dist/web-ui/content/modules/2f97ddba3842adaa/chunk.js +1 -0
  103. package/dist/web-ui/content/modules/31157ceb6d23b809/chunk.js +15 -0
  104. package/dist/web-ui/content/modules/389a5112332ec23a/host.js +1 -0
  105. package/dist/web-ui/content/modules/3ea13e8b3c2deaa4/panel-host.js +1 -0
  106. package/dist/web-ui/content/modules/3f8830f8ad28decc/chunk.js +3 -0
  107. package/dist/web-ui/content/modules/{70715360138f4d99 → 3fe11a75284ad8ae}/host.js +1 -1
  108. package/dist/web-ui/content/modules/{e0a1ae9163e77556 → 41445c6589dba325}/host.js +2 -2
  109. package/dist/web-ui/content/modules/{8b2f9a027ae1d7eb → 42e5c34002fcffb7}/chunk.js +1 -1
  110. package/dist/web-ui/content/modules/438807b8bf112cd0/chunk.js +1 -0
  111. package/dist/web-ui/content/modules/4861eca9a8a87ad0/chunk.js +1 -0
  112. package/dist/web-ui/content/modules/{78d06dfdc4b13d78 → 4970319a83432ec7}/chunk.js +1 -1
  113. package/dist/web-ui/content/modules/4a5d669c90f545cb/host.js +1 -0
  114. package/dist/web-ui/content/modules/4ba1e8c74bed7ef2/chunk.js +1 -0
  115. package/dist/web-ui/content/modules/5083a5dbb5b155b7/chunk.js +1 -0
  116. package/dist/web-ui/content/modules/50da446c1377c220/chunk.js +20 -0
  117. package/dist/web-ui/content/modules/52574891ef08e29b/host.js +30 -0
  118. package/dist/web-ui/content/modules/5705d25468274534/host.js +1 -0
  119. package/dist/web-ui/content/modules/579d486763d47c0d/chunk.js +1 -0
  120. package/dist/web-ui/content/modules/57c357d321db5df9/chunk.js +1 -0
  121. package/dist/web-ui/content/modules/5933ce8965aa4004/chunk.js +1 -0
  122. package/dist/web-ui/content/modules/5961ab2947c86ca1/shell-file-panel-drawer.js +1 -0
  123. package/dist/web-ui/content/modules/5b6e1369df7dea69/chunk.js +1 -0
  124. package/dist/web-ui/content/modules/5f298a8f43dd0589/chunk.js +1 -0
  125. package/dist/web-ui/content/modules/62e0023451f428cf/chunk.js +1 -0
  126. package/dist/web-ui/content/modules/6787bdcf56f743a5/host.js +1 -0
  127. package/dist/web-ui/content/modules/67c39b0398186a9f/host.js +1 -0
  128. package/dist/web-ui/content/modules/6b16f35c0627bafb/chunk.js +1 -0
  129. package/dist/web-ui/content/modules/6dd4f3e2f619f7a0/chunk.js +1 -0
  130. package/dist/web-ui/content/modules/70a2e13e0ccc8549/panel.js +1 -0
  131. package/dist/web-ui/content/modules/710db590e9707f73/runtime.js +338 -0
  132. package/dist/web-ui/content/modules/7249950f8771dbeb/workspaces-panel.js +4 -0
  133. package/dist/web-ui/content/modules/771439a41e737ee2/chunk.js +1 -0
  134. package/dist/web-ui/content/modules/{2061d4a88875b9f9 → 816eb9b3a000fb2c}/chunk.js +1 -1
  135. package/dist/web-ui/content/modules/{c0384ffb4ef740a0 → 831b6c7b43e800be}/host.js +1 -1
  136. package/dist/web-ui/content/modules/87c7f50d9455d55e/chunk.js +1 -0
  137. package/dist/web-ui/content/modules/87dcd516ffd9f688/composer-surface-adapter.js +1 -0
  138. package/dist/web-ui/content/modules/8891ca8165435ca1/chunk.js +1 -0
  139. package/dist/web-ui/content/modules/8b7cd7bffdfd69e7/brand-identity.js +1 -0
  140. package/dist/web-ui/content/modules/8bf9917f6c3429f6/host.js +1 -0
  141. package/dist/web-ui/content/modules/8de8368570ab089d/chunk.js +57 -0
  142. package/dist/web-ui/content/modules/8e612d4881fa4118/home.js +6 -0
  143. package/dist/web-ui/content/modules/8e6178262ea63dec/markdown.js +1 -0
  144. package/dist/web-ui/content/modules/913187c92a98a1ac/chunk.js +1 -0
  145. package/dist/web-ui/content/modules/96f2ae970f8c576b/host.js +1 -0
  146. package/dist/web-ui/content/modules/97d7f267959fd385/chunk.js +1 -0
  147. package/dist/web-ui/content/modules/{22497085d7cdd83b → 9b12c2301f3a18f3}/chunk.js +1 -1
  148. package/dist/web-ui/content/modules/{9f4e26a1c1867d65 → 9d941d6ff39861b8}/chunk.js +2 -2
  149. package/dist/web-ui/content/modules/9e163d54ff8fd1aa/chunk.js +1 -0
  150. package/dist/web-ui/content/modules/{0567e161e2cca41e → a2caed0139df4b21}/chunk.js +1 -1
  151. package/dist/web-ui/content/modules/a59734be368daa7e/chunk.js +1 -0
  152. package/dist/web-ui/content/modules/{e4503f8e6379ccdc → a61393bfa976d8d5}/chunk.js +1 -1
  153. package/dist/web-ui/content/modules/{df5d48b4ff04b443 → b63e075f222a1266}/library-bridge.js +2 -2
  154. package/dist/web-ui/content/modules/b713cad51ca4c512/chunk.js +1 -0
  155. package/dist/web-ui/content/modules/ba89cd97627e6682/queue-view-adapter.js +1 -0
  156. package/dist/web-ui/content/modules/bd3daf04a8bf4422/chunk.js +1 -0
  157. package/dist/web-ui/content/modules/{aa7d409d04bbd736 → bd7dc4bb46731ee7}/chunk.js +1 -1
  158. package/dist/web-ui/content/modules/bf3ee58e0da44822/chunk.js +1 -0
  159. package/dist/web-ui/content/modules/c0a446100d969f3e/chunk.js +8 -0
  160. package/dist/web-ui/content/modules/c2f09c8a472f5d83/dialog-modal.js +4 -0
  161. package/dist/web-ui/content/modules/c33935155289c22d/chunk.js +3 -0
  162. package/dist/web-ui/content/modules/c351eb11e0bdec2c/sidebar-peek.js +1 -0
  163. package/dist/web-ui/content/modules/ca7ca5902a35d26e/chunk.js +1 -0
  164. package/dist/web-ui/content/modules/cba6f13c0b2aec1c/chunk.js +1 -0
  165. package/dist/web-ui/content/modules/d434edbb2f4672e5/chunk.js +1 -0
  166. package/dist/web-ui/content/modules/{d569c96d4acfdec3 → d47d75a78ae598e3}/chunk.js +25 -25
  167. package/dist/web-ui/content/modules/d49f106c4d106057/chunk.js +1 -0
  168. package/dist/web-ui/content/modules/d5d28ec375826ef2/chunk.js +3 -0
  169. package/dist/web-ui/content/modules/{7edec8f23f8e0834 → d6b16dedb9011c33}/chunk.js +1 -1
  170. package/dist/web-ui/content/modules/d6fffe2c2a3a738d/toast-region.js +1 -0
  171. package/dist/web-ui/content/modules/d8a7011760f61719/group-editor.js +1 -0
  172. package/dist/web-ui/content/modules/{bf0b693a654e2655 → d9e2b65e9679ad39}/host.js +3 -3
  173. package/dist/web-ui/content/modules/db521a246e14e5e4/chunk.js +4 -0
  174. package/dist/web-ui/content/modules/{7994dec16e8b1039 → dedd4a19bb70e327}/page.js +2 -2
  175. package/dist/web-ui/content/modules/e060508ecd50fa7e/chunk.js +1 -0
  176. package/dist/web-ui/content/modules/e5174201f9d918fb/chunk.js +1 -0
  177. package/dist/web-ui/content/modules/e63582a3bce48f7d/chunk.js +1 -0
  178. package/dist/web-ui/content/modules/ea8fe4b9999fd2aa/chunk.js +1 -0
  179. package/dist/web-ui/content/modules/{d7cdd7dca9a0c9f8 → eac72f69716dba05}/chunk.js +1 -1
  180. package/dist/web-ui/content/modules/ebc53dedc3945514/host.js +1 -0
  181. package/dist/web-ui/content/modules/{0d7f7d954382dc42 → ec33e17c00c1eb24}/chunk.js +1 -1
  182. package/dist/web-ui/content/modules/{99e5cdf0c3bd0e3d → ed7405f064944215}/sha256.js +1 -1
  183. package/dist/web-ui/content/modules/f27a5d3c6c02a71c/chunk.js +1 -0
  184. package/dist/web-ui/content/modules/f383d892fef73483/chunk.js +1 -0
  185. package/dist/web-ui/content/modules/{084dca1ea52bf38e → f3cff7792ba39df8}/login-visual.js +1 -1
  186. package/dist/web-ui/content/modules/f43da7050badf54c/host.js +1 -0
  187. package/dist/web-ui/content/modules/face3dbf117d63e3/chunk.js +1 -0
  188. package/dist/web-ui/content/modules/fb2356eced24c4cc/host-bridge.js +1 -0
  189. package/dist/web-ui/content/styles.css +1 -1
  190. package/dist/web-ui/embedded-assets.d.ts +413 -420
  191. package/dist/web-ui/embedded-assets.js +5 -5
  192. package/dist/web-ui/group-chat-visibility.d.ts +1 -0
  193. package/dist/web-ui/group-chat-visibility.js +1 -1
  194. package/dist/web-ui/markdown.js +10 -36
  195. package/dist/web-ui/message-file-target.d.ts +8 -0
  196. package/dist/web-ui/message-file-target.js +105 -15
  197. package/dist/web-ui/page-route.js +2 -0
  198. package/dist/web-ui/react/local-preview/controller.d.ts +2 -2
  199. package/dist/web-ui/react/local-preview/controller.js +53 -10
  200. package/dist/web-ui/react/workspaces/types.d.ts +1 -0
  201. package/dist/web-ui/server-link-url.d.ts +3 -0
  202. package/dist/web-ui/server-link-url.js +18 -0
  203. package/package.json +2 -1
  204. package/skills/wand-knowledge/SKILL.md +47 -0
  205. package/skills/wand-knowledge/scripts/knowledge.mjs +18 -0
  206. package/dist/web-ui/content/modules/0341f0d00f88a16f/chunk.js +0 -1
  207. package/dist/web-ui/content/modules/069f5a4267b0a9e3/runtime.js +0 -279
  208. package/dist/web-ui/content/modules/0d62c22b7aed5f1f/host-bridge.js +0 -1
  209. package/dist/web-ui/content/modules/0da28408ec089cf7/chunk.js +0 -1
  210. package/dist/web-ui/content/modules/130e8905cc7f639c/toast-region.js +0 -1
  211. package/dist/web-ui/content/modules/186d6e3b44a3c539/host.js +0 -1
  212. package/dist/web-ui/content/modules/1870280f0e783c62/chunk.js +0 -4
  213. package/dist/web-ui/content/modules/19d3bc36fa1e9160/chunk.js +0 -1
  214. package/dist/web-ui/content/modules/1a0b5db535599f72/chunk.js +0 -1
  215. package/dist/web-ui/content/modules/1d1dc0fd8a0210aa/composer-surface-adapter.js +0 -1
  216. package/dist/web-ui/content/modules/23f15023aa2279a3/shell-file-panel-drawer.js +0 -1
  217. package/dist/web-ui/content/modules/2cab58e5d148844c/host.js +0 -1
  218. package/dist/web-ui/content/modules/32edeb64dbf339f6/chunk.js +0 -1
  219. package/dist/web-ui/content/modules/33daaeb4bf68c7ba/chunk.js +0 -9
  220. package/dist/web-ui/content/modules/37da177222b6308d/workspaces-panel.js +0 -4
  221. package/dist/web-ui/content/modules/3af7facf8a7588c7/chunk.js +0 -1
  222. package/dist/web-ui/content/modules/3b95dc1376e932ea/host.js +0 -1
  223. package/dist/web-ui/content/modules/3cbbad48df7998f8/chunk.js +0 -1
  224. package/dist/web-ui/content/modules/41cf79c899bc83c8/host.js +0 -1
  225. package/dist/web-ui/content/modules/444af9de1698eea0/host.js +0 -1
  226. package/dist/web-ui/content/modules/452327275cc5d8f8/host.js +0 -1
  227. package/dist/web-ui/content/modules/466310a17dac465f/chunk.js +0 -3
  228. package/dist/web-ui/content/modules/46f1b6c3274d399b/host.js +0 -1
  229. package/dist/web-ui/content/modules/47998d82dc65bfeb/sidebar-peek.js +0 -1
  230. package/dist/web-ui/content/modules/486a828390c5d44d/host.js +0 -30
  231. package/dist/web-ui/content/modules/4cc15b385bc6cc32/chunk.js +0 -1
  232. package/dist/web-ui/content/modules/4d5ab67f6c0ce19f/chunk.js +0 -1
  233. package/dist/web-ui/content/modules/54aaf60ac85dcb2b/chunk.js +0 -1
  234. package/dist/web-ui/content/modules/54c22eddaf009d00/chunk.js +0 -1
  235. package/dist/web-ui/content/modules/55b931232c672f4f/chunk.js +0 -1
  236. package/dist/web-ui/content/modules/583049de28ef2b02/panel.js +0 -1
  237. package/dist/web-ui/content/modules/5a2a58334d63e127/chunk.js +0 -20
  238. package/dist/web-ui/content/modules/5ba0668f5a22133b/home.js +0 -6
  239. package/dist/web-ui/content/modules/5cd5d3d65d966c5f/chunk.js +0 -1
  240. package/dist/web-ui/content/modules/6b41e59ab342482f/notice-view.js +0 -1
  241. package/dist/web-ui/content/modules/6b5445f41bef0a66/chunk.js +0 -1
  242. package/dist/web-ui/content/modules/6e8395f61c89b5aa/chunk.js +0 -1
  243. package/dist/web-ui/content/modules/6f74cede70164e19/chunk.js +0 -1
  244. package/dist/web-ui/content/modules/704690f5d6ab9157/chunk.js +0 -1
  245. package/dist/web-ui/content/modules/7dce56c1987e8d43/chunk.js +0 -29
  246. package/dist/web-ui/content/modules/80e92c14a6789896/progress.js +0 -1
  247. package/dist/web-ui/content/modules/8a828b4d087667dd/chunk.js +0 -1
  248. package/dist/web-ui/content/modules/8d6f223764846e18/brand-identity.js +0 -1
  249. package/dist/web-ui/content/modules/9136bae16758fd4c/chunk.js +0 -1
  250. package/dist/web-ui/content/modules/93fa5c35e4bcab96/chunk.js +0 -1
  251. package/dist/web-ui/content/modules/96fe39f39930d9e4/chunk.js +0 -8
  252. package/dist/web-ui/content/modules/9db41ad5ac96ffa2/chunk.js +0 -1
  253. package/dist/web-ui/content/modules/a073cb6d182ccd32/chunk.js +0 -1
  254. package/dist/web-ui/content/modules/a8cba9f1d6b49ef1/chunk.js +0 -1
  255. package/dist/web-ui/content/modules/a97b3b9b68f9ca38/chunk.js +0 -57
  256. package/dist/web-ui/content/modules/ac34ed6692b43ede/dropdown-surface.js +0 -1
  257. package/dist/web-ui/content/modules/aff19b31898aa157/chunk.js +0 -1
  258. package/dist/web-ui/content/modules/b2f6e088e6e45878/chunk.js +0 -1
  259. package/dist/web-ui/content/modules/b4446bf92e182bfb/employee-card.js +0 -1
  260. package/dist/web-ui/content/modules/b79c15aace456028/chunk.js +0 -6
  261. package/dist/web-ui/content/modules/b8c18baf7cfb61b1/chat-render.js +0 -76
  262. package/dist/web-ui/content/modules/b8c447171e3d60a0/chunk.js +0 -1
  263. package/dist/web-ui/content/modules/b945370f1fa784f9/chunk.js +0 -13
  264. package/dist/web-ui/content/modules/ba5fa76884e1f806/chunk.js +0 -1
  265. package/dist/web-ui/content/modules/bb1bb9460cc10fbe/host.js +0 -1
  266. package/dist/web-ui/content/modules/be7f1f9183a1247f/chunk.js +0 -3
  267. package/dist/web-ui/content/modules/bf7449bcf95e1454/chunk.js +0 -1
  268. package/dist/web-ui/content/modules/c091efd46e221c29/chunk.js +0 -1
  269. package/dist/web-ui/content/modules/c1ec2ebce8ea5dd8/dialog-modal.js +0 -4
  270. package/dist/web-ui/content/modules/c2f7bb50118f1603/chunk.js +0 -1
  271. package/dist/web-ui/content/modules/c369ce4eb71277e6/host.js +0 -1
  272. package/dist/web-ui/content/modules/c46b3501573953e9/chunk.js +0 -1
  273. package/dist/web-ui/content/modules/c577ad641502d509/panel-host.js +0 -1
  274. package/dist/web-ui/content/modules/c75976857c18f251/host.js +0 -1
  275. package/dist/web-ui/content/modules/c8eaffbedda0d3d0/queue-view-adapter.js +0 -3
  276. package/dist/web-ui/content/modules/cadd26ae50359434/chunk.js +0 -1
  277. package/dist/web-ui/content/modules/d37ff6684c9aeeec/chunk.js +0 -3
  278. package/dist/web-ui/content/modules/d48c1f89342bc4bc/workspace-window.js +0 -1
  279. package/dist/web-ui/content/modules/d859a83f486aab23/chunk.js +0 -15
  280. package/dist/web-ui/content/modules/d8b258a6455d77da/host.js +0 -5
  281. package/dist/web-ui/content/modules/d937e939122180b9/host.js +0 -1
  282. package/dist/web-ui/content/modules/e020beea3e7da7db/chunk.js +0 -1
  283. package/dist/web-ui/content/modules/e2feda63a603c64e/group-editor.js +0 -1
  284. package/dist/web-ui/content/modules/e70296674a841d60/chunk.js +0 -1
  285. package/dist/web-ui/content/modules/ec2f6b23d12d3a15/chunk.js +0 -1
  286. package/dist/web-ui/content/modules/ede751e1f2500d03/employee-profile.js +0 -1
  287. package/dist/web-ui/content/modules/ee4301b734e2fd43/chunk.js +0 -1
  288. package/dist/web-ui/content/modules/f4e6095edc32562c/markdown.js +0 -1
  289. package/dist/web-ui/content/modules/f7f0710962cab0e0/chunk.js +0 -10
  290. package/dist/web-ui/content/modules/fe30627fc1e59d4f/chunk.js +0 -1
  291. package/dist/web-ui/content/modules/ffbd3bcaecd8e814/task-board-host.js +0 -10
@@ -1,7 +1,7 @@
1
1
  import { asyncRoute } from "./express-async.js";
2
2
  import { surfaceDomainError } from "./http-error.js";
3
3
  import { sendRouteError } from "./server-request.js";
4
- import { discoverPiResources, resolvePiResourceSelection } from "./pi-resource-catalog.js";
4
+ import { discoverPiResources, resolvePiResourceSettingsPatch } from "./pi-resource-catalog.js";
5
5
  import { defaultPiCliSessionSettings, effectivePiSessionSettings, mergePiSessionDefaults, patchPiSessionSettings, } from "./pi-session-settings.js";
6
6
  const DOMAIN_MESSAGE = /^(Pi 设置必须是对象。|请选择有效的 Skills \/ MCP 列表。|资源选择不能包含路径、命令或其他设置。|资源选择必须是无重复的已安装资源 ID(每类最多64项)。|锁定技能必须是无重复的已安装 Skill ID(最多64项)。|CodeMode 请选择跟随 Pi、关闭、启用或仅 CodeMode。|CodeMode 必须是 off、on 或 only。|基础工具必须是无重复的 Pi 工具列表。|.+ 必须是是否启用(boolean)。|未知 Pi 设置:.+|所选 Skill 已不存在或已被停用,请重新选择;没有改用其他 Skill。|所选 MCP 已不存在,请重新选择;没有连接其他 MCP。)$/;
7
7
  /**
@@ -10,7 +10,7 @@ const DOMAIN_MESSAGE = /^(Pi 设置必须是对象。|请选择有效的 Skills
10
10
  * 之前只有「在某个会话里改一次,顺带成为新会话默认」这一条隐式路径,用户在设置页
11
11
  * 找不到它;而会话里的写入又只能表达会话本身的选择。这里给出显式入口,语义与
12
12
  * `StructuredSessionManager.setPiSettings` 写回默认的那一段保持一致(字段级合并、
13
- * 资源必须真实存在、不可表达的值直接拒绝)。
13
+ * 新增资源必须真实存在、不可表达的值直接拒绝)。
14
14
  */
15
15
  export function registerPiDefaultsRoutes(app, deps) {
16
16
  const readDefaults = () => deps.storage.getPiSessionDefaults()
@@ -42,26 +42,19 @@ export function registerPiDefaultsRoutes(app, deps) {
42
42
  }));
43
43
  app.patch("/api/pi-settings/defaults", asyncRoute(async (req, res) => {
44
44
  try {
45
- const body = req.body;
45
+ let patch = req.body;
46
46
  const current = readDefaults();
47
47
  // 先按现有默认校验字段本身;再按「只合并本次改动」落库,与会话写入同一套语义。
48
- const patched = patchPiSessionSettings(current, body);
49
- const next = mergePiSessionDefaults(current, body);
50
- if (body && typeof body === "object" && !Array.isArray(body)) {
51
- const touched = body;
52
- if (touched.resources !== undefined || touched.lockedSkills !== undefined) {
53
- const inventory = await discoverPiResources(deps.config, deps.config.defaultCwd);
54
- if (touched.resources !== undefined)
55
- resolvePiResourceSelection(inventory, next.resources ?? { skills: [], mcpServers: [] });
56
- if (touched.lockedSkills !== undefined) {
57
- resolvePiResourceSelection(inventory, { skills: next.lockedSkills ?? [], mcpServers: [] });
58
- }
59
- }
60
- if (next.autoResources === true) {
61
- const reason = autoResourcesReason(next);
62
- if (reason)
63
- throw new Error(reason);
64
- }
48
+ patchPiSessionSettings(current, patch);
49
+ if (patch.resources !== undefined || patch.lockedSkills !== undefined) {
50
+ const inventory = await discoverPiResources(deps.config, deps.config.defaultCwd);
51
+ patch = resolvePiResourceSettingsPatch(inventory, readDefaults(), patch);
52
+ }
53
+ const next = mergePiSessionDefaults(readDefaults(), patch);
54
+ if (next.autoResources === true) {
55
+ const reason = autoResourcesReason(next);
56
+ if (reason)
57
+ throw new Error(reason);
65
58
  }
66
59
  deps.storage.setPiSessionDefaults(next);
67
60
  res.json({ settings: effectivePiSessionSettings(next, "cli") });
@@ -11,7 +11,7 @@ import { toSessionDetailDTO } from "./session-transport.js";
11
11
  import { compactToolMessagesForTransport, windowMessagesForTransport } from "./message-truncator.js";
12
12
  import { enrichStructuredMessages } from "./structured-client-protocol.js";
13
13
  import { installedPiExtensions } from "./pi-extension-resources.js";
14
- import { discoverPiResources, resolvePiResourceSelection } from "./pi-resource-catalog.js";
14
+ import { discoverPiResources, resolvePiResourceSettingsPatch } from "./pi-resource-catalog.js";
15
15
  import { effectivePiSessionSettings, patchPiSessionSettings } from "./pi-session-settings.js";
16
16
  import { isProviderSessionId } from "./resume-policy.js";
17
17
  import { sendRouteError } from "./server-request.js";
@@ -64,7 +64,7 @@ export function registerSessionLifecycleRoutes(app, ctx) {
64
64
  if (body.mode !== undefined && !isExecutionMode(body.mode))
65
65
  throw badRequest(`无效执行模式: ${String(body.mode)}`);
66
66
  const initialInput = body.initialInput?.trim();
67
- const origin = parseSessionCreationOrigin(body);
67
+ const origin = parseSessionCreationOrigin(body, interactiveShell);
68
68
  const rawModel = typeof body.model === "string" ? body.model.trim() : "";
69
69
  const rawCommand = body.command?.trim() ?? "";
70
70
  const provider = interactiveShell
@@ -208,6 +208,14 @@ export function registerSessionLifecycleRoutes(app, ctx) {
208
208
  sendRouteError(res, surfaceDomainError(error, /Wand Agent|harness|core/i) ?? error, "无法启动结构化会话。");
209
209
  }
210
210
  }));
211
+ app.put("/api/sessions/:id/quick-terminal", (req, res) => {
212
+ try {
213
+ res.json(sessionResponseDTO(sessions.claimQuickTerminal(req.params.id), req));
214
+ }
215
+ catch (error) {
216
+ sendRouteError(res, error, "无法连接快捷终端。");
217
+ }
218
+ });
211
219
  app.post("/api/sessions/:id/directory", (req, res) => {
212
220
  const cwd = req.body?.cwd;
213
221
  if (typeof cwd !== "string" || !cwd.trim()) {
@@ -306,6 +314,7 @@ export function registerSessionLifecycleRoutes(app, ctx) {
306
314
  requirePiSession(id);
307
315
  const { settings } = structured.getPiSettings(id);
308
316
  const next = patchPiSessionSettings(settings, req.body);
317
+ let patch = req.body;
309
318
  if (req.body.autoResources === true) {
310
319
  const capabilities = await piSettingsResponse(id);
311
320
  const runtime = decisions?.status();
@@ -315,26 +324,17 @@ export function registerSessionLifecycleRoutes(app, ctx) {
315
324
  : capabilities.autoResourcesReason || "自动选择暂不可用。");
316
325
  }
317
326
  }
318
- if (req.body.resources !== undefined || req.body.lockedSkills !== undefined) {
319
- const inventory = await discoverPiResources(config, structured.get(id).cwd);
320
- // Removed resources may be retained only when already selected, so users can deselect stale
321
- // items one at a time. Any NEW ID must resolve; the runner always revalidates the full list.
322
- if (req.body.resources !== undefined)
323
- resolvePiResourceSelection(inventory, {
324
- skills: next.resources.skills.filter((id) => !settings.resources?.skills.includes(id)),
325
- mcpServers: next.resources.mcpServers.filter((id) => !settings.resources?.mcpServers.includes(id)),
326
- });
327
- if (req.body.lockedSkills !== undefined)
328
- resolvePiResourceSelection(inventory, {
329
- skills: next.lockedSkills.filter((id) => !settings.lockedSkills?.includes(id)), mcpServers: [],
330
- });
331
- }
332
327
  if (next.goalMode && !settings.goalMode) {
333
328
  const installed = await installedPiExtensions(config, structured.get(id).cwd);
334
329
  if (!installed.some((item) => item.goal))
335
330
  throw badRequest("目标模式不可用:请先在 Pi 中安装并启用 pi-goal。");
336
331
  }
337
- structured.setPiSettings(id, req.body);
332
+ if (req.body.resources !== undefined || req.body.lockedSkills !== undefined) {
333
+ const inventory = await discoverPiResources(config, structured.get(id).cwd);
334
+ // A lock-only patch must release from the latest selection after asynchronous discovery.
335
+ patch = resolvePiResourceSettingsPatch(inventory, structured.getPiSettings(id).settings, patch);
336
+ }
337
+ structured.setPiSettings(id, patch);
338
338
  // 回复「实际生效」的设置(CLI 的 CodeMode 只归一到 off/on),不把存库原值当生效值展示。
339
339
  const saved = structured.getPiSettings(id);
340
340
  res.json({ settings: effectivePiSessionSettings(saved.settings, saved.resolution.engine) });
@@ -88,7 +88,7 @@ export function registerSessionListRoutes(app, ctx) {
88
88
  }
89
89
  });
90
90
  app.get("/api/sessions", (req, res) => {
91
- res.json(sessions.listSlim().map((session) => toSessionListItemDTO(session)));
91
+ res.json(sessions.listSlim().filter(session => session.sessionSource !== "quick-terminal").map((session) => toSessionListItemDTO(session)));
92
92
  });
93
93
  app.get("/api/sessions/provider-usage", (_req, res) => {
94
94
  res.json(storage.countInteractiveSessionsByProvider());
@@ -17,6 +17,7 @@ import { parseWandTaskAgent } from "./storage.js";
17
17
  import { compactTransportAvatar } from "./fixed-employee-avatar.js";
18
18
  import { canArchiveTask } from "./task-archive-policy.js";
19
19
  import { TaskReadModel } from "./task-read-model.js";
20
+ import { readTaskActions } from "./task-actions.js";
20
21
  import { refreshAutoBoardTaskTitles, taskTitleService } from "./task-title-service.js";
21
22
  import { provisionalTaskTitleFromDescription } from "./task-title.js";
22
23
  import { isWandTaskStatus, statusAfterWandTaskDispatch } from "./task-types.js";
@@ -217,6 +218,11 @@ export function registerTaskRoutes(app, deps) {
217
218
  res.json(model.tasks.filter(task => workspaceId === undefined || task.workspaceId === workspaceId)
218
219
  .map(task => taskDto(deps, task, model)));
219
220
  });
221
+ app.get("/api/wand-task-actions", (req, res) => {
222
+ const workspaceId = typeof req.query.workspaceId === "string" ? req.query.workspaceId : undefined;
223
+ res.set("Cache-Control", "no-store");
224
+ res.json(readTaskActions(storage, sessions, workspaceId));
225
+ });
220
226
  registerTaskCommentRoutes(app, deps);
221
227
  app.get("/api/wand-task-agent-defaults", (_req, res) => {
222
228
  res.json(readTaskBoardLastAgent(storage));
@@ -49,6 +49,7 @@ export interface PublicUpdateRoutesDependencies {
49
49
  resolveMacosBetaDownload(fileName: string): Promise<DownloadAsset | null>;
50
50
  resolveLatestIpa(): Promise<ResolvedUpdateAsset | null>;
51
51
  resolveIosDownload(): Promise<DownloadAsset | null>;
52
+ resolveIosAppDownload?(appId: string, fileName?: string): Promise<DownloadAsset | null>;
52
53
  }
53
54
  export declare function registerPublicUpdateRoutes(app: Express, deps: PublicUpdateRoutesDependencies, publicOrigin?: string): void;
54
55
  export declare class ServerUpdateState {
@@ -253,11 +253,15 @@ export function registerPublicUpdateRoutes(app, deps, publicOrigin) {
253
253
  });
254
254
  return;
255
255
  }
256
- const updateAvailable = compareWandInstallOrder(payload.latestVersion, currentVersion) > 0;
256
+ const versionOrder = compareWandInstallOrder(payload.latestVersion, currentVersion);
257
+ const currentBuild = text(req.query.currentBuild);
258
+ const updateAvailable = versionOrder > 0 || (versionOrder === 0 && !!currentBuild
259
+ && compareWandInstallOrder(payload.bundleBuild, currentBuild) > 0);
257
260
  res.json({
258
261
  updateAvailable,
259
262
  currentVersion,
260
263
  latestVersion: payload.latestVersion,
264
+ latestBuild: payload.bundleBuild,
261
265
  downloadUrl: updateAvailable ? payload.downloadUrl : null,
262
266
  installUrl: updateAvailable ? payload.installUrl : null,
263
267
  manifestUrl: payload.manifestUrl,
@@ -291,22 +295,27 @@ export function registerPublicUpdateRoutes(app, deps, publicOrigin) {
291
295
  res.setHeader("Cache-Control", "no-cache");
292
296
  res.send(buildIosInstallPage({
293
297
  title: payload.title,
294
- version: payload.latestVersion,
298
+ version: iosAppId(req) ? `${payload.latestVersion}(${payload.bundleBuild})` : payload.latestVersion,
295
299
  sizeLabel: formatIosAssetSize(payload.size),
296
300
  installUrl: payload.installUrl ?? "#",
297
301
  downloadUrl: payload.downloadUrl,
298
302
  signed: payload.signed,
299
303
  https: payload.origin.startsWith("https://"),
304
+ apps: await resolveIosInstallLinks(req, deps, publicOrigin),
300
305
  }));
301
306
  }));
302
307
  app.get("/ios/download", asyncRoute(async (req, res) => {
303
- const asset = await deps.resolveIosDownload();
308
+ const appId = iosAppId(req);
309
+ const asset = appId
310
+ ? await deps.resolveIosAppDownload?.(appId, text(req.query.fileName) || undefined)
311
+ : await deps.resolveIosDownload();
304
312
  if (!asset) {
305
313
  res.status(404).json({ error: "当前没有可下载的 IPA 文件。" });
306
314
  return;
307
315
  }
308
316
  // iOS 每次 debug 构建产出独立时间戳的 IPA,不清理会按构建次数堆积。
309
- await pruneQuietly(deps.pruneIosIpaDirectory?.bind(deps), asset.fileName, " iOS 构建包");
317
+ if (!appId)
318
+ await pruneQuietly(deps.pruneIosIpaDirectory?.bind(deps), asset.fileName, " iOS 构建包");
310
319
  streamFileWithRange(req, res, {
311
320
  filePath: asset.filePath,
312
321
  size: asset.size,
@@ -316,9 +325,19 @@ export function registerPublicUpdateRoutes(app, deps, publicOrigin) {
316
325
  });
317
326
  }));
318
327
  }
319
- async function resolveIosOtaPayload(req, deps, publicOrigin) {
320
- const latest = await deps.resolveLatestIpa();
321
- const local = await deps.resolveIosDownload();
328
+ function iosAppId(req) {
329
+ if (req.query.app === undefined)
330
+ return undefined;
331
+ if (req.query.app !== "huniu-helper")
332
+ throw new HttpError(404, "unknown_app", "未知的 iOS 应用。");
333
+ return "huniu-helper";
334
+ }
335
+ async function resolveIosOtaPayload(req, deps, publicOrigin, selection) {
336
+ const appId = selection ? selection.appId : iosAppId(req);
337
+ const local = appId
338
+ ? await deps.resolveIosAppDownload?.(appId, selection ? undefined : text(req.query.fileName) || undefined)
339
+ : await deps.resolveIosDownload();
340
+ const latest = appId ? null : await deps.resolveLatestIpa();
322
341
  if (!latest && !local)
323
342
  return null;
324
343
  // Explicit ?origin= wins; then the deployment's configured publicOrigin
@@ -334,13 +353,17 @@ async function resolveIosOtaPayload(req, deps, publicOrigin) {
334
353
  const size = local?.size ?? latest?.size ?? 0;
335
354
  const latestVersion = latest?.version ?? "0.0.0";
336
355
  const metadata = local
337
- ? await inspectIpa(local.filePath, { version: latestVersion }).catch(() => ({
338
- bundleId: "com.wand.app",
339
- bundleVersion: latestVersion,
340
- bundleBuild: latestVersion,
341
- title: "Wand",
342
- signed: false,
343
- }))
356
+ ? await inspectIpa(local.filePath, { version: latestVersion }).catch((error) => {
357
+ if (appId)
358
+ throw error;
359
+ return {
360
+ bundleId: "com.wand.app",
361
+ bundleVersion: latestVersion,
362
+ bundleBuild: latestVersion,
363
+ title: "Wand",
364
+ signed: false,
365
+ };
366
+ })
344
367
  : {
345
368
  bundleId: "com.wand.app",
346
369
  bundleVersion: latestVersion,
@@ -348,10 +371,17 @@ async function resolveIosOtaPayload(req, deps, publicOrigin) {
348
371
  title: "Wand",
349
372
  signed: false,
350
373
  };
351
- const downloadPath = latest?.downloadUrl ?? "/ios/download";
374
+ if (appId && metadata.bundleId !== "dev.tigertools.PlaylistBridge") {
375
+ throw new HttpError(503, "invalid_app_package", "所选 iOS 安装包身份不匹配。");
376
+ }
377
+ // Pin both manifest and IPA: publishing a new build must not change an in-flight install.
378
+ const suffix = appId ? `?app=${appId}&fileName=${encodeURIComponent(fileName)}` : "";
379
+ const downloadPath = appId ? `/ios/download${suffix}` : (latest?.downloadUrl ?? "/ios/download");
352
380
  const downloadUrl = origin ? absoluteUrl(origin, downloadPath) : downloadPath;
353
- const manifestUrl = origin ? absoluteUrl(origin, "/ios/manifest.plist") : "/ios/manifest.plist";
354
- const installPageUrl = origin ? absoluteUrl(origin, "/ios/install") : "/ios/install";
381
+ const manifestPath = `/ios/manifest.plist${suffix}`;
382
+ const installPath = appId ? `/ios/install?app=${appId}` : "/ios/install";
383
+ const manifestUrl = origin ? absoluteUrl(origin, manifestPath) : manifestPath;
384
+ const installPageUrl = origin ? absoluteUrl(origin, installPath) : installPath;
355
385
  const blockers = collectIosOtaBlockers({
356
386
  signed: metadata.signed,
357
387
  origin,
@@ -367,6 +397,7 @@ async function resolveIosOtaPayload(req, deps, publicOrigin) {
367
397
  });
368
398
  return {
369
399
  latestVersion: metadata.bundleVersion || latestVersion,
400
+ bundleBuild: metadata.bundleBuild,
370
401
  downloadUrl,
371
402
  installUrl: origin ? buildItmsServicesUrl(manifestUrl) : null,
372
403
  manifestUrl,
@@ -383,6 +414,20 @@ async function resolveIosOtaPayload(req, deps, publicOrigin) {
383
414
  manifest,
384
415
  };
385
416
  }
417
+ async function resolveIosInstallLinks(req, deps, publicOrigin) {
418
+ const currentApp = iosAppId(req);
419
+ const selections = [{}, { appId: "huniu-helper" }];
420
+ // One missing/broken package must not hide the other app's valid installer.
421
+ const results = await Promise.allSettled(selections.map(selection => resolveIosOtaPayload(req, deps, publicOrigin, selection)));
422
+ return results.flatMap((result, index) => {
423
+ if (result.status !== "fulfilled" || !result.value?.otaReady)
424
+ return [];
425
+ return [{
426
+ title: result.value.title, url: result.value.installPageUrl,
427
+ current: selections[index].appId === currentApp,
428
+ }];
429
+ });
430
+ }
386
431
  export class ServerUpdateState {
387
432
  providerCliUpdateCache = null;
388
433
  providerCliUpdateInFlight = false;
@@ -227,7 +227,7 @@ function workspaceWithCounts(storage, workspace, sessionCounts, includeArchived
227
227
  const worktreeCount = storage.listWorkspaceTasks(workspace.id)
228
228
  .filter((task) => (includeArchived || !task.archived) && task.worktree !== null)
229
229
  .length;
230
- const sessionCount = (sessionCounts ?? storage.countSessionsByWorkspace({ includeArchived, excludeSystemAiCalls: true })).get(workspace.id) ?? 0;
230
+ const sessionCount = (sessionCounts ?? storage.countSessionsByWorkspace({ includeArchived, excludeSystemAiCalls: true, excludeQuickTerminals: true })).get(workspace.id) ?? 0;
231
231
  return { ...workspace, worktreeCount, sessionCount };
232
232
  }
233
233
  // ── Layout validation / sanitization(前端 PUT 与测试共用)──
@@ -341,7 +341,7 @@ export function registerWorkspaceRoutes(app, storage, sessions, titleOptions = {
341
341
  // 列出所有项目(按创建时间降序:新建在前,打开不会改位置)
342
342
  app.get("/api/workspaces", (req, res) => {
343
343
  const includeArchived = req.query.includeArchived === "1";
344
- const sessionCounts = storage.countSessionsByWorkspace({ includeArchived, excludeSystemAiCalls: true });
344
+ const sessionCounts = storage.countSessionsByWorkspace({ includeArchived, excludeSystemAiCalls: true, excludeQuickTerminals: true });
345
345
  res.json(storage.listWorkspaces()
346
346
  .filter((workspace) => !isGlobalWorkspace(workspace))
347
347
  .map((workspace) => workspaceWithCounts(storage, workspace, sessionCounts, includeArchived)));
@@ -380,7 +380,7 @@ export function registerWorkspaceRoutes(app, storage, sessions, titleOptions = {
380
380
  const archivedTaskIds = new Set(storage.listWorkspaceTasks(workspace.id)
381
381
  .filter((task) => task.archived).map((task) => task.id));
382
382
  const teamMarkers = teamSessionMarkers(storage);
383
- const visibleSessions = storage.listSessionsByWorkspaceSlim(workspace.id).filter((session) => !isSystemAiCall(session)).map((session) => ({
383
+ const visibleSessions = storage.listSessionsByWorkspaceSlim(workspace.id).filter((session) => !isSystemAiCall(session) && session.sessionSource !== "quick-terminal").map((session) => ({
384
384
  ...workspaceSessionSummary(session, { workspaceName: workspace.name }, sessions, teamMarkersFor(teamMarkers, session.id)),
385
385
  workspaceTaskId: session.workspaceTaskId,
386
386
  })).filter((session) => includeArchived || (!session.archived
@@ -614,7 +614,7 @@ export function registerWorkspaceRoutes(app, storage, sessions, titleOptions = {
614
614
  // Server-owned one-shot feature logs are not Agent work. Do not filter by employee,
615
615
  // sessionSource=automation or generic automation IDs: those also carry dispatch,
616
616
  // communication and scheduled work. Keep storage and employee audit history intact.
617
- const sessionVisible = (session) => !isSystemAiCall(session)
617
+ const sessionVisible = (session) => !isSystemAiCall(session) && session.sessionSource !== "quick-terminal"
618
618
  && (includeArchived || !session.archived);
619
619
  const workspaces = [...model.workspaces.values()];
620
620
  // 群聊与成员派发标记一次查全:列表里每条会话只做 Map 命中,不逐个查库。
@@ -925,7 +925,7 @@ export function registerWorkspaceRoutes(app, storage, sessions, titleOptions = {
925
925
  const workspace = storage.getWorkspace(task.workspaceId);
926
926
  const teamMarkers = teamSessionMarkers(storage);
927
927
  const card = storage.getWandTaskByWorkspaceTaskId(task.id);
928
- const taskSessions = storage.listSessionsByWorkspaceTaskSlim(task.id).filter(session => !isSystemAiCall(session))
928
+ const taskSessions = storage.listSessionsByWorkspaceTaskSlim(task.id).filter(session => !isSystemAiCall(session) && session.sessionSource !== "quick-terminal")
929
929
  .map(session => liveSession(session, sessions));
930
930
  res.json({
931
931
  ...task,
package/dist/server.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { registerKnowledgeRoutes } from "./server-knowledge-routes.js";
1
2
  import { OpenRouterFreeModelsService } from "./openrouter-free-models.js";
2
3
  import { OpenCodeFreeModelsService, registerOpenCodeFreePool, adoptSystemOpenCodeFreeDefault } from "./opencode-system-fallback.js";
3
4
  import { OPENCODE_FREE_GROUP_ID, OPENCODE_FREE_GROUP_NAME } from "./opencode-free-selection.js";
@@ -419,7 +420,7 @@ export async function startServer(config, configPath, options = {}) {
419
420
  storage, config, structured: structuredSessions, processes, sessions: sessionRegistry,
420
421
  });
421
422
  structuredSessions.setEmployeeInputAdmission({
422
- canStart: (session, scheduling) => taskExecutionQueue.canStartSession(session, scheduling),
423
+ canStart: (session, scheduling, immediate) => taskExecutionQueue.canStartSession(session, scheduling, immediate),
423
424
  schedule: employeeId => taskExecutionQueue.scheduleDrain(employeeId),
424
425
  });
425
426
  let apnsConfiguration = null;
@@ -688,6 +689,7 @@ export async function startServer(config, configPath, options = {}) {
688
689
  executionQueue: taskExecutionQueue,
689
690
  notifyEmployeeChanged: (employeeId) => notifyAiTeamRun({ kind: "silicon-employee-definition", employeeId }),
690
691
  });
692
+ registerKnowledgeRoutes(app, storage);
691
693
  registerEmployeeImRoutes(app, { storage, im: employeeIm, requireAdmin });
692
694
  registerDingTalkRoutes(app, { service: dingtalk, requireAdmin, install: () => dingtalkDws.install() });
693
695
  registerAttentionRoutes(app, { sessions: sessionRegistry, runner: aiTeams });
@@ -1074,7 +1076,7 @@ export async function startServer(config, configPath, options = {}) {
1074
1076
  }, MODEL_CATALOG_AUTO_REFRESH_INTERVAL_MS);
1075
1077
  modelCatalogRefreshTimer.unref();
1076
1078
  }
1077
- // 会话仍按固定 7 天归档再清理;任务窗口每次扫描读取当前设置。
1079
+ // 每次扫描读取当前保留窗口;未完成、待验收和升级前任务归档不进入自动清理。
1078
1080
  // 保存任务保留设置后走同一条扫描,不等下一小时。
1079
1081
  const retentionDeps = {
1080
1082
  storage,
@@ -0,0 +1,7 @@
1
+ import type { ConversationTurn, SessionSnapshot, StructuredQuestion, ToolUseBlock } from "./types.js";
2
+ export declare function sessionToolQuestions(block: ToolUseBlock): StructuredQuestion[];
3
+ /** One source session, latest assistant request only. Historical cards stay read-only. */
4
+ export declare function pendingSessionQuestions(session: Pick<SessionSnapshot, "status"> & {
5
+ archived?: boolean;
6
+ messages?: ConversationTurn[];
7
+ }): ToolUseBlock[];
@@ -0,0 +1,25 @@
1
+ export function sessionToolQuestions(block) {
2
+ if (block.semantic?.kind === "question_request")
3
+ return block.semantic.questions;
4
+ // Legacy Claude recordings predate the semantic projection.
5
+ if (block.name === "AskUserQuestion" && Array.isArray(block.input.questions))
6
+ return block.input.questions;
7
+ return [];
8
+ }
9
+ /** One source session, latest assistant request only. Historical cards stay read-only. */
10
+ export function pendingSessionQuestions(session) {
11
+ if (session.archived || ["failed", "stopped", "exited"].includes(session.status))
12
+ return [];
13
+ const turns = session.messages ?? [];
14
+ const results = new Set(turns.flatMap(turn => turn.content.flatMap(block => block.type === "tool_result" ? [block.tool_use_id] : [])));
15
+ for (let index = turns.length - 1; index >= 0; index--) {
16
+ const turn = turns[index];
17
+ if (turn.role === "user" && turn.content.some(block => block.type === "text" && block.text.trim()))
18
+ return [];
19
+ if (turn.role !== "assistant")
20
+ continue;
21
+ return turn.content.filter((block) => block.type === "tool_use"
22
+ && sessionToolQuestions(block).length > 0 && !results.has(block.id));
23
+ }
24
+ return [];
25
+ }
@@ -39,6 +39,9 @@ export declare class SessionRegistry {
39
39
  ownerOf(id: string): SessionOwner | null;
40
40
  get(id: string): SessionSnapshot | null;
41
41
  getLatest(id: string): SessionSnapshot | null;
42
+ claimQuickTerminal(id: string): SessionSnapshot;
43
+ /** Read-only runtime owner. Never hydrate a stored transcript to discover actions. */
44
+ getRuntimeSnapshot(id: string): SessionSnapshot | null;
42
45
  /** Runtime facts and membership only; list/policy reads must not hydrate transcripts. */
43
46
  getSlim(id: string): SessionSnapshot | null;
44
47
  listSlim(options?: {
@@ -6,6 +6,8 @@ import { systemAiSessions } from "./system-ai-session-recorder.js";
6
6
  import { cleanupWorktreeSync } from "./git-worktree.js";
7
7
  import { inferProviderFromCommand } from "./session-provider.js";
8
8
  import { enrichStructuredMessages } from "./structured-client-protocol.js";
9
+ import { canClaimQuickTerminal } from "./quick-terminal-session.js";
10
+ import { badRequest, notFound } from "./http-error.js";
9
11
  export function deleteProviderNativeHistory(deleter, provider, providerSessionId, cwd) {
10
12
  const id = providerSessionId.trim();
11
13
  if (!id)
@@ -168,6 +170,21 @@ export class SessionRegistry {
168
170
  getLatest(id) {
169
171
  return this.get(id);
170
172
  }
173
+ claimQuickTerminal(id) {
174
+ const snapshot = this.get(id);
175
+ if (!snapshot)
176
+ throw notFound("未找到该终端,可能已被删除。");
177
+ if (!canClaimQuickTerminal(snapshot))
178
+ throw badRequest("只有普通空白终端可以作为快捷终端。");
179
+ const updated = this.storage.claimQuickTerminal(id);
180
+ if (this.processes.getOwned(id))
181
+ this.processes.setSessionSource(id, updated.sessionSource);
182
+ return this.get(id);
183
+ }
184
+ /** Read-only runtime owner. Never hydrate a stored transcript to discover actions. */
185
+ getRuntimeSnapshot(id) {
186
+ return this.structured.get(id) ?? this.processes.getOwned(id) ?? null;
187
+ }
171
188
  /** Runtime facts and membership only; list/policy reads must not hydrate transcripts. */
172
189
  getSlim(id) {
173
190
  const snapshot = this.structured.getSlim(id) ?? this.processes.getOwnedSlim(id) ?? this.storage.getSessionSlim(id);
@@ -3,7 +3,7 @@ export declare function parseExecutionMode(value: unknown, fallback: ExecutionMo
3
3
  export declare function parseSessionCreationOrigin(body: {
4
4
  sessionSource?: unknown;
5
5
  automationId?: unknown;
6
- } | null | undefined): {
6
+ } | null | undefined, allowQuickTerminal?: boolean): {
7
7
  sessionSource: SessionSource;
8
8
  automationId?: string;
9
9
  };
@@ -1,5 +1,6 @@
1
1
  import { isExecutionMode } from "./config.js";
2
2
  import { isSystemAiCall } from "./system-ai-call.js";
3
+ import { badRequest } from "./http-error.js";
3
4
  export function parseExecutionMode(value, fallback) {
4
5
  if (value === undefined)
5
6
  return fallback;
@@ -8,9 +9,12 @@ export function parseExecutionMode(value, fallback) {
8
9
  }
9
10
  return value;
10
11
  }
11
- export function parseSessionCreationOrigin(body) {
12
+ export function parseSessionCreationOrigin(body, allowQuickTerminal = false) {
12
13
  const rawSource = body?.sessionSource;
13
- if (rawSource !== undefined && rawSource !== "interactive" && rawSource !== "automation" && rawSource !== "startup") {
14
+ if (rawSource === "quick-terminal" && (!allowQuickTerminal || body?.automationId !== undefined)) {
15
+ throw badRequest("快捷终端只允许无自动化绑定的空白 PTY shell。");
16
+ }
17
+ if (rawSource !== undefined && rawSource !== "interactive" && rawSource !== "automation" && rawSource !== "startup" && rawSource !== "quick-terminal") {
14
18
  throw new Error("sessionSource 必须是 interactive、automation 或 startup。");
15
19
  }
16
20
  const rawAutomationId = body?.automationId;
@@ -102,7 +102,7 @@ export function sessionSortTimestamp(snapshot) {
102
102
  return Number.isFinite(timestamp) ? timestamp : 0;
103
103
  }
104
104
  export function buildSessionListEntries(sessions) {
105
- return sessions.map((session) => ({
105
+ return sessions.filter(session => session.sessionSource !== "quick-terminal").map((session) => ({
106
106
  type: "managed",
107
107
  key: `session-${session.id}`,
108
108
  sortTimestamp: sessionSortTimestamp(session),
@@ -262,15 +262,18 @@ export class EmployeeRepository {
262
262
  if (accessToken && this.resolveEmployeeKnowledgeAccess(accessToken) !== employeeId) {
263
263
  throw new Error("知识库访问已失效,请等待新的会话执行。");
264
264
  }
265
- return this.db.prepare("DELETE FROM employee_knowledge WHERE employee_id = ? AND id = ?")
265
+ const deleted = this.db.prepare("DELETE FROM employee_knowledge WHERE employee_id = ? AND id = ?")
266
266
  .run(employeeId, entryId).changes === 1;
267
+ if (deleted)
268
+ this.s.invalidateKnowledgeNamespace("personal", employeeId);
269
+ return deleted;
267
270
  });
268
271
  }
269
272
  clearEmployeeKnowledge(employeeId) {
270
273
  this.s.transaction(() => {
271
274
  this.requireKnowledgeEmployee(employeeId);
272
275
  this.db.prepare("DELETE FROM employee_knowledge WHERE employee_id = ?").run(employeeId);
273
- this.db.prepare("DELETE FROM employee_knowledge_access WHERE employee_id = ?").run(employeeId);
276
+ this.s.invalidateKnowledgeNamespace("personal", employeeId);
274
277
  });
275
278
  }
276
279
  /** Opaque per-execution capability: no employee selector, app token or DB secret in model prompts. */
@@ -0,0 +1,35 @@
1
+ import type { DatabaseSync } from "node:sqlite";
2
+ import type { WandStorage } from "../storage.js";
3
+ import { type KnowledgeAccess, type KnowledgeDocument, type KnowledgeDocumentInput, type KnowledgeLibrary, type KnowledgeScope } from "../knowledge-types.js";
4
+ export declare class KnowledgeRepository {
5
+ #private;
6
+ private readonly db;
7
+ private readonly s;
8
+ constructor(db: DatabaseSync, s: WandStorage);
9
+ knowledgeOwners(): {
10
+ employees: Array<{
11
+ id: string;
12
+ name: string;
13
+ }>;
14
+ projects: Array<{
15
+ id: string;
16
+ name: string;
17
+ readOnly: boolean;
18
+ }>;
19
+ };
20
+ readKnowledgeLibrary(scope: KnowledgeScope, ownerId: string, query?: string, accessToken?: string): KnowledgeLibrary;
21
+ getKnowledgeDocument(scope: KnowledgeScope, ownerId: string, id: string, accessToken?: string): KnowledgeDocument;
22
+ createKnowledgeDocument(scope: KnowledgeScope, ownerId: string, input: KnowledgeDocumentInput, accessToken?: string): {
23
+ entry: KnowledgeDocument;
24
+ created: boolean;
25
+ };
26
+ updateKnowledgeDocument(scope: KnowledgeScope, ownerId: string, id: string, revision: number, input: KnowledgeDocumentInput, accessToken?: string): KnowledgeDocument;
27
+ deleteKnowledgeDocument(scope: KnowledgeScope, ownerId: string, id: string, revision: number, accessToken?: string): void;
28
+ invalidateKnowledgeNamespace(scope: KnowledgeScope, ownerId: string): void;
29
+ /** Only persisted bindings count; legacy UI identity projections are not authority. */
30
+ knowledgeSessionScope(sessionId: string): KnowledgeAccess | null;
31
+ issueKnowledgeAccess(sessionId: string, now?: number): string;
32
+ resolveKnowledgeAccess(token: string, now?: number): KnowledgeAccess | null;
33
+ revokeKnowledgeAccess(token: string): void;
34
+ revokeSessionKnowledgeAccess(sessionId: string): void;
35
+ }