@jingyi0605/codingns 0.3.5 → 0.4.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 (255) hide show
  1. package/README.md +16 -0
  2. package/bin/codingns.mjs +1369 -10
  3. package/dist/public/assets/{TerminalPage-CgrfstRm.js → TerminalPage-6jHZV9Mh.js} +17 -17
  4. package/dist/public/assets/index-CSVhg7I8.js +123 -0
  5. package/dist/public/assets/index-Ce1VX19m.css +1 -0
  6. package/dist/public/index.html +2 -2
  7. package/dist/server/config/opencode-base-url-resolver.d.ts +7 -0
  8. package/dist/server/config/opencode-base-url-resolver.js +48 -11
  9. package/dist/server/config/opencode-base-url-resolver.js.map +1 -1
  10. package/dist/server/config/opencode-system-probe-helper-client.d.ts +4 -0
  11. package/dist/server/config/opencode-system-probe-helper-client.js +29 -0
  12. package/dist/server/config/opencode-system-probe-helper-client.js.map +1 -1
  13. package/dist/server/config/opencode-system-probe-helper-process.d.ts +12 -0
  14. package/dist/server/config/opencode-system-probe-helper-process.js +34 -7
  15. package/dist/server/config/opencode-system-probe-helper-process.js.map +1 -1
  16. package/dist/server/modules/assistant-capability/assistant-capability-controller.d.ts +317 -0
  17. package/dist/server/modules/assistant-capability/assistant-capability-controller.js +549 -1
  18. package/dist/server/modules/assistant-capability/assistant-capability-controller.js.map +1 -1
  19. package/dist/server/modules/assistant-capability/assistant-capability-service.d.ts +330 -2
  20. package/dist/server/modules/assistant-capability/assistant-capability-service.js +958 -3
  21. package/dist/server/modules/assistant-capability/assistant-capability-service.js.map +1 -1
  22. package/dist/server/modules/butler/assistant-automation-service.d.ts +110 -0
  23. package/dist/server/modules/butler/assistant-automation-service.js +786 -0
  24. package/dist/server/modules/butler/assistant-automation-service.js.map +1 -0
  25. package/dist/server/modules/butler/assistant-automation-trigger.d.ts +94 -0
  26. package/dist/server/modules/butler/assistant-automation-trigger.js +400 -0
  27. package/dist/server/modules/butler/assistant-automation-trigger.js.map +1 -0
  28. package/dist/server/modules/butler/assistant-sandbox-service.d.ts +55 -0
  29. package/dist/server/modules/butler/assistant-sandbox-service.js +266 -0
  30. package/dist/server/modules/butler/assistant-sandbox-service.js.map +1 -0
  31. package/dist/server/modules/butler/butler-action-context-service.d.ts +4 -1
  32. package/dist/server/modules/butler/butler-action-context-service.js +8 -2
  33. package/dist/server/modules/butler/butler-action-context-service.js.map +1 -1
  34. package/dist/server/modules/butler/butler-control-session-service.d.ts +8 -1
  35. package/dist/server/modules/butler/butler-control-session-service.js +154 -40
  36. package/dist/server/modules/butler/butler-control-session-service.js.map +1 -1
  37. package/dist/server/modules/butler/butler-control-timer-scheduler.d.ts +32 -0
  38. package/dist/server/modules/butler/butler-control-timer-scheduler.js +93 -0
  39. package/dist/server/modules/butler/butler-control-timer-scheduler.js.map +1 -0
  40. package/dist/server/modules/butler/butler-control-timer-service.d.ts +42 -0
  41. package/dist/server/modules/butler/butler-control-timer-service.js +132 -0
  42. package/dist/server/modules/butler/butler-control-timer-service.js.map +1 -0
  43. package/dist/server/modules/butler/butler-controller.d.ts +42 -2
  44. package/dist/server/modules/butler/butler-controller.js +79 -12
  45. package/dist/server/modules/butler/butler-controller.js.map +1 -1
  46. package/dist/server/modules/butler/butler-follow-up-service.d.ts +9 -1
  47. package/dist/server/modules/butler/butler-follow-up-service.js +273 -181
  48. package/dist/server/modules/butler/butler-follow-up-service.js.map +1 -1
  49. package/dist/server/modules/butler/butler-inbox-analysis-service.d.ts +4 -1
  50. package/dist/server/modules/butler/butler-inbox-analysis-service.js +18 -4
  51. package/dist/server/modules/butler/butler-inbox-analysis-service.js.map +1 -1
  52. package/dist/server/modules/butler/butler-inbox-instruction-adapter.js +7 -6
  53. package/dist/server/modules/butler/butler-inbox-instruction-adapter.js.map +1 -1
  54. package/dist/server/modules/butler/butler-profile-service.js +2 -5
  55. package/dist/server/modules/butler/butler-profile-service.js.map +1 -1
  56. package/dist/server/modules/butler/butler-project-service.d.ts +3 -1
  57. package/dist/server/modules/butler/butler-project-service.js +7 -1
  58. package/dist/server/modules/butler/butler-project-service.js.map +1 -1
  59. package/dist/server/modules/butler/butler-session-service.d.ts +3 -1
  60. package/dist/server/modules/butler/butler-session-service.js +12 -1
  61. package/dist/server/modules/butler/butler-session-service.js.map +1 -1
  62. package/dist/server/modules/butler/butler-session-summary-service.js +2 -1
  63. package/dist/server/modules/butler/butler-session-summary-service.js.map +1 -1
  64. package/dist/server/modules/butler/butler-workspace-context.d.ts +3 -0
  65. package/dist/server/modules/butler/butler-workspace-context.js +182 -51
  66. package/dist/server/modules/butler/butler-workspace-context.js.map +1 -1
  67. package/dist/server/modules/butler/patrol-execution-service.js +2 -1
  68. package/dist/server/modules/butler/patrol-execution-service.js.map +1 -1
  69. package/dist/server/modules/butler/provider-adapter-registry.d.ts +3 -0
  70. package/dist/server/modules/butler/provider-adapter-registry.js +18 -1
  71. package/dist/server/modules/butler/provider-adapter-registry.js.map +1 -1
  72. package/dist/server/modules/butler/verification-run-service.d.ts +9 -2
  73. package/dist/server/modules/butler/verification-run-service.js +188 -34
  74. package/dist/server/modules/butler/verification-run-service.js.map +1 -1
  75. package/dist/server/modules/debug-target/debug-target-controller.d.ts +13 -0
  76. package/dist/server/modules/debug-target/debug-target-controller.js +77 -2
  77. package/dist/server/modules/debug-target/debug-target-controller.js.map +1 -1
  78. package/dist/server/modules/debug-target/debug-target-service.d.ts +17 -3
  79. package/dist/server/modules/debug-target/debug-target-service.js +696 -98
  80. package/dist/server/modules/debug-target/debug-target-service.js.map +1 -1
  81. package/dist/server/modules/git/git-command-helper-client.d.ts +3 -0
  82. package/dist/server/modules/git/git-command-helper-client.js +71 -29
  83. package/dist/server/modules/git/git-command-helper-client.js.map +1 -1
  84. package/dist/server/modules/git/git-command-helper-process.js +62 -9
  85. package/dist/server/modules/git/git-command-helper-process.js.map +1 -1
  86. package/dist/server/modules/git/git-command-runner.d.ts +1 -0
  87. package/dist/server/modules/git/git-command-runner.js +44 -1
  88. package/dist/server/modules/git/git-command-runner.js.map +1 -1
  89. package/dist/server/modules/git/git-controller.js +8 -7
  90. package/dist/server/modules/git/git-controller.js.map +1 -1
  91. package/dist/server/modules/git/git-read-service.d.ts +7 -7
  92. package/dist/server/modules/git/git-read-service.js +41 -24
  93. package/dist/server/modules/git/git-read-service.js.map +1 -1
  94. package/dist/server/modules/model-switch/cc-switch-adapter.js +6 -2
  95. package/dist/server/modules/model-switch/cc-switch-adapter.js.map +1 -1
  96. package/dist/server/modules/preferences/profile-service.d.ts +3 -1
  97. package/dist/server/modules/preferences/profile-service.js +74 -3
  98. package/dist/server/modules/preferences/profile-service.js.map +1 -1
  99. package/dist/server/modules/provider/codex-model-options.js +2 -3
  100. package/dist/server/modules/provider/codex-model-options.js.map +1 -1
  101. package/dist/server/modules/provider/opencode-model-options.js +2 -3
  102. package/dist/server/modules/provider/opencode-model-options.js.map +1 -1
  103. package/dist/server/modules/provider/provider-discovery-helper-client.d.ts +14 -7
  104. package/dist/server/modules/provider/provider-discovery-helper-client.js +208 -46
  105. package/dist/server/modules/provider/provider-discovery-helper-client.js.map +1 -1
  106. package/dist/server/modules/provider/provider-discovery-helper-process.js +96 -47
  107. package/dist/server/modules/provider/provider-discovery-helper-process.js.map +1 -1
  108. package/dist/server/modules/provider/provider-discovery-runtime.d.ts +4 -0
  109. package/dist/server/modules/provider/provider-discovery-runtime.js +145 -0
  110. package/dist/server/modules/provider/provider-discovery-runtime.js.map +1 -0
  111. package/dist/server/modules/sessions/claude-runtime-helper-client.js +23 -1
  112. package/dist/server/modules/sessions/claude-runtime-helper-client.js.map +1 -1
  113. package/dist/server/modules/sessions/session-history-service.d.ts +12 -3
  114. package/dist/server/modules/sessions/session-history-service.js +465 -67
  115. package/dist/server/modules/sessions/session-history-service.js.map +1 -1
  116. package/dist/server/modules/sessions/session-live-runtime-service.d.ts +8 -0
  117. package/dist/server/modules/sessions/session-live-runtime-service.js +164 -34
  118. package/dist/server/modules/sessions/session-live-runtime-service.js.map +1 -1
  119. package/dist/server/modules/sessions/session-message-origin-utils.d.ts +12 -0
  120. package/dist/server/modules/sessions/session-message-origin-utils.js +45 -0
  121. package/dist/server/modules/sessions/session-message-origin-utils.js.map +1 -0
  122. package/dist/server/modules/sessions/session-permission-request-service.js +167 -0
  123. package/dist/server/modules/sessions/session-permission-request-service.js.map +1 -1
  124. package/dist/server/modules/skills/builtin-skill-service.d.ts +12 -0
  125. package/dist/server/modules/skills/builtin-skill-service.js +49 -0
  126. package/dist/server/modules/skills/builtin-skill-service.js.map +1 -0
  127. package/dist/server/modules/skills/builtin-skills/codingns-assistant/SKILL.md +82 -0
  128. package/dist/server/modules/skills/builtin-skills/codingns-assistant/agents/openai.yaml +4 -0
  129. package/dist/server/modules/skills/builtin-skills/codingns-assistant/references/cli-workflow.md +136 -0
  130. package/dist/server/modules/skills/skill-manager-service.d.ts +7 -0
  131. package/dist/server/modules/skills/skill-manager-service.js +98 -0
  132. package/dist/server/modules/skills/skill-manager-service.js.map +1 -1
  133. package/dist/server/modules/tailscale/tailscale-helper-client.d.ts +1 -0
  134. package/dist/server/modules/tailscale/tailscale-helper-client.js +12 -0
  135. package/dist/server/modules/tailscale/tailscale-helper-client.js.map +1 -1
  136. package/dist/server/modules/tasks/task-helper-client.d.ts +10 -2
  137. package/dist/server/modules/tasks/task-helper-client.js +152 -27
  138. package/dist/server/modules/tasks/task-helper-client.js.map +1 -1
  139. package/dist/server/modules/tasks/task-helper-process-handlers.d.ts +10 -3
  140. package/dist/server/modules/tasks/task-helper-process-handlers.js +7 -5
  141. package/dist/server/modules/tasks/task-helper-process-handlers.js.map +1 -1
  142. package/dist/server/modules/tasks/task-helper-process.js +104 -3
  143. package/dist/server/modules/tasks/task-helper-process.js.map +1 -1
  144. package/dist/server/modules/tasks/task-lane-executors.js +2 -2
  145. package/dist/server/modules/tasks/task-lane-executors.js.map +1 -1
  146. package/dist/server/modules/tasks/task-types.d.ts +4 -0
  147. package/dist/server/modules/tasks/task-types.js +5 -1
  148. package/dist/server/modules/tasks/task-types.js.map +1 -1
  149. package/dist/server/modules/terminal/command-template-service.d.ts +11 -2
  150. package/dist/server/modules/terminal/command-template-service.js +91 -9
  151. package/dist/server/modules/terminal/command-template-service.js.map +1 -1
  152. package/dist/server/modules/terminal/runtime/terminal-log-writer-client.js +1 -1
  153. package/dist/server/modules/terminal/runtime/terminal-log-writer-client.js.map +1 -1
  154. package/dist/server/modules/terminal/runtime/terminal-log-writer-process.js +160 -11
  155. package/dist/server/modules/terminal/runtime/terminal-log-writer-process.js.map +1 -1
  156. package/dist/server/modules/terminal/template-port-runtime.d.ts +1 -1
  157. package/dist/server/modules/terminal/template-port-runtime.js +87 -37
  158. package/dist/server/modules/terminal/template-port-runtime.js.map +1 -1
  159. package/dist/server/modules/terminal/terminal-controller.d.ts +3 -0
  160. package/dist/server/modules/terminal/terminal-controller.js +41 -0
  161. package/dist/server/modules/terminal/terminal-controller.js.map +1 -1
  162. package/dist/server/modules/terminal/terminal-service.d.ts +4 -0
  163. package/dist/server/modules/terminal/terminal-service.js +35 -1
  164. package/dist/server/modules/terminal/terminal-service.js.map +1 -1
  165. package/dist/server/modules/workbench/workbench-service.d.ts +3 -0
  166. package/dist/server/modules/workbench/workbench-service.js +7 -6
  167. package/dist/server/modules/workbench/workbench-service.js.map +1 -1
  168. package/dist/server/modules/workbench/workspace-file-watcher.d.ts +14 -6
  169. package/dist/server/modules/workbench/workspace-file-watcher.js +267 -57
  170. package/dist/server/modules/workbench/workspace-file-watcher.js.map +1 -1
  171. package/dist/server/modules/workbench/workspace-panel-snapshot-service.d.ts +3 -0
  172. package/dist/server/modules/workbench/workspace-panel-snapshot-service.js +149 -41
  173. package/dist/server/modules/workbench/workspace-panel-snapshot-service.js.map +1 -1
  174. package/dist/server/modules/workspace/workspace-code-composition.d.ts +1 -0
  175. package/dist/server/modules/workspace/workspace-code-composition.js +183 -1
  176. package/dist/server/modules/workspace/workspace-code-composition.js.map +1 -1
  177. package/dist/server/modules/workspace/workspace-service.js +54 -17
  178. package/dist/server/modules/workspace/workspace-service.js.map +1 -1
  179. package/dist/server/modules/worktree/worktree-cleanup-service.d.ts +1 -1
  180. package/dist/server/modules/worktree/worktree-cleanup-service.js +22 -17
  181. package/dist/server/modules/worktree/worktree-cleanup-service.js.map +1 -1
  182. package/dist/server/modules/worktree/worktree-controller.js +6 -5
  183. package/dist/server/modules/worktree/worktree-controller.js.map +1 -1
  184. package/dist/server/modules/worktree/worktree-manager.d.ts +10 -2
  185. package/dist/server/modules/worktree/worktree-manager.js +35 -20
  186. package/dist/server/modules/worktree/worktree-manager.js.map +1 -1
  187. package/dist/server/modules/worktree/worktree-merge-service.d.ts +2 -2
  188. package/dist/server/modules/worktree/worktree-merge-service.js +34 -27
  189. package/dist/server/modules/worktree/worktree-merge-service.js.map +1 -1
  190. package/dist/server/modules/worktree/worktree-sync-service.d.ts +1 -1
  191. package/dist/server/modules/worktree/worktree-sync-service.js +5 -3
  192. package/dist/server/modules/worktree/worktree-sync-service.js.map +1 -1
  193. package/dist/server/routes/assistant.js +43 -0
  194. package/dist/server/routes/assistant.js.map +1 -1
  195. package/dist/server/routes/butler.js +5 -0
  196. package/dist/server/routes/butler.js.map +1 -1
  197. package/dist/server/server/create-server.d.ts +8 -0
  198. package/dist/server/server/create-server.js +51 -13
  199. package/dist/server/server/create-server.js.map +1 -1
  200. package/dist/server/shared/http/request-abort.d.ts +2 -0
  201. package/dist/server/shared/http/request-abort.js +38 -0
  202. package/dist/server/shared/http/request-abort.js.map +1 -0
  203. package/dist/server/storage/repositories/assistant-automation-run-repository.d.ts +12 -0
  204. package/dist/server/storage/repositories/assistant-automation-run-repository.js +139 -0
  205. package/dist/server/storage/repositories/assistant-automation-run-repository.js.map +1 -0
  206. package/dist/server/storage/repositories/assistant-automation-task-repository.d.ts +15 -0
  207. package/dist/server/storage/repositories/assistant-automation-task-repository.js +173 -0
  208. package/dist/server/storage/repositories/assistant-automation-task-repository.js.map +1 -0
  209. package/dist/server/storage/repositories/assistant-sandbox-workspace-repository.d.ts +17 -0
  210. package/dist/server/storage/repositories/assistant-sandbox-workspace-repository.js +164 -0
  211. package/dist/server/storage/repositories/assistant-sandbox-workspace-repository.js.map +1 -0
  212. package/dist/server/storage/repositories/butler-control-session-repository.js +27 -3
  213. package/dist/server/storage/repositories/butler-control-session-repository.js.map +1 -1
  214. package/dist/server/storage/repositories/butler-control-timer-repository.d.ts +15 -0
  215. package/dist/server/storage/repositories/butler-control-timer-repository.js +157 -0
  216. package/dist/server/storage/repositories/butler-control-timer-repository.js.map +1 -0
  217. package/dist/server/storage/repositories/user-preference-profile-repository.js +6 -3
  218. package/dist/server/storage/repositories/user-preference-profile-repository.js.map +1 -1
  219. package/dist/server/storage/sqlite/client.js +239 -2
  220. package/dist/server/storage/sqlite/client.js.map +1 -1
  221. package/dist/server/storage/sqlite/schema.sql +107 -1
  222. package/dist/server/types/domain.d.ts +89 -2
  223. package/dist/server/ws/workbench-ws-hub.d.ts +14 -7
  224. package/dist/server/ws/workbench-ws-hub.js +316 -158
  225. package/dist/server/ws/workbench-ws-hub.js.map +1 -1
  226. package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.d.ts +4 -1
  227. package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.js +111 -3
  228. package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.js.map +1 -1
  229. package/node_modules/@codingns/session-sync-core/dist/providers/codex.d.ts +6 -1
  230. package/node_modules/@codingns/session-sync-core/dist/providers/codex.js +306 -31
  231. package/node_modules/@codingns/session-sync-core/dist/providers/codex.js.map +1 -1
  232. package/node_modules/@codingns/session-sync-core/dist/providers/gemini.d.ts +5 -1
  233. package/node_modules/@codingns/session-sync-core/dist/providers/gemini.js +187 -26
  234. package/node_modules/@codingns/session-sync-core/dist/providers/gemini.js.map +1 -1
  235. package/node_modules/@codingns/session-sync-core/dist/providers/kimi.d.ts +4 -1
  236. package/node_modules/@codingns/session-sync-core/dist/providers/kimi.js +98 -1
  237. package/node_modules/@codingns/session-sync-core/dist/providers/kimi.js.map +1 -1
  238. package/node_modules/@codingns/session-sync-core/dist/providers/opencode.d.ts +2 -0
  239. package/node_modules/@codingns/session-sync-core/dist/providers/opencode.js +71 -8
  240. package/node_modules/@codingns/session-sync-core/dist/providers/opencode.js.map +1 -1
  241. package/node_modules/@codingns/session-sync-core/dist/providers/utils.d.ts +1 -0
  242. package/node_modules/@codingns/session-sync-core/dist/providers/utils.js +4 -1
  243. package/node_modules/@codingns/session-sync-core/dist/providers/utils.js.map +1 -1
  244. package/node_modules/@codingns/session-sync-core/dist/runtime/claude-runtime.js +44 -0
  245. package/node_modules/@codingns/session-sync-core/dist/runtime/claude-runtime.js.map +1 -1
  246. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js +9 -3
  247. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js.map +1 -1
  248. package/node_modules/@codingns/session-sync-core/dist/runtime/types.d.ts +1 -0
  249. package/node_modules/@codingns/session-sync-core/dist/services.js +17 -8
  250. package/node_modules/@codingns/session-sync-core/dist/services.js.map +1 -1
  251. package/node_modules/@codingns/session-sync-core/dist/types.d.ts +4 -0
  252. package/package.json +1 -1
  253. package/scripts/postinstall.mjs +33 -0
  254. package/dist/public/assets/index-Cek6u0b9.css +0 -1
  255. package/dist/public/assets/index-THHY79si.js +0 -122
@@ -1,5 +1,7 @@
1
1
  import { createId } from "../../shared/utils/id.js";
2
+ import { AppError } from "../../shared/errors/app-error.js";
2
3
  import { nowIso } from "../../shared/utils/time.js";
4
+ import { recordButlerProxyMessageOrigin } from "../sessions/session-message-origin-utils.js";
3
5
  const ASSISTANT_CAPABILITIES = [
4
6
  {
5
7
  name: "capabilities.list",
@@ -25,6 +27,18 @@ const ASSISTANT_CAPABILITIES = [
25
27
  enabled: true,
26
28
  summary: "列出指定项目下可操作的会话"
27
29
  },
30
+ {
31
+ name: "projects.sessions.start",
32
+ mode: "proxy_execute",
33
+ enabled: true,
34
+ summary: "按当前助手配置为项目新建真实会话"
35
+ },
36
+ {
37
+ name: "sessions.start",
38
+ mode: "proxy_execute",
39
+ enabled: true,
40
+ summary: "按 project/workspace/sandbox 目标新建真实会话;未指定目标时自动创建沙箱"
41
+ },
28
42
  {
29
43
  name: "sessions.get",
30
44
  mode: "read",
@@ -55,6 +69,90 @@ const ASSISTANT_CAPABILITIES = [
55
69
  enabled: true,
56
70
  summary: "从指定会话或消息点 fork 新会话"
57
71
  },
72
+ {
73
+ name: "automations.list",
74
+ mode: "read",
75
+ enabled: true,
76
+ summary: "列出当前助手自动化任务"
77
+ },
78
+ {
79
+ name: "automations.get",
80
+ mode: "read",
81
+ enabled: true,
82
+ summary: "读取单个助手自动化任务详情"
83
+ },
84
+ {
85
+ name: "automations.create",
86
+ mode: "proxy_execute",
87
+ enabled: true,
88
+ summary: "创建正式助手自动化任务"
89
+ },
90
+ {
91
+ name: "automations.cancel",
92
+ mode: "proxy_execute",
93
+ enabled: true,
94
+ summary: "取消助手自动化任务"
95
+ },
96
+ {
97
+ name: "automations.runs.list",
98
+ mode: "read",
99
+ enabled: true,
100
+ summary: "读取助手自动化执行记录"
101
+ },
102
+ {
103
+ name: "sandboxes.list",
104
+ mode: "read",
105
+ enabled: true,
106
+ summary: "列出当前助手沙箱"
107
+ },
108
+ {
109
+ name: "sandboxes.create",
110
+ mode: "proxy_execute",
111
+ enabled: true,
112
+ summary: "创建新的助手沙箱"
113
+ },
114
+ {
115
+ name: "sandboxes.promote",
116
+ mode: "proxy_execute",
117
+ enabled: true,
118
+ summary: "保留或晋升助手沙箱"
119
+ },
120
+ {
121
+ name: "sandboxes.expire",
122
+ mode: "proxy_execute",
123
+ enabled: true,
124
+ summary: "标记助手沙箱过期"
125
+ },
126
+ {
127
+ name: "sandboxes.remove",
128
+ mode: "proxy_execute",
129
+ enabled: true,
130
+ summary: "清理助手沙箱"
131
+ },
132
+ {
133
+ name: "timers.list",
134
+ mode: "read",
135
+ enabled: true,
136
+ summary: "列出当前助手会话相关的计时器"
137
+ },
138
+ {
139
+ name: "timers.get",
140
+ mode: "read",
141
+ enabled: true,
142
+ summary: "读取单个助手计时器详情"
143
+ },
144
+ {
145
+ name: "timers.create",
146
+ mode: "proxy_execute",
147
+ enabled: true,
148
+ summary: "创建助手控制会话的定时继续任务"
149
+ },
150
+ {
151
+ name: "timers.cancel",
152
+ mode: "proxy_execute",
153
+ enabled: true,
154
+ summary: "取消助手控制会话计时器"
155
+ },
58
156
  {
59
157
  name: "terminals.list",
60
158
  mode: "read",
@@ -72,27 +170,193 @@ const ASSISTANT_CAPABILITIES = [
72
170
  mode: "proxy_execute",
73
171
  enabled: true,
74
172
  summary: "向受控终端发送输入"
173
+ },
174
+ {
175
+ name: "terminals.close",
176
+ mode: "proxy_execute",
177
+ enabled: true,
178
+ summary: "关闭指定受控终端"
179
+ },
180
+ {
181
+ name: "debug-targets.compatibility-matrix.get",
182
+ mode: "read",
183
+ enabled: true,
184
+ summary: "读取调试框架兼容矩阵"
185
+ },
186
+ {
187
+ name: "debug-targets.analyze",
188
+ mode: "proxy_execute",
189
+ enabled: true,
190
+ summary: "分析工作区调试目标和服务"
191
+ },
192
+ {
193
+ name: "debug-targets.framework-analysis.get",
194
+ mode: "read",
195
+ enabled: true,
196
+ summary: "读取调试目标框架分析结果"
197
+ },
198
+ {
199
+ name: "debug-targets.framework-analysis.refresh",
200
+ mode: "proxy_execute",
201
+ enabled: true,
202
+ summary: "刷新调试目标框架分析结果"
203
+ },
204
+ {
205
+ name: "debug-targets.launch-plan.create",
206
+ mode: "proxy_execute",
207
+ enabled: true,
208
+ summary: "生成调试目标启动计划,支持显式端口请求"
209
+ },
210
+ {
211
+ name: "debug-targets.run",
212
+ mode: "proxy_execute",
213
+ enabled: true,
214
+ summary: "启动调试目标,支持显式端口请求"
215
+ },
216
+ {
217
+ name: "debug-targets.runtime-latest.get",
218
+ mode: "read",
219
+ enabled: true,
220
+ summary: "读取调试目标最近一次运行态"
221
+ },
222
+ {
223
+ name: "debug-targets.runtimes.list",
224
+ mode: "read",
225
+ enabled: true,
226
+ summary: "读取调试目标运行历史"
227
+ },
228
+ {
229
+ name: "debug-runtimes.get",
230
+ mode: "read",
231
+ enabled: true,
232
+ summary: "读取指定调试运行时详情"
233
+ },
234
+ {
235
+ name: "workspaces.list",
236
+ mode: "read",
237
+ enabled: true,
238
+ summary: "列出当前可见工作区"
239
+ },
240
+ {
241
+ name: "workspaces.browse",
242
+ mode: "read",
243
+ enabled: true,
244
+ summary: "浏览可导入的本地目录"
245
+ },
246
+ {
247
+ name: "workspaces.directory.create",
248
+ mode: "proxy_execute",
249
+ enabled: true,
250
+ summary: "创建新的工作区目录"
251
+ },
252
+ {
253
+ name: "workspaces.import",
254
+ mode: "proxy_execute",
255
+ enabled: true,
256
+ summary: "把已有目录导入成工作区"
257
+ },
258
+ {
259
+ name: "workspaces.clone",
260
+ mode: "proxy_execute",
261
+ enabled: true,
262
+ summary: "克隆仓库并导入成工作区"
263
+ },
264
+ {
265
+ name: "workspaces.reorder",
266
+ mode: "proxy_execute",
267
+ enabled: true,
268
+ summary: "调整工作区显示顺序"
269
+ },
270
+ {
271
+ name: "workspaces.management.get",
272
+ mode: "read",
273
+ enabled: true,
274
+ summary: "读取工作区管理摘要"
275
+ },
276
+ {
277
+ name: "workspaces.navigation-state.update",
278
+ mode: "proxy_execute",
279
+ enabled: true,
280
+ summary: "更新工作区导航状态"
281
+ },
282
+ {
283
+ name: "workspaces.remove",
284
+ mode: "proxy_execute",
285
+ enabled: true,
286
+ summary: "移除工作区入口"
287
+ },
288
+ {
289
+ name: "worktrees.tree",
290
+ mode: "read",
291
+ enabled: true,
292
+ summary: "读取工作树结构"
293
+ },
294
+ {
295
+ name: "worktrees.create",
296
+ mode: "proxy_execute",
297
+ enabled: true,
298
+ summary: "创建子工作树"
299
+ },
300
+ {
301
+ name: "worktrees.merge-preview",
302
+ mode: "read",
303
+ enabled: true,
304
+ summary: "读取子工作树合并预览"
305
+ },
306
+ {
307
+ name: "worktrees.merge-into-parent",
308
+ mode: "proxy_execute",
309
+ enabled: true,
310
+ summary: "把子工作树合并回父工作区"
311
+ },
312
+ {
313
+ name: "worktrees.cleanup",
314
+ mode: "proxy_execute",
315
+ enabled: true,
316
+ summary: "清理子工作树"
75
317
  }
76
318
  ];
77
319
  export class AssistantCapabilityService {
78
320
  butlerProjectService;
79
321
  butlerSessionService;
322
+ butlerControlSessionService;
323
+ assistantAutomationService;
324
+ assistantSandboxService;
325
+ butlerControlTimerService;
80
326
  sessionHistoryService;
81
327
  sessionLiveRuntimeService;
82
328
  terminalService;
83
- constructor(butlerProjectService, butlerSessionService, sessionHistoryService, sessionLiveRuntimeService, terminalService) {
329
+ debugTargetService;
330
+ workspaceService;
331
+ worktreeManager;
332
+ worktreeSyncService;
333
+ worktreeMergeService;
334
+ worktreeCleanupService;
335
+ sessionMessageOriginRepository;
336
+ constructor(butlerProjectService, butlerSessionService, butlerControlSessionService, assistantAutomationService, assistantSandboxService, butlerControlTimerService, sessionHistoryService, sessionLiveRuntimeService, terminalService, debugTargetService, workspaceService, worktreeManager, worktreeSyncService, worktreeMergeService, worktreeCleanupService, sessionMessageOriginRepository = null) {
84
337
  this.butlerProjectService = butlerProjectService;
85
338
  this.butlerSessionService = butlerSessionService;
339
+ this.butlerControlSessionService = butlerControlSessionService;
340
+ this.assistantAutomationService = assistantAutomationService;
341
+ this.assistantSandboxService = assistantSandboxService;
342
+ this.butlerControlTimerService = butlerControlTimerService;
86
343
  this.sessionHistoryService = sessionHistoryService;
87
344
  this.sessionLiveRuntimeService = sessionLiveRuntimeService;
88
345
  this.terminalService = terminalService;
346
+ this.debugTargetService = debugTargetService;
347
+ this.workspaceService = workspaceService;
348
+ this.worktreeManager = worktreeManager;
349
+ this.worktreeSyncService = worktreeSyncService;
350
+ this.worktreeMergeService = worktreeMergeService;
351
+ this.worktreeCleanupService = worktreeCleanupService;
352
+ this.sessionMessageOriginRepository = sessionMessageOriginRepository;
89
353
  }
90
354
  listCapabilities() {
91
355
  return this.createReceipt("capabilities.list", {
92
356
  kind: "none",
93
357
  id: null
94
358
  }, {
95
- version: "2026-04-14",
359
+ version: "2026-04-16",
96
360
  items: ASSISTANT_CAPABILITIES
97
361
  });
98
362
  }
@@ -133,6 +397,72 @@ export class AssistantCapabilityService {
133
397
  items
134
398
  });
135
399
  }
400
+ async startProjectSession(input) {
401
+ const config = this.resolveSessionLaunchConfig(input);
402
+ const session = await this.butlerSessionService.startSession(input.projectId, {
403
+ role: "adhoc",
404
+ ownershipMode: "managed",
405
+ content: input.content.trim(),
406
+ providerId: config.providerId,
407
+ model: config.model,
408
+ reasoningLevel: config.reasoningLevel,
409
+ permissionMode: config.permissionMode
410
+ }, input.userId);
411
+ return this.createReceipt("projects.sessions.start", {
412
+ kind: "project",
413
+ id: input.projectId
414
+ }, {
415
+ session
416
+ });
417
+ }
418
+ async startSession(input) {
419
+ const config = this.resolveSessionLaunchConfig(input);
420
+ const currentControlSession = this.butlerControlSessionService.getCurrentSession(input.userId);
421
+ const target = input.target
422
+ ? this.resolveAssistantSessionTarget(input.target, input.userId)
423
+ : await this.createAutomaticSandboxTarget(input, currentControlSession);
424
+ if (target.kind === "project") {
425
+ const session = await this.butlerSessionService.startSession(target.id, {
426
+ role: "adhoc",
427
+ ownershipMode: "managed",
428
+ content: input.content.trim(),
429
+ providerId: config.providerId,
430
+ model: config.model,
431
+ reasoningLevel: config.reasoningLevel,
432
+ permissionMode: config.permissionMode
433
+ }, input.userId);
434
+ return this.createReceipt("sessions.start", {
435
+ kind: "project",
436
+ id: target.id
437
+ }, {
438
+ session,
439
+ target
440
+ });
441
+ }
442
+ const session = await this.sessionLiveRuntimeService.startLiveSession({
443
+ workspaceId: target.workspaceId,
444
+ userId: input.userId,
445
+ provider: config.providerId,
446
+ content: input.content.trim(),
447
+ clientRequestId: null,
448
+ runtimeOptions: {
449
+ model: config.model,
450
+ reasoningLevel: config.reasoningLevel,
451
+ permissionMode: config.permissionMode,
452
+ attachments: []
453
+ }
454
+ });
455
+ if (target.kind === "sandbox") {
456
+ this.assistantSandboxService.markSandboxUsedByControlSession(target.id, input.userId, currentControlSession?.id ?? null);
457
+ }
458
+ return this.createReceipt("sessions.start", {
459
+ kind: target.kind,
460
+ id: target.id
461
+ }, {
462
+ session,
463
+ target
464
+ });
465
+ }
136
466
  getSession(sessionId, userId) {
137
467
  const session = this.sessionHistoryService.getSession(sessionId, userId);
138
468
  return this.createReceipt("sessions.get", {
@@ -161,11 +491,19 @@ export class AssistantCapabilityService {
161
491
  });
162
492
  }
163
493
  async sendSessionMessage(input) {
494
+ const requestedAt = nowIso();
495
+ const clientRequestId = recordButlerProxyMessageOrigin(this.sessionMessageOriginRepository, {
496
+ sessionId: input.sessionId,
497
+ clientRequestId: input.clientRequestId?.trim() || null,
498
+ content: input.content,
499
+ createdAt: requestedAt,
500
+ fallbackKey: `assistant-send:${input.sessionId}:${requestedAt}`
501
+ });
164
502
  const result = await this.sessionLiveRuntimeService.sendLiveMessage({
165
503
  sessionId: input.sessionId,
166
504
  userId: input.userId,
167
505
  content: input.content,
168
- clientRequestId: input.clientRequestId?.trim() || null,
506
+ clientRequestId,
169
507
  runtimeOptions: {
170
508
  model: input.model?.trim() || null,
171
509
  reasoningLevel: input.reasoningLevel?.trim() || null,
@@ -173,6 +511,14 @@ export class AssistantCapabilityService {
173
511
  attachments: []
174
512
  }
175
513
  });
514
+ recordButlerProxyMessageOrigin(this.sessionMessageOriginRepository, {
515
+ sessionId: input.sessionId,
516
+ clientRequestId,
517
+ messageId: result.message?.messageId ?? null,
518
+ content: input.content,
519
+ createdAt: result.acceptedAt,
520
+ fallbackKey: `assistant-send:${input.sessionId}:${result.acceptedAt}`
521
+ });
176
522
  return this.createReceipt("sessions.message.send", {
177
523
  kind: "session",
178
524
  id: input.sessionId
@@ -196,6 +542,229 @@ export class AssistantCapabilityService {
196
542
  session
197
543
  });
198
544
  }
545
+ listTimers(input) {
546
+ const items = this.butlerControlTimerService.listTimers({
547
+ userId: input.userId,
548
+ statuses: input.status ? [input.status] : undefined,
549
+ controlSessionId: input.controlSessionId ?? null,
550
+ limit: input.limit ?? undefined
551
+ });
552
+ return this.createReceipt("timers.list", {
553
+ kind: "none",
554
+ id: null
555
+ }, {
556
+ items
557
+ });
558
+ }
559
+ listAutomations(input) {
560
+ const items = this.assistantAutomationService.listTasks({
561
+ userId: input.userId,
562
+ statuses: input.status ? [input.status] : undefined,
563
+ controlSessionId: input.controlSessionId ?? null
564
+ });
565
+ return this.createReceipt("automations.list", {
566
+ kind: "none",
567
+ id: null
568
+ }, {
569
+ items
570
+ });
571
+ }
572
+ getAutomation(automationId, userId) {
573
+ const automation = this.assistantAutomationService.getTask(automationId, userId);
574
+ return this.createReceipt("automations.get", {
575
+ kind: "automation",
576
+ id: automationId
577
+ }, {
578
+ automation
579
+ });
580
+ }
581
+ createAutomation(input) {
582
+ const triggerType = input.triggerType ?? "once";
583
+ const automation = this.assistantAutomationService.createTask({
584
+ userId: input.userId,
585
+ controlSessionId: input.controlSessionId,
586
+ projectId: input.projectId,
587
+ title: input.title,
588
+ trigger: buildAssistantAutomationTriggerInput(triggerType, input),
589
+ action: {
590
+ type: "send_control_message",
591
+ content: input.content,
592
+ includeTriggerContext: input.includeTriggerContext ?? triggerType === "condition",
593
+ targetSessionId: input.targetSessionId ?? null
594
+ }
595
+ });
596
+ return this.createReceipt("automations.create", {
597
+ kind: "automation",
598
+ id: automation.id
599
+ }, {
600
+ automation
601
+ });
602
+ }
603
+ updateAutomation(input) {
604
+ const automation = this.assistantAutomationService.updateTask({
605
+ taskId: input.automationId,
606
+ userId: input.userId,
607
+ title: input.title,
608
+ content: input.content,
609
+ includeTriggerContext: input.includeTriggerContext,
610
+ dueAt: input.dueAt,
611
+ everySeconds: input.everySeconds,
612
+ everyMinutes: input.everyMinutes,
613
+ everyHours: input.everyHours,
614
+ stopAt: input.stopAt,
615
+ cronMinute: input.cronMinute,
616
+ cronHour: input.cronHour,
617
+ cronDaysOfWeek: input.cronDaysOfWeek,
618
+ pollIntervalSeconds: input.pollIntervalSeconds,
619
+ expiresAt: input.expiresAt,
620
+ maxChecks: input.maxChecks
621
+ });
622
+ return this.createReceipt("automations.update", {
623
+ kind: "automation",
624
+ id: input.automationId
625
+ }, {
626
+ automation
627
+ });
628
+ }
629
+ cancelAutomation(automationId, userId) {
630
+ const automation = this.assistantAutomationService.cancelTask(automationId, userId);
631
+ return this.createReceipt("automations.cancel", {
632
+ kind: "automation",
633
+ id: automationId
634
+ }, {
635
+ automation
636
+ });
637
+ }
638
+ skipAutomationWait(automationId, userId) {
639
+ const automation = this.assistantAutomationService.skipCurrentWait(automationId, userId);
640
+ return this.createReceipt("automations.wait.skip", {
641
+ kind: "automation",
642
+ id: automationId
643
+ }, {
644
+ automation
645
+ });
646
+ }
647
+ listAutomationRuns(automationId, userId) {
648
+ const items = this.assistantAutomationService.listRuns(automationId, userId);
649
+ return this.createReceipt("automations.runs.list", {
650
+ kind: "automation",
651
+ id: automationId
652
+ }, {
653
+ items
654
+ });
655
+ }
656
+ listRecentAutomationRuns(input) {
657
+ const items = this.assistantAutomationService.listRecentRuns({
658
+ userId: input.userId,
659
+ controlSessionId: input.controlSessionId ?? null,
660
+ limit: input.limit ?? undefined
661
+ });
662
+ return this.createReceipt("automations.runs.recent", {
663
+ kind: "none",
664
+ id: null
665
+ }, {
666
+ items
667
+ });
668
+ }
669
+ listSandboxes(input) {
670
+ const items = this.assistantSandboxService.listSandboxes({
671
+ userId: input.userId,
672
+ controlSessionId: input.controlSessionId ?? null,
673
+ statuses: input.status ? [input.status] : undefined
674
+ });
675
+ return this.createReceipt("sandboxes.list", {
676
+ kind: "none",
677
+ id: null
678
+ }, {
679
+ items
680
+ });
681
+ }
682
+ async createSandbox(input) {
683
+ const currentControlSession = this.butlerControlSessionService.getCurrentSession(input.userId);
684
+ const sandbox = await this.assistantSandboxService.createSandbox({
685
+ userId: input.userId,
686
+ controlSessionId: currentControlSession?.id ?? null,
687
+ title: input.title,
688
+ description: input.description,
689
+ purpose: input.purpose,
690
+ expiresAt: input.expiresAt,
691
+ source: input.sourceKind === "clone"
692
+ ? {
693
+ kind: "clone",
694
+ repositoryUrl: requireAssistantRepositoryUrl(input.repositoryUrl),
695
+ directoryName: input.directoryName,
696
+ auth: input.auth
697
+ }
698
+ : {
699
+ kind: "blank",
700
+ directoryName: input.directoryName
701
+ }
702
+ });
703
+ return this.createReceipt("sandboxes.create", {
704
+ kind: "sandbox",
705
+ id: sandbox.id
706
+ }, {
707
+ sandbox
708
+ });
709
+ }
710
+ promoteSandbox(input) {
711
+ const sandbox = this.assistantSandboxService.promoteSandbox(input.sandboxId, input.userId, {
712
+ mode: input.mode,
713
+ projectName: input.projectName,
714
+ defaultProvider: input.defaultProvider
715
+ });
716
+ return this.createReceipt("sandboxes.promote", {
717
+ kind: "sandbox",
718
+ id: input.sandboxId
719
+ }, {
720
+ sandbox
721
+ });
722
+ }
723
+ expireSandbox(sandboxId, userId) {
724
+ const sandbox = this.assistantSandboxService.expireSandbox(sandboxId, userId);
725
+ return this.createReceipt("sandboxes.expire", {
726
+ kind: "sandbox",
727
+ id: sandboxId
728
+ }, {
729
+ sandbox
730
+ });
731
+ }
732
+ removeSandbox(sandboxId, userId) {
733
+ const sandbox = this.assistantSandboxService.removeSandbox(sandboxId, userId);
734
+ return this.createReceipt("sandboxes.remove", {
735
+ kind: "sandbox",
736
+ id: sandboxId
737
+ }, {
738
+ sandbox
739
+ });
740
+ }
741
+ getTimer(timerId, userId) {
742
+ const timer = this.butlerControlTimerService.getTimer(timerId, userId);
743
+ return this.createReceipt("timers.get", {
744
+ kind: "timer",
745
+ id: timerId
746
+ }, {
747
+ timer
748
+ });
749
+ }
750
+ createTimer(input) {
751
+ const timer = this.butlerControlTimerService.createTimer(input);
752
+ return this.createReceipt("timers.create", {
753
+ kind: "timer",
754
+ id: timer.id
755
+ }, {
756
+ timer
757
+ });
758
+ }
759
+ cancelTimer(timerId, userId) {
760
+ const timer = this.butlerControlTimerService.cancelTimer(timerId, userId);
761
+ return this.createReceipt("timers.cancel", {
762
+ kind: "timer",
763
+ id: timerId
764
+ }, {
765
+ timer
766
+ });
767
+ }
199
768
  async listTerminals(input) {
200
769
  const workspaceId = input.projectId?.trim()
201
770
  ? this.butlerProjectService.getById(input.projectId).workspaceId
@@ -227,6 +796,243 @@ export class AssistantCapabilityService {
227
796
  result
228
797
  });
229
798
  }
799
+ async closeTerminal(terminalId) {
800
+ const result = await this.terminalService.closeTerminal(terminalId);
801
+ return this.createReceipt("terminals.close", {
802
+ kind: "terminal",
803
+ id: terminalId
804
+ }, {
805
+ result
806
+ });
807
+ }
808
+ getDebugCompatibilityMatrix() {
809
+ return this.createReceipt("debug-targets.compatibility-matrix.get", {
810
+ kind: "none",
811
+ id: null
812
+ }, {
813
+ matrix: this.debugTargetService.getCompatibilityMatrix()
814
+ });
815
+ }
816
+ analyzeDebugTarget(input) {
817
+ const result = this.debugTargetService.analyze({
818
+ workspaceId: input.workspaceId,
819
+ rootPath: input.rootPath,
820
+ commandHints: input.commandHints ?? []
821
+ });
822
+ return this.createReceipt("debug-targets.analyze", {
823
+ kind: "debug_target",
824
+ id: result.target.id
825
+ }, {
826
+ result
827
+ });
828
+ }
829
+ getDebugFrameworkAnalysis(targetId) {
830
+ return this.createReceipt("debug-targets.framework-analysis.get", {
831
+ kind: "debug_target",
832
+ id: targetId
833
+ }, {
834
+ result: this.debugTargetService.getFrameworkAnalysis(targetId)
835
+ });
836
+ }
837
+ refreshDebugFrameworkAnalysis(targetId) {
838
+ return this.createReceipt("debug-targets.framework-analysis.refresh", {
839
+ kind: "debug_target",
840
+ id: targetId
841
+ }, {
842
+ result: this.debugTargetService.refreshFrameworkAnalysis(targetId)
843
+ });
844
+ }
845
+ async createDebugLaunchPlan(input) {
846
+ const plan = await this.debugTargetService.createLaunchPlan(input.targetId, input.portRequests, input.userId);
847
+ return this.createReceipt("debug-targets.launch-plan.create", {
848
+ kind: "debug_target",
849
+ id: input.targetId
850
+ }, {
851
+ plan
852
+ });
853
+ }
854
+ async runDebugTarget(input) {
855
+ const result = await this.debugTargetService.run({
856
+ targetId: input.targetId,
857
+ userId: input.userId,
858
+ shell: input.shell ?? undefined,
859
+ runtimeType: input.runtimeType ?? undefined,
860
+ portRequests: input.portRequests
861
+ });
862
+ return this.createReceipt("debug-targets.run", {
863
+ kind: "debug_target",
864
+ id: input.targetId
865
+ }, {
866
+ result
867
+ });
868
+ }
869
+ async getLatestDebugRuntime(targetId) {
870
+ const runtime = await this.debugTargetService.getLatestRuntimeDetail(targetId);
871
+ return this.createReceipt("debug-targets.runtime-latest.get", {
872
+ kind: "debug_target",
873
+ id: targetId
874
+ }, {
875
+ runtime
876
+ });
877
+ }
878
+ async listDebugRuntimes(input) {
879
+ const history = await this.debugTargetService.getRecentRuntimeDetails(input.targetId, input.limit);
880
+ return this.createReceipt("debug-targets.runtimes.list", {
881
+ kind: "debug_target",
882
+ id: input.targetId
883
+ }, {
884
+ history
885
+ });
886
+ }
887
+ async getDebugRuntime(runtimeId) {
888
+ const runtime = await this.debugTargetService.getRuntimeDetail(runtimeId);
889
+ return this.createReceipt("debug-runtimes.get", {
890
+ kind: "debug_runtime",
891
+ id: runtimeId
892
+ }, {
893
+ runtime
894
+ });
895
+ }
896
+ listWorkspaces() {
897
+ return this.createReceipt("workspaces.list", {
898
+ kind: "none",
899
+ id: null
900
+ }, {
901
+ items: this.workspaceService.list()
902
+ });
903
+ }
904
+ browseWorkspaces(requestedPath) {
905
+ return this.createReceipt("workspaces.browse", {
906
+ kind: "none",
907
+ id: null
908
+ }, {
909
+ result: this.workspaceService.browseDirectories(requestedPath?.trim() || undefined)
910
+ });
911
+ }
912
+ createWorkspaceDirectory(input) {
913
+ const result = this.workspaceService.createDirectory(input.parentPath, input.directoryName);
914
+ return this.createReceipt("workspaces.directory.create", {
915
+ kind: "none",
916
+ id: null
917
+ }, {
918
+ result
919
+ });
920
+ }
921
+ importWorkspace(input) {
922
+ const workspace = this.workspaceService.importWorkspace(input.path, input.name ?? undefined);
923
+ return this.createReceipt("workspaces.import", {
924
+ kind: "workspace",
925
+ id: workspace.id
926
+ }, {
927
+ workspace
928
+ });
929
+ }
930
+ async cloneWorkspace(input) {
931
+ const workspace = await this.workspaceService.cloneWorkspace({
932
+ repositoryUrl: input.repositoryUrl,
933
+ parentPath: input.parentPath,
934
+ directoryName: input.directoryName ?? undefined,
935
+ name: input.name ?? undefined,
936
+ auth: input.auth ?? undefined
937
+ });
938
+ return this.createReceipt("workspaces.clone", {
939
+ kind: "workspace",
940
+ id: workspace.id
941
+ }, {
942
+ workspace
943
+ });
944
+ }
945
+ reorderWorkspaces(workspaceIds) {
946
+ const items = this.workspaceService.reorderWorkspaces(workspaceIds);
947
+ return this.createReceipt("workspaces.reorder", {
948
+ kind: "none",
949
+ id: null
950
+ }, {
951
+ items
952
+ });
953
+ }
954
+ async getWorkspaceManagementSummary(workspaceId) {
955
+ const summary = await this.workspaceService.getManagementSummary(workspaceId);
956
+ return this.createReceipt("workspaces.management.get", {
957
+ kind: "workspace",
958
+ id: workspaceId
959
+ }, {
960
+ summary
961
+ });
962
+ }
963
+ updateWorkspaceNavigationState(input) {
964
+ const state = this.workspaceService.updateNavigationState(input.workspaceId, input.userId, {
965
+ collapsed: input.collapsed,
966
+ backgroundColor: input.backgroundColor
967
+ });
968
+ return this.createReceipt("workspaces.navigation-state.update", {
969
+ kind: "workspace",
970
+ id: input.workspaceId
971
+ }, {
972
+ state
973
+ });
974
+ }
975
+ removeWorkspace(workspaceId) {
976
+ const workspace = this.workspaceService.removeWorkspace(workspaceId);
977
+ return this.createReceipt("workspaces.remove", {
978
+ kind: "workspace",
979
+ id: workspaceId
980
+ }, {
981
+ workspace
982
+ });
983
+ }
984
+ async getWorktreeTree(rootWorkspaceId) {
985
+ await this.worktreeSyncService.syncRoot(rootWorkspaceId);
986
+ const items = this.worktreeManager.getTree(rootWorkspaceId);
987
+ return this.createReceipt("worktrees.tree", {
988
+ kind: "workspace",
989
+ id: rootWorkspaceId
990
+ }, {
991
+ rootWorkspaceId,
992
+ items
993
+ });
994
+ }
995
+ async createWorktree(input) {
996
+ const result = await this.worktreeManager.create({
997
+ sourceWorkspaceId: input.sourceWorkspaceId,
998
+ branchName: input.branchName,
999
+ displayName: input.displayName ?? undefined,
1000
+ baseRef: input.baseRef ?? undefined
1001
+ });
1002
+ return this.createReceipt("worktrees.create", {
1003
+ kind: "worktree",
1004
+ id: result.workspace.id
1005
+ }, {
1006
+ result
1007
+ });
1008
+ }
1009
+ async getWorktreeMergePreview(workspaceId) {
1010
+ const preview = await this.worktreeMergeService.preview(workspaceId);
1011
+ return this.createReceipt("worktrees.merge-preview", {
1012
+ kind: "worktree",
1013
+ id: workspaceId
1014
+ }, {
1015
+ preview
1016
+ });
1017
+ }
1018
+ async mergeWorktreeIntoParent(workspaceId) {
1019
+ const result = await this.worktreeMergeService.apply(workspaceId);
1020
+ return this.createReceipt("worktrees.merge-into-parent", {
1021
+ kind: "worktree",
1022
+ id: workspaceId
1023
+ }, {
1024
+ result
1025
+ });
1026
+ }
1027
+ async cleanupWorktree(workspaceId, userId, options) {
1028
+ const result = await this.worktreeCleanupService.cleanup(workspaceId, userId, options);
1029
+ return this.createReceipt("worktrees.cleanup", {
1030
+ kind: "worktree",
1031
+ id: workspaceId
1032
+ }, {
1033
+ result
1034
+ });
1035
+ }
230
1036
  createReceipt(capability, targetRef, payload) {
231
1037
  return {
232
1038
  ok: true,
@@ -237,5 +1043,154 @@ export class AssistantCapabilityService {
237
1043
  payload
238
1044
  };
239
1045
  }
1046
+ resolveSessionLaunchConfig(input) {
1047
+ const controlSession = this.butlerControlSessionService.getCurrentSession(input.userId);
1048
+ const providerId = input.providerId?.trim()
1049
+ ?? controlSession?.providerId
1050
+ ?? undefined;
1051
+ if (!providerId) {
1052
+ throw new AppError({
1053
+ statusCode: 409,
1054
+ errorCode: "ASSISTANT_CONTROL_SESSION_NOT_FOUND",
1055
+ detail: "当前没有可用的助手控制会话,无法继承默认 provider"
1056
+ });
1057
+ }
1058
+ return {
1059
+ providerId,
1060
+ model: normalizeAssistantText(input.model) ?? controlSession?.model ?? null,
1061
+ reasoningLevel: normalizeAssistantText(input.reasoningLevel) ?? controlSession?.reasoningLevel ?? null,
1062
+ permissionMode: normalizeAssistantText(input.permissionMode) ?? controlSession?.permissionMode ?? null
1063
+ };
1064
+ }
1065
+ resolveAssistantSessionTarget(target, userId) {
1066
+ if (target.kind === "project") {
1067
+ const project = this.butlerProjectService.getById(target.projectId);
1068
+ return {
1069
+ kind: "project",
1070
+ id: project.id,
1071
+ workspaceId: project.workspaceId
1072
+ };
1073
+ }
1074
+ if (target.kind === "workspace") {
1075
+ return {
1076
+ kind: "workspace",
1077
+ id: target.workspaceId,
1078
+ workspaceId: target.workspaceId
1079
+ };
1080
+ }
1081
+ return {
1082
+ kind: "sandbox",
1083
+ id: target.sandboxId,
1084
+ workspaceId: this.assistantSandboxService.resolveWorkspaceId(target.sandboxId, userId)
1085
+ };
1086
+ }
1087
+ async createAutomaticSandboxTarget(input, controlSession) {
1088
+ const sandbox = await this.assistantSandboxService.createSandbox({
1089
+ userId: input.userId,
1090
+ controlSessionId: controlSession?.id ?? null,
1091
+ title: inferAutomaticSandboxTitle(controlSession, input.content),
1092
+ purpose: "当前任务未指定工作区,系统自动创建",
1093
+ source: {
1094
+ kind: "blank"
1095
+ }
1096
+ });
1097
+ return {
1098
+ kind: "sandbox",
1099
+ id: sandbox.id,
1100
+ workspaceId: sandbox.workspaceId
1101
+ };
1102
+ }
1103
+ }
1104
+ function normalizeAssistantText(value) {
1105
+ const normalized = value?.trim();
1106
+ return normalized ? normalized : null;
1107
+ }
1108
+ function inferAutomaticSandboxTitle(controlSession, content) {
1109
+ return normalizeAssistantText(controlSession?.title)
1110
+ ?? normalizeAssistantText(controlSession?.lastSummary)
1111
+ ?? summarizeAssistantText(content)
1112
+ ?? "助手临时沙箱";
1113
+ }
1114
+ function summarizeAssistantText(content) {
1115
+ const normalized = normalizeAssistantText(content);
1116
+ if (!normalized) {
1117
+ return null;
1118
+ }
1119
+ return normalized.length > 48 ? `${normalized.slice(0, 45)}...` : normalized;
1120
+ }
1121
+ function buildAssistantAutomationTriggerInput(triggerType, input) {
1122
+ switch (triggerType) {
1123
+ case "once":
1124
+ return {
1125
+ type: "once",
1126
+ dueAt: input.dueAt ?? null,
1127
+ afterSeconds: input.afterSeconds ?? null
1128
+ };
1129
+ case "interval":
1130
+ return {
1131
+ type: "interval",
1132
+ seconds: input.everySeconds ?? null,
1133
+ minutes: input.everyMinutes ?? null,
1134
+ hours: input.everyHours ?? null,
1135
+ stopAt: input.stopAt ?? null
1136
+ };
1137
+ case "cron":
1138
+ return {
1139
+ type: "cron",
1140
+ minute: input.cronMinute ?? null,
1141
+ hour: input.cronHour ?? null,
1142
+ daysOfWeek: input.cronDaysOfWeek ?? null,
1143
+ stopAt: input.stopAt ?? null
1144
+ };
1145
+ case "condition": {
1146
+ const conditionKind = input.conditionKind;
1147
+ if (conditionKind === "git.remote_tag_changed") {
1148
+ return {
1149
+ type: "condition",
1150
+ conditionKind,
1151
+ repositoryUrl: input.repositoryUrl ?? null,
1152
+ pollIntervalSeconds: input.pollIntervalSeconds ?? null,
1153
+ expiresAt: input.expiresAt ?? null,
1154
+ maxChecks: input.maxChecks ?? null
1155
+ };
1156
+ }
1157
+ return {
1158
+ type: "condition",
1159
+ conditionKind: requireAssistantConditionKind(conditionKind),
1160
+ sessionId: input.conditionSessionId ?? null,
1161
+ pollIntervalSeconds: input.pollIntervalSeconds ?? null,
1162
+ expiresAt: input.expiresAt ?? null,
1163
+ maxChecks: input.maxChecks ?? null
1164
+ };
1165
+ }
1166
+ default:
1167
+ return assertNeverAssistantAutomationTriggerType(triggerType);
1168
+ }
1169
+ }
1170
+ function requireAssistantRepositoryUrl(value) {
1171
+ const normalized = normalizeAssistantText(value);
1172
+ if (!normalized) {
1173
+ throw new AppError({
1174
+ statusCode: 400,
1175
+ errorCode: "INVALID_INPUT",
1176
+ detail: "clone 沙箱必须提供 repositoryUrl",
1177
+ field: "repositoryUrl"
1178
+ });
1179
+ }
1180
+ return normalized;
1181
+ }
1182
+ function requireAssistantConditionKind(value) {
1183
+ if (value === "git.remote_tag_changed" || value === "session.runtime_idle") {
1184
+ return value;
1185
+ }
1186
+ throw new AppError({
1187
+ statusCode: 400,
1188
+ errorCode: "INVALID_INPUT",
1189
+ detail: "condition 自动化必须提供 conditionKind",
1190
+ field: "conditionKind"
1191
+ });
1192
+ }
1193
+ function assertNeverAssistantAutomationTriggerType(value) {
1194
+ throw new Error(`Unexpected assistant automation triggerType: ${String(value)}`);
240
1195
  }
241
1196
  //# sourceMappingURL=assistant-capability-service.js.map