@jingyi0605/codingns 0.3.6 → 0.5.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 (369) hide show
  1. package/README.md +3 -0
  2. package/bin/codingns.mjs +913 -1
  3. package/dist/public/assets/AdaptiveButlerPage-B153lk5H.css +1 -0
  4. package/dist/public/assets/AdaptiveButlerPage-R-XZw7pd.js +3 -0
  5. package/dist/public/assets/App-DUAg5urj.css +1 -0
  6. package/dist/public/assets/App-DkvE5EyM.js +30 -0
  7. package/dist/public/assets/BootstrapPage-Vu5oEJ8z.js +1 -0
  8. package/dist/public/assets/ConversationPage-Cjpg6g0J.js +2 -0
  9. package/dist/public/assets/DesktopDetachPreviewPage-BgeEqbc5.js +1 -0
  10. package/dist/public/assets/DesktopWindowPage-1WelvxdH.js +2 -0
  11. package/dist/public/assets/FileContextPanel-D_ghXJuW.js +1 -0
  12. package/dist/public/assets/GitSidebar-D9f9Jxwr.js +6 -0
  13. package/dist/public/assets/MobileCreateSessionSheet-DLq5qPkx.js +1 -0
  14. package/dist/public/assets/MobileSheet-DLg-gX1t.js +1 -0
  15. package/dist/public/assets/MobileTopHeaderFrame-DArgZI7L.js +1 -0
  16. package/dist/public/assets/MobileWorkspaceSwitcherHeader-0ywJKfBQ.js +1 -0
  17. package/dist/public/assets/ServerSettingsModal-izoYMx9U.js +1 -0
  18. package/dist/public/assets/SessionIndexPage-C5aG8FIv.js +1 -0
  19. package/dist/public/assets/SettingsPage-HJIC-P-4.js +1 -0
  20. package/dist/public/assets/TerminalManagerPanel-DpyUTo9k.js +1 -0
  21. package/dist/public/assets/{TerminalPage-D00S4KM6.js → TerminalPage-CtKXIU0h.js} +19 -19
  22. package/dist/public/assets/TerminalRuntimeFallbackModal-CRhOQOsT.js +1 -0
  23. package/dist/public/assets/ToolFilesPage-DcYPsS-e.js +1 -0
  24. package/dist/public/assets/ToolGitPage-CsPl89ty.js +1 -0
  25. package/dist/public/assets/ToolProcessesPage-D0dvR8xK.js +1 -0
  26. package/dist/public/assets/ToolsHomePage-4fP-KRiv.js +1 -0
  27. package/dist/public/assets/WorkbenchLandingPage-kvlfyxRo.js +1 -0
  28. package/dist/public/assets/WorkbenchLayout-ByFw4eeu.js +3 -0
  29. package/dist/public/assets/WorkbenchModal-Ctob14VR.js +1 -0
  30. package/dist/public/assets/WorkbenchShellRoute-BUITtdAg.css +1 -0
  31. package/dist/public/assets/WorkbenchShellRoute-Kw7JEZI3.js +1 -0
  32. package/dist/public/assets/WorkspaceDebugDetailPage-Com5kEXJ.js +1 -0
  33. package/dist/public/assets/WorkspaceDetailPage-D0Lrx4Uz.js +1 -0
  34. package/dist/public/assets/WorkspaceHomePage-wR8d3aP9.js +1 -0
  35. package/dist/public/assets/butler-records-events-DgWCG364.js +1 -0
  36. package/dist/public/assets/default-session-permission-mode-CcGwR4Kk.js +1 -0
  37. package/dist/public/assets/event-DvH9tcej.js +1 -0
  38. package/dist/public/assets/file-tree-icon-UFVoVzhM.js +31 -0
  39. package/dist/public/assets/index-Byp9hJ0c.js +42 -0
  40. package/dist/public/assets/index-_52jxu4a.css +1 -0
  41. package/dist/public/assets/preferences-service-KIYeE2gk.js +1 -0
  42. package/dist/public/assets/session-runtime-machine-0KNSSPp5.js +17 -0
  43. package/dist/public/assets/styles-BWPBZvze.css +1 -0
  44. package/dist/public/assets/styles-CSUx5LGe.js +1 -0
  45. package/dist/public/assets/terminal-runtime-meta-AWXJpN4r.js +1 -0
  46. package/dist/public/assets/useRegisteredDebugTemplates-DBDRdptr.js +1 -0
  47. package/dist/public/assets/window-BWqRixxq.js +1 -0
  48. package/dist/public/index.html +2 -2
  49. package/dist/server/middlewares/auth-guard.d.ts +4 -0
  50. package/dist/server/middlewares/auth-guard.js +42 -4
  51. package/dist/server/middlewares/auth-guard.js.map +1 -1
  52. package/dist/server/modules/assistant-capability/assistant-capability-controller.d.ts +234 -0
  53. package/dist/server/modules/assistant-capability/assistant-capability-controller.js +365 -0
  54. package/dist/server/modules/assistant-capability/assistant-capability-controller.js.map +1 -1
  55. package/dist/server/modules/assistant-capability/assistant-capability-service.d.ts +262 -2
  56. package/dist/server/modules/assistant-capability/assistant-capability-service.js +737 -3
  57. package/dist/server/modules/assistant-capability/assistant-capability-service.js.map +1 -1
  58. package/dist/server/modules/auth/auth-controller.d.ts +11 -1
  59. package/dist/server/modules/auth/auth-controller.js +61 -2
  60. package/dist/server/modules/auth/auth-controller.js.map +1 -1
  61. package/dist/server/modules/auth/auth-device-display-name.d.ts +10 -0
  62. package/dist/server/modules/auth/auth-device-display-name.js +190 -0
  63. package/dist/server/modules/auth/auth-device-display-name.js.map +1 -0
  64. package/dist/server/modules/auth/auth-service.d.ts +80 -5
  65. package/dist/server/modules/auth/auth-service.js +333 -23
  66. package/dist/server/modules/auth/auth-service.js.map +1 -1
  67. package/dist/server/modules/butler/assistant-automation-service.d.ts +112 -0
  68. package/dist/server/modules/butler/assistant-automation-service.js +832 -0
  69. package/dist/server/modules/butler/assistant-automation-service.js.map +1 -0
  70. package/dist/server/modules/butler/assistant-automation-trigger.d.ts +94 -0
  71. package/dist/server/modules/butler/assistant-automation-trigger.js +400 -0
  72. package/dist/server/modules/butler/assistant-automation-trigger.js.map +1 -0
  73. package/dist/server/modules/butler/assistant-sandbox-cleanup-scheduler.d.ts +32 -0
  74. package/dist/server/modules/butler/assistant-sandbox-cleanup-scheduler.js +93 -0
  75. package/dist/server/modules/butler/assistant-sandbox-cleanup-scheduler.js.map +1 -0
  76. package/dist/server/modules/butler/assistant-sandbox-service.d.ts +69 -0
  77. package/dist/server/modules/butler/assistant-sandbox-service.js +399 -0
  78. package/dist/server/modules/butler/assistant-sandbox-service.js.map +1 -0
  79. package/dist/server/modules/butler/butler-action-context-service.d.ts +4 -1
  80. package/dist/server/modules/butler/butler-action-context-service.js +8 -2
  81. package/dist/server/modules/butler/butler-action-context-service.js.map +1 -1
  82. package/dist/server/modules/butler/butler-auth-service.js +7 -2
  83. package/dist/server/modules/butler/butler-auth-service.js.map +1 -1
  84. package/dist/server/modules/butler/butler-control-session-service.d.ts +11 -1
  85. package/dist/server/modules/butler/butler-control-session-service.js +173 -40
  86. package/dist/server/modules/butler/butler-control-session-service.js.map +1 -1
  87. package/dist/server/modules/butler/butler-control-timer-scheduler.d.ts +32 -0
  88. package/dist/server/modules/butler/butler-control-timer-scheduler.js +93 -0
  89. package/dist/server/modules/butler/butler-control-timer-scheduler.js.map +1 -0
  90. package/dist/server/modules/butler/butler-control-timer-service.d.ts +42 -0
  91. package/dist/server/modules/butler/butler-control-timer-service.js +132 -0
  92. package/dist/server/modules/butler/butler-control-timer-service.js.map +1 -0
  93. package/dist/server/modules/butler/butler-controller.d.ts +42 -2
  94. package/dist/server/modules/butler/butler-controller.js +79 -12
  95. package/dist/server/modules/butler/butler-controller.js.map +1 -1
  96. package/dist/server/modules/butler/butler-follow-up-evaluation-instruction-adapter.d.ts +2 -1
  97. package/dist/server/modules/butler/butler-follow-up-evaluation-instruction-adapter.js +27 -25
  98. package/dist/server/modules/butler/butler-follow-up-evaluation-instruction-adapter.js.map +1 -1
  99. package/dist/server/modules/butler/butler-follow-up-service.d.ts +41 -5
  100. package/dist/server/modules/butler/butler-follow-up-service.js +568 -371
  101. package/dist/server/modules/butler/butler-follow-up-service.js.map +1 -1
  102. package/dist/server/modules/butler/butler-inbox-analysis-service.d.ts +4 -1
  103. package/dist/server/modules/butler/butler-inbox-analysis-service.js +18 -4
  104. package/dist/server/modules/butler/butler-inbox-analysis-service.js.map +1 -1
  105. package/dist/server/modules/butler/butler-inbox-service.js +1 -0
  106. package/dist/server/modules/butler/butler-inbox-service.js.map +1 -1
  107. package/dist/server/modules/butler/butler-profile-service.js +2 -5
  108. package/dist/server/modules/butler/butler-profile-service.js.map +1 -1
  109. package/dist/server/modules/butler/butler-project-service.d.ts +3 -1
  110. package/dist/server/modules/butler/butler-project-service.js +7 -1
  111. package/dist/server/modules/butler/butler-project-service.js.map +1 -1
  112. package/dist/server/modules/butler/butler-session-service.d.ts +5 -1
  113. package/dist/server/modules/butler/butler-session-service.js +26 -1
  114. package/dist/server/modules/butler/butler-session-service.js.map +1 -1
  115. package/dist/server/modules/butler/butler-session-summary-service.js +2 -1
  116. package/dist/server/modules/butler/butler-session-summary-service.js.map +1 -1
  117. package/dist/server/modules/butler/butler-workspace-context.d.ts +4 -1
  118. package/dist/server/modules/butler/butler-workspace-context.js +204 -58
  119. package/dist/server/modules/butler/butler-workspace-context.js.map +1 -1
  120. package/dist/server/modules/butler/patrol-execution-service.js +2 -1
  121. package/dist/server/modules/butler/patrol-execution-service.js.map +1 -1
  122. package/dist/server/modules/butler/provider-adapter-registry.d.ts +3 -0
  123. package/dist/server/modules/butler/provider-adapter-registry.js +18 -1
  124. package/dist/server/modules/butler/provider-adapter-registry.js.map +1 -1
  125. package/dist/server/modules/butler/verification-run-service.d.ts +9 -2
  126. package/dist/server/modules/butler/verification-run-service.js +188 -34
  127. package/dist/server/modules/butler/verification-run-service.js.map +1 -1
  128. package/dist/server/modules/debug-target/debug-target-controller.js +1 -1
  129. package/dist/server/modules/debug-target/debug-target-controller.js.map +1 -1
  130. package/dist/server/modules/debug-target/debug-target-service.d.ts +7 -2
  131. package/dist/server/modules/debug-target/debug-target-service.js +563 -100
  132. package/dist/server/modules/debug-target/debug-target-service.js.map +1 -1
  133. package/dist/server/modules/git/git-command-helper-client.d.ts +1 -0
  134. package/dist/server/modules/git/git-command-helper-client.js +19 -26
  135. package/dist/server/modules/git/git-command-helper-client.js.map +1 -1
  136. package/dist/server/modules/git/git-command-runner.js +19 -1
  137. package/dist/server/modules/git/git-command-runner.js.map +1 -1
  138. package/dist/server/modules/preferences/profile-service.d.ts +3 -1
  139. package/dist/server/modules/preferences/profile-service.js +74 -3
  140. package/dist/server/modules/preferences/profile-service.js.map +1 -1
  141. package/dist/server/modules/provider/provider-controller.d.ts +1 -1
  142. package/dist/server/modules/provider/provider-controller.js.map +1 -1
  143. package/dist/server/modules/provider/provider-discovery-helper-client.d.ts +5 -3
  144. package/dist/server/modules/provider/provider-discovery-helper-client.js +129 -43
  145. package/dist/server/modules/provider/provider-discovery-helper-client.js.map +1 -1
  146. package/dist/server/modules/provider/provider-discovery-helper-process.js +44 -0
  147. package/dist/server/modules/provider/provider-discovery-helper-process.js.map +1 -1
  148. package/dist/server/modules/provider/provider-discovery-runtime.js +83 -3
  149. package/dist/server/modules/provider/provider-discovery-runtime.js.map +1 -1
  150. package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-identity-service.d.ts +10 -0
  151. package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-identity-service.js +48 -0
  152. package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-identity-service.js.map +1 -0
  153. package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-packets.d.ts +48 -0
  154. package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-packets.js +11 -0
  155. package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-packets.js.map +1 -0
  156. package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-protocol.d.ts +74 -0
  157. package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-protocol.js +302 -0
  158. package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-protocol.js.map +1 -0
  159. package/dist/server/modules/relay-tunnel/relay-tunnel-controller.d.ts +33 -0
  160. package/dist/server/modules/relay-tunnel/relay-tunnel-controller.js +57 -0
  161. package/dist/server/modules/relay-tunnel/relay-tunnel-controller.js.map +1 -0
  162. package/dist/server/modules/relay-tunnel/relay-tunnel-edge-proof.d.ts +9 -0
  163. package/dist/server/modules/relay-tunnel/relay-tunnel-edge-proof.js +25 -0
  164. package/dist/server/modules/relay-tunnel/relay-tunnel-edge-proof.js.map +1 -0
  165. package/dist/server/modules/relay-tunnel/relay-tunnel-gateway-service.d.ts +18 -0
  166. package/dist/server/modules/relay-tunnel/relay-tunnel-gateway-service.js +230 -0
  167. package/dist/server/modules/relay-tunnel/relay-tunnel-gateway-service.js.map +1 -0
  168. package/dist/server/modules/relay-tunnel/relay-tunnel-runtime-adapter.d.ts +41 -0
  169. package/dist/server/modules/relay-tunnel/relay-tunnel-runtime-adapter.js +443 -0
  170. package/dist/server/modules/relay-tunnel/relay-tunnel-runtime-adapter.js.map +1 -0
  171. package/dist/server/modules/relay-tunnel/relay-tunnel-service.d.ts +111 -0
  172. package/dist/server/modules/relay-tunnel/relay-tunnel-service.js +771 -0
  173. package/dist/server/modules/relay-tunnel/relay-tunnel-service.js.map +1 -0
  174. package/dist/server/modules/sessions/claude-runtime-helper-client.js +23 -1
  175. package/dist/server/modules/sessions/claude-runtime-helper-client.js.map +1 -1
  176. package/dist/server/modules/sessions/codex-app-server-helper-client.d.ts +2 -1
  177. package/dist/server/modules/sessions/codex-app-server-helper-client.js +78 -0
  178. package/dist/server/modules/sessions/codex-app-server-helper-client.js.map +1 -1
  179. package/dist/server/modules/sessions/codex-app-server-helper-process.js +84 -2
  180. package/dist/server/modules/sessions/codex-app-server-helper-process.js.map +1 -1
  181. package/dist/server/modules/sessions/provider-session-delete-cli.d.ts +15 -0
  182. package/dist/server/modules/sessions/provider-session-delete-cli.js +148 -0
  183. package/dist/server/modules/sessions/provider-session-delete-cli.js.map +1 -0
  184. package/dist/server/modules/sessions/session-controller.d.ts +4 -1
  185. package/dist/server/modules/sessions/session-controller.js +4 -0
  186. package/dist/server/modules/sessions/session-controller.js.map +1 -1
  187. package/dist/server/modules/sessions/session-history-service.d.ts +24 -1
  188. package/dist/server/modules/sessions/session-history-service.js +401 -42
  189. package/dist/server/modules/sessions/session-history-service.js.map +1 -1
  190. package/dist/server/modules/sessions/session-live-runtime-router-service.d.ts +25 -0
  191. package/dist/server/modules/sessions/session-live-runtime-router-service.js +42 -0
  192. package/dist/server/modules/sessions/session-live-runtime-router-service.js.map +1 -0
  193. package/dist/server/modules/sessions/session-live-runtime-service.d.ts +6 -0
  194. package/dist/server/modules/sessions/session-live-runtime-service.js +130 -28
  195. package/dist/server/modules/sessions/session-live-runtime-service.js.map +1 -1
  196. package/dist/server/modules/sessions/session-message-attachment-service.d.ts +1 -0
  197. package/dist/server/modules/sessions/session-message-attachment-service.js +22 -0
  198. package/dist/server/modules/sessions/session-message-attachment-service.js.map +1 -1
  199. package/dist/server/modules/sessions/session-message-origin-utils.d.ts +12 -0
  200. package/dist/server/modules/sessions/session-message-origin-utils.js +45 -0
  201. package/dist/server/modules/sessions/session-message-origin-utils.js.map +1 -0
  202. package/dist/server/modules/sessions/session-permission-request-service.d.ts +1 -0
  203. package/dist/server/modules/sessions/session-permission-request-service.js +367 -5
  204. package/dist/server/modules/sessions/session-permission-request-service.js.map +1 -1
  205. package/dist/server/modules/sessions/session-provider-error-mapper.js +32 -0
  206. package/dist/server/modules/sessions/session-provider-error-mapper.js.map +1 -1
  207. package/dist/server/modules/sessions/session-provider-usage-guard-service.d.ts +37 -0
  208. package/dist/server/modules/sessions/session-provider-usage-guard-service.js +179 -0
  209. package/dist/server/modules/sessions/session-provider-usage-guard-service.js.map +1 -0
  210. package/dist/server/modules/sessions/session-provider-usage-limit.d.ts +17 -0
  211. package/dist/server/modules/sessions/session-provider-usage-limit.js +465 -0
  212. package/dist/server/modules/sessions/session-provider-usage-limit.js.map +1 -0
  213. package/dist/server/modules/skills/assistant-runtime-skill-catalog.d.ts +8 -0
  214. package/dist/server/modules/skills/assistant-runtime-skill-catalog.js +26 -0
  215. package/dist/server/modules/skills/assistant-runtime-skill-catalog.js.map +1 -0
  216. package/dist/server/modules/skills/assistant-runtime-skill-cleanup.d.ts +9 -0
  217. package/dist/server/modules/skills/assistant-runtime-skill-cleanup.js +55 -0
  218. package/dist/server/modules/skills/assistant-runtime-skill-cleanup.js.map +1 -0
  219. package/dist/server/modules/skills/builtin-skill-service.js +1 -6
  220. package/dist/server/modules/skills/builtin-skill-service.js.map +1 -1
  221. package/dist/server/modules/skills/builtin-skills/codingns-assistant/SKILL.md +19 -12
  222. package/dist/server/modules/skills/builtin-skills/codingns-assistant/references/cli-workflow.md +9 -3
  223. package/dist/server/modules/skills/skill-controller.d.ts +2 -2
  224. package/dist/server/modules/skills/skill-controller.js +9 -1
  225. package/dist/server/modules/skills/skill-controller.js.map +1 -1
  226. package/dist/server/modules/skills/skill-manager-service.d.ts +26 -1
  227. package/dist/server/modules/skills/skill-manager-service.js +346 -90
  228. package/dist/server/modules/skills/skill-manager-service.js.map +1 -1
  229. package/dist/server/modules/skills/skill-name-policy.d.ts +2 -0
  230. package/dist/server/modules/skills/skill-name-policy.js +10 -0
  231. package/dist/server/modules/skills/skill-name-policy.js.map +1 -0
  232. package/dist/server/modules/tailscale/tailscale-service.d.ts +2 -0
  233. package/dist/server/modules/tailscale/tailscale-service.js +21 -8
  234. package/dist/server/modules/tailscale/tailscale-service.js.map +1 -1
  235. package/dist/server/modules/tasks/task-helper-client.d.ts +5 -2
  236. package/dist/server/modules/tasks/task-helper-client.js +118 -38
  237. package/dist/server/modules/tasks/task-helper-client.js.map +1 -1
  238. package/dist/server/modules/tasks/task-helper-process.js +94 -3
  239. package/dist/server/modules/tasks/task-helper-process.js.map +1 -1
  240. package/dist/server/modules/tasks/task-types.d.ts +6 -0
  241. package/dist/server/modules/tasks/task-types.js +7 -1
  242. package/dist/server/modules/tasks/task-types.js.map +1 -1
  243. package/dist/server/modules/terminal/command-template-service.d.ts +9 -0
  244. package/dist/server/modules/terminal/command-template-service.js +87 -5
  245. package/dist/server/modules/terminal/command-template-service.js.map +1 -1
  246. package/dist/server/modules/terminal/template-reverse-proxy-service.js +71 -3
  247. package/dist/server/modules/terminal/template-reverse-proxy-service.js.map +1 -1
  248. package/dist/server/modules/terminal/terminal-controller.d.ts +3 -0
  249. package/dist/server/modules/terminal/terminal-controller.js +41 -0
  250. package/dist/server/modules/terminal/terminal-controller.js.map +1 -1
  251. package/dist/server/modules/workbench/workbench-service.d.ts +3 -0
  252. package/dist/server/modules/workbench/workbench-service.js +4 -3
  253. package/dist/server/modules/workbench/workbench-service.js.map +1 -1
  254. package/dist/server/modules/workbench/workspace-file-watcher.d.ts +14 -6
  255. package/dist/server/modules/workbench/workspace-file-watcher.js +267 -57
  256. package/dist/server/modules/workbench/workspace-file-watcher.js.map +1 -1
  257. package/dist/server/modules/workbench/workspace-panel-snapshot-service.d.ts +2 -0
  258. package/dist/server/modules/workbench/workspace-panel-snapshot-service.js +32 -3
  259. package/dist/server/modules/workbench/workspace-panel-snapshot-service.js.map +1 -1
  260. package/dist/server/modules/worktree/worktree-manager.d.ts +9 -1
  261. package/dist/server/modules/worktree/worktree-manager.js +9 -1
  262. package/dist/server/modules/worktree/worktree-manager.js.map +1 -1
  263. package/dist/server/routes/assistant.js +49 -0
  264. package/dist/server/routes/assistant.js.map +1 -1
  265. package/dist/server/routes/auth.js +4 -0
  266. package/dist/server/routes/auth.js.map +1 -1
  267. package/dist/server/routes/butler.js +5 -0
  268. package/dist/server/routes/butler.js.map +1 -1
  269. package/dist/server/routes/sessions.js +1 -0
  270. package/dist/server/routes/sessions.js.map +1 -1
  271. package/dist/server/routes/system.d.ts +2 -1
  272. package/dist/server/routes/system.js +13 -1
  273. package/dist/server/routes/system.js.map +1 -1
  274. package/dist/server/server/create-server.d.ts +18 -0
  275. package/dist/server/server/create-server.js +113 -20
  276. package/dist/server/server/create-server.js.map +1 -1
  277. package/dist/server/shared/utils/tokens.d.ts +3 -1
  278. package/dist/server/shared/utils/tokens.js +9 -2
  279. package/dist/server/shared/utils/tokens.js.map +1 -1
  280. package/dist/server/storage/repositories/assistant-automation-run-repository.d.ts +12 -0
  281. package/dist/server/storage/repositories/assistant-automation-run-repository.js +139 -0
  282. package/dist/server/storage/repositories/assistant-automation-run-repository.js.map +1 -0
  283. package/dist/server/storage/repositories/assistant-automation-task-repository.d.ts +17 -0
  284. package/dist/server/storage/repositories/assistant-automation-task-repository.js +179 -0
  285. package/dist/server/storage/repositories/assistant-automation-task-repository.js.map +1 -0
  286. package/dist/server/storage/repositories/assistant-sandbox-workspace-repository.d.ts +18 -0
  287. package/dist/server/storage/repositories/assistant-sandbox-workspace-repository.js +191 -0
  288. package/dist/server/storage/repositories/assistant-sandbox-workspace-repository.js.map +1 -0
  289. package/dist/server/storage/repositories/auth-device-repository.d.ts +22 -0
  290. package/dist/server/storage/repositories/auth-device-repository.js +97 -0
  291. package/dist/server/storage/repositories/auth-device-repository.js.map +1 -0
  292. package/dist/server/storage/repositories/auth-device-session-repository.d.ts +17 -0
  293. package/dist/server/storage/repositories/auth-device-session-repository.js +82 -0
  294. package/dist/server/storage/repositories/auth-device-session-repository.js.map +1 -0
  295. package/dist/server/storage/repositories/auth-login-event-repository.d.ts +9 -0
  296. package/dist/server/storage/repositories/auth-login-event-repository.js +53 -0
  297. package/dist/server/storage/repositories/auth-login-event-repository.js.map +1 -0
  298. package/dist/server/storage/repositories/auth-token-repository.d.ts +4 -0
  299. package/dist/server/storage/repositories/auth-token-repository.js +58 -5
  300. package/dist/server/storage/repositories/auth-token-repository.js.map +1 -1
  301. package/dist/server/storage/repositories/butler-control-session-repository.js +27 -3
  302. package/dist/server/storage/repositories/butler-control-session-repository.js.map +1 -1
  303. package/dist/server/storage/repositories/butler-control-timer-repository.d.ts +15 -0
  304. package/dist/server/storage/repositories/butler-control-timer-repository.js +157 -0
  305. package/dist/server/storage/repositories/butler-control-timer-repository.js.map +1 -0
  306. package/dist/server/storage/repositories/butler-follow-up-task-repository.js +21 -3
  307. package/dist/server/storage/repositories/butler-follow-up-task-repository.js.map +1 -1
  308. package/dist/server/storage/repositories/instance-relay-tunnel-identity-repository.d.ts +8 -0
  309. package/dist/server/storage/repositories/instance-relay-tunnel-identity-repository.js +52 -0
  310. package/dist/server/storage/repositories/instance-relay-tunnel-identity-repository.js.map +1 -0
  311. package/dist/server/storage/repositories/instance-relay-tunnel-repository.d.ts +10 -0
  312. package/dist/server/storage/repositories/instance-relay-tunnel-repository.js +153 -0
  313. package/dist/server/storage/repositories/instance-relay-tunnel-repository.js.map +1 -0
  314. package/dist/server/storage/repositories/instance-tailscale-repository.js +6 -3
  315. package/dist/server/storage/repositories/instance-tailscale-repository.js.map +1 -1
  316. package/dist/server/storage/repositories/managed-skill-repository.d.ts +2 -1
  317. package/dist/server/storage/repositories/managed-skill-repository.js +14 -4
  318. package/dist/server/storage/repositories/managed-skill-repository.js.map +1 -1
  319. package/dist/server/storage/repositories/session-message-attachment-repository.d.ts +2 -0
  320. package/dist/server/storage/repositories/session-message-attachment-repository.js +24 -0
  321. package/dist/server/storage/repositories/session-message-attachment-repository.js.map +1 -1
  322. package/dist/server/storage/repositories/user-preference-profile-repository.js +6 -3
  323. package/dist/server/storage/repositories/user-preference-profile-repository.js.map +1 -1
  324. package/dist/server/storage/sqlite/client.js +534 -2
  325. package/dist/server/storage/sqlite/client.js.map +1 -1
  326. package/dist/server/storage/sqlite/schema.sql +228 -4
  327. package/dist/server/types/domain.d.ts +170 -2
  328. package/dist/server/ws/workbench-ws-hub.d.ts +14 -8
  329. package/dist/server/ws/workbench-ws-hub.js +369 -209
  330. package/dist/server/ws/workbench-ws-hub.js.map +1 -1
  331. package/dist/server/ws/ws-auth-guard.js +1 -4
  332. package/dist/server/ws/ws-auth-guard.js.map +1 -1
  333. package/dist/server/ws/ws-server.d.ts +1 -1
  334. package/dist/server/ws/ws-server.js.map +1 -1
  335. package/node_modules/@codingns/session-sync-core/dist/codex-resume-history.d.ts +1 -0
  336. package/node_modules/@codingns/session-sync-core/dist/codex-resume-history.js +80 -0
  337. package/node_modules/@codingns/session-sync-core/dist/codex-resume-history.js.map +1 -0
  338. package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.d.ts +5 -1
  339. package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.js +122 -4
  340. package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.js.map +1 -1
  341. package/node_modules/@codingns/session-sync-core/dist/providers/codex.d.ts +17 -1
  342. package/node_modules/@codingns/session-sync-core/dist/providers/codex.js +437 -51
  343. package/node_modules/@codingns/session-sync-core/dist/providers/codex.js.map +1 -1
  344. package/node_modules/@codingns/session-sync-core/dist/providers/gemini.d.ts +7 -1
  345. package/node_modules/@codingns/session-sync-core/dist/providers/gemini.js +240 -27
  346. package/node_modules/@codingns/session-sync-core/dist/providers/gemini.js.map +1 -1
  347. package/node_modules/@codingns/session-sync-core/dist/providers/kimi.d.ts +5 -1
  348. package/node_modules/@codingns/session-sync-core/dist/providers/kimi.js +108 -2
  349. package/node_modules/@codingns/session-sync-core/dist/providers/kimi.js.map +1 -1
  350. package/node_modules/@codingns/session-sync-core/dist/providers/opencode.d.ts +3 -0
  351. package/node_modules/@codingns/session-sync-core/dist/providers/opencode.js +101 -8
  352. package/node_modules/@codingns/session-sync-core/dist/providers/opencode.js.map +1 -1
  353. package/node_modules/@codingns/session-sync-core/dist/providers/utils.d.ts +1 -0
  354. package/node_modules/@codingns/session-sync-core/dist/providers/utils.js +4 -1
  355. package/node_modules/@codingns/session-sync-core/dist/providers/utils.js.map +1 -1
  356. package/node_modules/@codingns/session-sync-core/dist/runtime/claude-runtime.js +44 -0
  357. package/node_modules/@codingns/session-sync-core/dist/runtime/claude-runtime.js.map +1 -1
  358. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.d.ts +5 -1
  359. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js +153 -60
  360. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js.map +1 -1
  361. package/node_modules/@codingns/session-sync-core/dist/runtime/types.d.ts +1 -0
  362. package/node_modules/@codingns/session-sync-core/dist/services.d.ts +1 -0
  363. package/node_modules/@codingns/session-sync-core/dist/services.js +24 -8
  364. package/node_modules/@codingns/session-sync-core/dist/services.js.map +1 -1
  365. package/node_modules/@codingns/session-sync-core/dist/types.d.ts +6 -0
  366. package/package.json +1 -1
  367. package/scripts/postinstall.mjs +0 -33
  368. package/dist/public/assets/index-BlOinYqR.js +0 -122
  369. package/dist/public/assets/index-Dg_7g6lA.css +0 -1
@@ -0,0 +1,832 @@
1
+ import { AppError } from "../../shared/errors/app-error.js";
2
+ import { createId } from "../../shared/utils/id.js";
3
+ import { nowIso } from "../../shared/utils/time.js";
4
+ import { readProviderUsageLimitErrorData } from "../sessions/session-provider-usage-guard-service.js";
5
+ import { createTaskManager } from "../tasks/task-manager.js";
6
+ import { HOST_TASK_TYPES } from "../tasks/task-types.js";
7
+ import { buildConditionTriggerConfig, computeNextRunAt, createTriggerConfig, parseActionConfig, parseConditionState, parseTriggerConfig } from "./assistant-automation-trigger.js";
8
+ const DEFAULT_DUE_TASK_LIMIT = 20;
9
+ const DEFAULT_RECENT_RUN_LIMIT = 30;
10
+ export class AssistantAutomationService {
11
+ butlerProfileService;
12
+ butlerControlSessionService;
13
+ taskRepository;
14
+ runRepository;
15
+ taskManager;
16
+ gitCommandRunner;
17
+ sessionLiveRuntimeService;
18
+ gitWorkingDirectory;
19
+ constructor(butlerProfileService, butlerControlSessionService, taskRepository, runRepository, taskManager = createTaskManager(), dependencies = {}) {
20
+ this.butlerProfileService = butlerProfileService;
21
+ this.butlerControlSessionService = butlerControlSessionService;
22
+ this.taskRepository = taskRepository;
23
+ this.runRepository = runRepository;
24
+ this.taskManager = taskManager;
25
+ this.gitCommandRunner = dependencies.gitCommandRunner ?? null;
26
+ this.sessionLiveRuntimeService = dependencies.sessionLiveRuntimeService ?? null;
27
+ this.gitWorkingDirectory = dependencies.gitWorkingDirectory ?? process.cwd();
28
+ this.registerBackgroundTasks();
29
+ }
30
+ listTasks(filters) {
31
+ this.butlerProfileService.ensureInitialized();
32
+ return this.taskRepository
33
+ .list({
34
+ statuses: filters.statuses,
35
+ controlSessionId: filters.controlSessionId?.trim() || undefined,
36
+ limit: filters.limit
37
+ })
38
+ .map((record) => this.toTaskView(record, filters.userId));
39
+ }
40
+ getTask(taskId, userId) {
41
+ this.butlerProfileService.ensureInitialized();
42
+ const task = this.requireTask(taskId.trim());
43
+ return this.toTaskView(task, userId);
44
+ }
45
+ listRuns(taskId, _userId, limit) {
46
+ this.butlerProfileService.ensureInitialized();
47
+ this.requireTask(taskId);
48
+ return this.runRepository
49
+ .listByAutomation(taskId.trim(), limit)
50
+ .map((record) => this.toRunView(record));
51
+ }
52
+ listRecentRuns(filters) {
53
+ this.butlerProfileService.ensureInitialized();
54
+ const limit = filters.limit && filters.limit > 0 ? filters.limit : DEFAULT_RECENT_RUN_LIMIT;
55
+ const taskMap = new Map(this.taskRepository.list().map((task) => [task.id, task]));
56
+ return this.runRepository
57
+ .listRecent(limit * 3)
58
+ .filter((run) => {
59
+ const task = taskMap.get(run.automationId);
60
+ if (!task || task.userId !== filters.userId) {
61
+ return false;
62
+ }
63
+ if (filters.controlSessionId?.trim()) {
64
+ return task.controlSessionId === filters.controlSessionId.trim();
65
+ }
66
+ return true;
67
+ })
68
+ .slice(0, limit)
69
+ .map((record) => this.toRunView(record));
70
+ }
71
+ createTask(input) {
72
+ this.butlerProfileService.ensureInitialized();
73
+ const controlSession = input.controlSessionId?.trim()
74
+ ? this.butlerControlSessionService.getSession(input.controlSessionId, input.userId)
75
+ : this.butlerControlSessionService.getCurrentSession(input.userId);
76
+ if (!controlSession) {
77
+ throw new AppError({
78
+ statusCode: 409,
79
+ errorCode: "BUTLER_CONTROL_SESSION_NOT_FOUND",
80
+ detail: "当前没有可用的助手控制会话,无法创建自动化任务"
81
+ });
82
+ }
83
+ const timestamp = nowIso();
84
+ const trigger = createTriggerConfig(input.trigger, timestamp);
85
+ const task = this.taskRepository.create({
86
+ id: createId(),
87
+ userId: input.userId,
88
+ controlSessionId: controlSession.id,
89
+ projectId: normalizeNullableText(input.projectId),
90
+ title: normalizeNullableText(input.title),
91
+ triggerType: trigger.triggerType,
92
+ triggerConfigJson: trigger.triggerConfigJson,
93
+ actionType: "send_control_message",
94
+ actionConfigJson: JSON.stringify({
95
+ content: requireContent(input.action.content),
96
+ includeTriggerContext: input.action.includeTriggerContext === true,
97
+ targetSessionId: normalizeNullableText(input.action.targetSessionId)
98
+ }),
99
+ status: "active",
100
+ nextRunAt: trigger.nextRunAt,
101
+ lastRunAt: null,
102
+ lastRunSummary: null,
103
+ lastError: null,
104
+ createdAt: timestamp,
105
+ updatedAt: timestamp,
106
+ cancelledAt: null
107
+ });
108
+ return this.toTaskView(task, input.userId);
109
+ }
110
+ updateTask(input) {
111
+ this.butlerProfileService.ensureInitialized();
112
+ const current = this.requireTask(input.taskId);
113
+ if (current.status !== "active") {
114
+ throw new AppError({
115
+ statusCode: 409,
116
+ errorCode: "ASSISTANT_AUTOMATION_UPDATE_NOT_ALLOWED",
117
+ detail: "只有进行中的自动化可以修改配置"
118
+ });
119
+ }
120
+ const updatedAt = nowIso();
121
+ const currentTriggerConfig = parseTriggerConfig(current.triggerType, current.triggerConfigJson);
122
+ const currentActionConfig = parseActionConfig(current.actionConfigJson);
123
+ const trigger = this.buildUpdatedTrigger(current, currentTriggerConfig, input, updatedAt);
124
+ const actionConfig = {
125
+ content: typeof input.content === "string"
126
+ ? requireContent(input.content)
127
+ : currentActionConfig.content,
128
+ includeTriggerContext: typeof input.includeTriggerContext === "boolean"
129
+ ? input.includeTriggerContext
130
+ : currentActionConfig.includeTriggerContext,
131
+ targetSessionId: currentActionConfig.targetSessionId
132
+ };
133
+ const nextTitle = input.title !== undefined
134
+ ? normalizeNullableText(input.title)
135
+ : current.title;
136
+ const updated = this.taskRepository.update({
137
+ ...current,
138
+ title: nextTitle,
139
+ triggerConfigJson: trigger.triggerConfigJson,
140
+ nextRunAt: trigger.nextRunAt,
141
+ actionConfigJson: JSON.stringify(actionConfig),
142
+ updatedAt,
143
+ lastError: null
144
+ });
145
+ return this.toTaskView(updated, input.userId);
146
+ }
147
+ cancelTask(taskId, userId) {
148
+ this.butlerProfileService.ensureInitialized();
149
+ const current = this.requireTask(taskId);
150
+ const cancelledAt = nowIso();
151
+ const updated = this.taskRepository.update({
152
+ ...current,
153
+ status: "cancelled",
154
+ updatedAt: cancelledAt,
155
+ cancelledAt,
156
+ nextRunAt: null
157
+ });
158
+ return this.toTaskView(updated, userId);
159
+ }
160
+ skipCurrentWait(taskId, userId) {
161
+ this.butlerProfileService.ensureInitialized();
162
+ const current = this.requireTask(taskId);
163
+ if (current.status !== "active" || !current.nextRunAt) {
164
+ throw new AppError({
165
+ statusCode: 409,
166
+ errorCode: "ASSISTANT_AUTOMATION_WAIT_NOT_ACTIVE",
167
+ detail: "当前自动化没有可取消的等待"
168
+ });
169
+ }
170
+ if (current.triggerType === "once") {
171
+ throw new AppError({
172
+ statusCode: 409,
173
+ errorCode: "ASSISTANT_AUTOMATION_WAIT_SKIP_UNSUPPORTED",
174
+ detail: "单次自动化不支持只取消本次等待"
175
+ });
176
+ }
177
+ const referenceAt = nowIso();
178
+ const triggerConfig = parseTriggerConfig(current.triggerType, current.triggerConfigJson);
179
+ const nextReferenceAt = current.nextRunAt > referenceAt ? current.nextRunAt : referenceAt;
180
+ const nextRunAt = computeNextRunAt(triggerConfig, nextReferenceAt);
181
+ const updatedAt = referenceAt;
182
+ this.runRepository.create({
183
+ id: createId(),
184
+ automationId: current.id,
185
+ runSeq: this.runRepository.getLatestSeq(current.id) + 1,
186
+ triggerType: current.triggerType,
187
+ triggerSnapshotJson: current.triggerConfigJson,
188
+ actionType: current.actionType,
189
+ actionSnapshotJson: current.actionConfigJson,
190
+ status: "cancelled",
191
+ summary: "已手动取消本次等待,保留自动化并重新安排下一次运行。",
192
+ error: null,
193
+ scheduledAt: current.nextRunAt,
194
+ startedAt: updatedAt,
195
+ finishedAt: updatedAt,
196
+ createdAt: updatedAt
197
+ });
198
+ const updated = this.taskRepository.update({
199
+ ...current,
200
+ status: nextRunAt === null ? "completed" : "active",
201
+ nextRunAt,
202
+ lastError: null,
203
+ updatedAt
204
+ });
205
+ return this.toTaskView(updated, userId);
206
+ }
207
+ async runDueTasks(referenceAt) {
208
+ this.butlerProfileService.ensureInitialized();
209
+ return await this.taskManager.enqueue(HOST_TASK_TYPES.assistantAutomationTick, {
210
+ key: "global",
211
+ source: "assistant_automation.run_due_tasks",
212
+ input: {
213
+ referenceAt
214
+ }
215
+ }).promise;
216
+ }
217
+ registerBackgroundTasks() {
218
+ if (!this.taskManager.has(HOST_TASK_TYPES.assistantAutomationTick)) {
219
+ this.taskManager.register({
220
+ taskType: HOST_TASK_TYPES.assistantAutomationTick,
221
+ executionLane: "host_background",
222
+ timeoutMs: 10_000,
223
+ run: async ({ referenceAt }) => await this.runDueTasksDirect(referenceAt)
224
+ });
225
+ }
226
+ if (!this.taskManager.has(HOST_TASK_TYPES.assistantAutomationEvaluate)) {
227
+ this.taskManager.register({
228
+ taskType: HOST_TASK_TYPES.assistantAutomationEvaluate,
229
+ executionLane: "host_background",
230
+ timeoutMs: 20_000,
231
+ run: async ({ automationId, referenceAt }) => {
232
+ await this.evaluateTask(automationId, referenceAt);
233
+ }
234
+ });
235
+ }
236
+ }
237
+ async runDueTasksDirect(referenceAt) {
238
+ this.reactivatePausedTasks(referenceAt);
239
+ const activeTaskCount = this.taskRepository.list({
240
+ statuses: ["active"]
241
+ }).length;
242
+ const dueTasks = this.taskRepository.listDueActive(referenceAt, DEFAULT_DUE_TASK_LIMIT);
243
+ const handles = dueTasks.map((task) => this.taskManager.enqueue(HOST_TASK_TYPES.assistantAutomationEvaluate, {
244
+ key: task.id,
245
+ source: "assistant_automation.tick.evaluate",
246
+ input: {
247
+ automationId: task.id,
248
+ referenceAt
249
+ }
250
+ }));
251
+ await Promise.all(handles.map((handle) => handle.promise));
252
+ return {
253
+ activeTaskCount,
254
+ dueTaskCount: dueTasks.length,
255
+ processedTaskCount: dueTasks.length,
256
+ idle: dueTasks.length === 0
257
+ };
258
+ }
259
+ reactivatePausedTasks(referenceAt) {
260
+ const pausedTasks = this.taskRepository.listDuePaused(referenceAt, DEFAULT_DUE_TASK_LIMIT);
261
+ for (const task of pausedTasks) {
262
+ const triggerConfig = parseTriggerConfig(task.triggerType, task.triggerConfigJson);
263
+ const nextRunAt = computeNextRunAt(triggerConfig, referenceAt);
264
+ this.taskRepository.update({
265
+ ...task,
266
+ status: nextRunAt ? "active" : "completed",
267
+ nextRunAt,
268
+ lastError: null,
269
+ updatedAt: referenceAt
270
+ });
271
+ }
272
+ }
273
+ async evaluateTask(automationId, referenceAt) {
274
+ const task = this.reconcileTaskWithLatestRun(this.requireTask(automationId), referenceAt);
275
+ if (!task || task.status !== "active" || !task.nextRunAt || task.nextRunAt > referenceAt) {
276
+ return;
277
+ }
278
+ await this.processDueTask(task, referenceAt);
279
+ }
280
+ async processDueTask(task, referenceAt) {
281
+ const prepared = await this.prepareDueTask(task, referenceAt);
282
+ if (prepared.kind === "skip") {
283
+ this.taskRepository.update(prepared.task);
284
+ return;
285
+ }
286
+ const run = this.runRepository.create({
287
+ id: createId(),
288
+ automationId: task.id,
289
+ runSeq: this.runRepository.getLatestSeq(task.id) + 1,
290
+ triggerType: task.triggerType,
291
+ triggerSnapshotJson: prepared.triggerSnapshotJson,
292
+ actionType: task.actionType,
293
+ actionSnapshotJson: task.actionConfigJson,
294
+ status: "running",
295
+ summary: null,
296
+ error: null,
297
+ scheduledAt: prepared.scheduledAt,
298
+ startedAt: referenceAt,
299
+ finishedAt: null,
300
+ createdAt: referenceAt
301
+ });
302
+ try {
303
+ const result = await this.butlerControlSessionService.sendMessage(task.userId, {
304
+ controlSessionId: task.controlSessionId,
305
+ content: prepared.messageContent,
306
+ clientRequestId: buildAutomationClientRequestId(task.id, prepared.scheduledAt)
307
+ });
308
+ const summary = summarizeMessage(prepared.messageContent);
309
+ const finishedRun = this.runRepository.update({
310
+ ...run,
311
+ status: "succeeded",
312
+ summary,
313
+ error: null,
314
+ finishedAt: result.acceptedAt
315
+ });
316
+ this.taskRepository.update(prepared.finalizeSuccess(result.acceptedAt, finishedRun.summary ?? summary));
317
+ }
318
+ catch (error) {
319
+ const usageLimitBlocked = readProviderUsageLimitErrorData(error instanceof AppError ? error.data : undefined);
320
+ if (usageLimitBlocked?.blockedUntil) {
321
+ const summary = `${usageLimitBlocked.sourceLabel?.trim() || "当前控制会话"}检测到 provider 套餐限额,已顺延到 ${usageLimitBlocked.blockedUntil} 后再继续。`;
322
+ this.runRepository.update({
323
+ ...run,
324
+ status: "skipped",
325
+ summary,
326
+ error: null,
327
+ finishedAt: referenceAt
328
+ });
329
+ this.taskRepository.update(this.buildUsageLimitDeferredTask(task, prepared, referenceAt, usageLimitBlocked.blockedUntil, usageLimitBlocked.sourceLabel));
330
+ return;
331
+ }
332
+ const finishedAt = nowIso();
333
+ const errorMessage = error instanceof Error ? error.message : String(error);
334
+ this.runRepository.update({
335
+ ...run,
336
+ status: "failed",
337
+ summary: null,
338
+ error: errorMessage,
339
+ finishedAt
340
+ });
341
+ this.taskRepository.update(prepared.finalizeFailure(finishedAt, errorMessage));
342
+ }
343
+ }
344
+ async prepareDueTask(task, referenceAt) {
345
+ const actionConfig = parseActionConfig(task.actionConfigJson);
346
+ const triggerConfig = parseTriggerConfig(task.triggerType, task.triggerConfigJson);
347
+ const scheduledAt = task.nextRunAt ?? referenceAt;
348
+ if (triggerConfig.type === "condition") {
349
+ return await this.prepareConditionTask(task, triggerConfig, actionConfig, referenceAt, scheduledAt);
350
+ }
351
+ const messageContent = actionConfig.content;
352
+ const triggerSnapshotJson = JSON.stringify(triggerConfig);
353
+ return {
354
+ kind: "run",
355
+ task,
356
+ scheduledAt,
357
+ triggerSnapshotJson,
358
+ actionConfig,
359
+ messageContent,
360
+ finalizeSuccess: (finishedAt, summary) => this.finalizeSuccessfulTask(task, triggerConfig, finishedAt, summary),
361
+ finalizeFailure: (finishedAt, errorMessage) => ({
362
+ ...task,
363
+ status: "failed",
364
+ nextRunAt: null,
365
+ lastRunAt: finishedAt,
366
+ lastError: errorMessage,
367
+ updatedAt: finishedAt
368
+ })
369
+ };
370
+ }
371
+ async prepareConditionTask(task, triggerConfig, actionConfig, referenceAt, scheduledAt) {
372
+ const currentState = parseConditionState(triggerConfig);
373
+ if (shouldCompleteConditionWithoutCheck(triggerConfig, currentState, referenceAt)) {
374
+ return {
375
+ kind: "skip",
376
+ task: {
377
+ ...task,
378
+ status: "completed",
379
+ nextRunAt: null,
380
+ updatedAt: referenceAt,
381
+ lastError: null
382
+ }
383
+ };
384
+ }
385
+ try {
386
+ if (triggerConfig.conditionKind === "git.remote_tag_changed") {
387
+ return await this.prepareGitRemoteTagChangedTask(task, triggerConfig, currentState, actionConfig, referenceAt, scheduledAt);
388
+ }
389
+ return await this.prepareSessionRuntimeIdleTask(task, triggerConfig, currentState, actionConfig, referenceAt, scheduledAt);
390
+ }
391
+ catch (error) {
392
+ const errorMessage = error instanceof Error ? error.message : String(error);
393
+ const nextState = bumpConditionStateOnError(triggerConfig.conditionKind, currentState, referenceAt);
394
+ const nextTask = this.buildConditionSkippedTask(task, triggerConfig, nextState, referenceAt, errorMessage);
395
+ return {
396
+ kind: "skip",
397
+ task: nextTask
398
+ };
399
+ }
400
+ }
401
+ async prepareGitRemoteTagChangedTask(task, triggerConfig, state, actionConfig, referenceAt, scheduledAt) {
402
+ const latest = await this.readLatestRemoteTag(state.repositoryUrl);
403
+ const nextState = {
404
+ ...state,
405
+ latestTag: latest.tag,
406
+ latestRef: latest.ref,
407
+ checkCount: state.checkCount + 1,
408
+ lastCheckedAt: referenceAt
409
+ };
410
+ const baselineMissing = !state.latestTag && !state.latestRef;
411
+ const matched = !baselineMissing
412
+ && (state.latestTag !== latest.tag || state.latestRef !== latest.ref);
413
+ if (!matched) {
414
+ return {
415
+ kind: "skip",
416
+ task: this.buildConditionSkippedTask(task, triggerConfig, nextState, referenceAt, null)
417
+ };
418
+ }
419
+ const nextTriggerConfig = buildConditionTriggerConfig(triggerConfig, nextState);
420
+ const triggerContext = {
421
+ conditionKind: triggerConfig.conditionKind,
422
+ repositoryUrl: state.repositoryUrl,
423
+ previousTag: state.latestTag,
424
+ previousRef: state.latestRef,
425
+ currentTag: latest.tag,
426
+ currentRef: latest.ref,
427
+ checkedAt: referenceAt
428
+ };
429
+ const messageContent = mergeTriggerContext(actionConfig.content, actionConfig.includeTriggerContext, buildGitTagChangedContextMessage(triggerContext));
430
+ return {
431
+ kind: "run",
432
+ task,
433
+ scheduledAt,
434
+ triggerSnapshotJson: JSON.stringify({
435
+ ...nextTriggerConfig,
436
+ triggerContext
437
+ }),
438
+ actionConfig,
439
+ messageContent,
440
+ finalizeSuccess: (finishedAt, summary) => ({
441
+ ...task,
442
+ triggerConfigJson: JSON.stringify(nextTriggerConfig),
443
+ status: "completed",
444
+ nextRunAt: null,
445
+ lastRunAt: finishedAt,
446
+ lastRunSummary: summary,
447
+ lastError: null,
448
+ updatedAt: finishedAt
449
+ }),
450
+ finalizeFailure: (finishedAt, errorMessage) => ({
451
+ ...task,
452
+ triggerConfigJson: JSON.stringify(nextTriggerConfig),
453
+ status: "failed",
454
+ nextRunAt: null,
455
+ lastRunAt: finishedAt,
456
+ lastError: errorMessage,
457
+ updatedAt: finishedAt
458
+ })
459
+ };
460
+ }
461
+ async prepareSessionRuntimeIdleTask(task, triggerConfig, state, actionConfig, referenceAt, scheduledAt) {
462
+ if (!this.sessionLiveRuntimeService) {
463
+ throw new AppError({
464
+ statusCode: 500,
465
+ errorCode: "ASSISTANT_AUTOMATION_CONDITION_UNSUPPORTED",
466
+ detail: "当前环境未配置 session runtime 能力,无法检查 session.runtime_idle"
467
+ });
468
+ }
469
+ const runtime = await this.sessionLiveRuntimeService.getSessionRuntime(state.sessionId, task.userId);
470
+ const nextState = {
471
+ ...state,
472
+ lastObservedRunningState: normalizeNullableText(String(runtime.runningState)),
473
+ lastHasActiveRun: runtime.hasActiveRun,
474
+ checkCount: state.checkCount + 1,
475
+ lastCheckedAt: referenceAt
476
+ };
477
+ const baselineMissing = state.lastHasActiveRun === null && !state.lastObservedRunningState;
478
+ const matched = !baselineMissing
479
+ && state.lastHasActiveRun === true
480
+ && runtime.hasActiveRun === false;
481
+ if (!matched) {
482
+ return {
483
+ kind: "skip",
484
+ task: this.buildConditionSkippedTask(task, triggerConfig, nextState, referenceAt, null)
485
+ };
486
+ }
487
+ const nextTriggerConfig = buildConditionTriggerConfig(triggerConfig, nextState);
488
+ const triggerContext = {
489
+ conditionKind: triggerConfig.conditionKind,
490
+ sessionId: state.sessionId,
491
+ previousRunningState: state.lastObservedRunningState,
492
+ previousHasActiveRun: state.lastHasActiveRun,
493
+ currentRunningState: String(runtime.runningState),
494
+ currentHasActiveRun: runtime.hasActiveRun,
495
+ checkedAt: referenceAt
496
+ };
497
+ const messageContent = mergeTriggerContext(actionConfig.content, actionConfig.includeTriggerContext, buildSessionRuntimeIdleContextMessage(triggerContext));
498
+ return {
499
+ kind: "run",
500
+ task,
501
+ scheduledAt,
502
+ triggerSnapshotJson: JSON.stringify({
503
+ ...nextTriggerConfig,
504
+ triggerContext
505
+ }),
506
+ actionConfig,
507
+ messageContent,
508
+ finalizeSuccess: (finishedAt, summary) => ({
509
+ ...task,
510
+ triggerConfigJson: JSON.stringify(nextTriggerConfig),
511
+ status: "completed",
512
+ nextRunAt: null,
513
+ lastRunAt: finishedAt,
514
+ lastRunSummary: summary,
515
+ lastError: null,
516
+ updatedAt: finishedAt
517
+ }),
518
+ finalizeFailure: (finishedAt, errorMessage) => ({
519
+ ...task,
520
+ triggerConfigJson: JSON.stringify(nextTriggerConfig),
521
+ status: "failed",
522
+ nextRunAt: null,
523
+ lastRunAt: finishedAt,
524
+ lastError: errorMessage,
525
+ updatedAt: finishedAt
526
+ })
527
+ };
528
+ }
529
+ buildConditionSkippedTask(task, triggerConfig, nextState, referenceAt, lastError) {
530
+ const nextTriggerConfig = buildConditionTriggerConfig(triggerConfig, nextState);
531
+ const exhaustedByCount = triggerConfig.maxChecks !== null && nextState.checkCount >= triggerConfig.maxChecks;
532
+ const nextRunAt = exhaustedByCount ? null : computeNextRunAt(nextTriggerConfig, referenceAt);
533
+ const completed = nextRunAt === null;
534
+ return {
535
+ ...task,
536
+ triggerConfigJson: JSON.stringify(nextTriggerConfig),
537
+ status: completed ? "completed" : "active",
538
+ nextRunAt,
539
+ lastError,
540
+ updatedAt: referenceAt
541
+ };
542
+ }
543
+ finalizeSuccessfulTask(task, triggerConfig, finishedAt, summary) {
544
+ const nextRunAt = computeNextRunAt(triggerConfig, finishedAt);
545
+ const completed = triggerConfig.type === "once" || nextRunAt === null;
546
+ return {
547
+ ...task,
548
+ status: completed ? "completed" : "active",
549
+ nextRunAt,
550
+ lastRunAt: finishedAt,
551
+ lastRunSummary: summary,
552
+ lastError: null,
553
+ updatedAt: finishedAt
554
+ };
555
+ }
556
+ buildUsageLimitDeferredTask(task, prepared, referenceAt, blockedUntil, sourceLabel) {
557
+ const effectiveLabel = sourceLabel?.trim()
558
+ || (prepared.actionConfig.targetSessionId?.trim()
559
+ ? `目标会话 ${prepared.actionConfig.targetSessionId.trim()}`
560
+ : "当前控制会话");
561
+ const summary = `${effectiveLabel}检测到 provider 套餐限额,系统会在 ${blockedUntil} 后自动继续。`;
562
+ const nextStatus = task.triggerType === "once" ? "active" : "paused";
563
+ return {
564
+ ...task,
565
+ status: nextStatus,
566
+ nextRunAt: blockedUntil,
567
+ lastRunAt: referenceAt,
568
+ lastRunSummary: summary,
569
+ lastError: null,
570
+ updatedAt: referenceAt
571
+ };
572
+ }
573
+ requireTask(taskId) {
574
+ const task = this.taskRepository.findById(taskId.trim());
575
+ if (!task) {
576
+ throw new AppError({
577
+ statusCode: 404,
578
+ errorCode: "ASSISTANT_AUTOMATION_NOT_FOUND",
579
+ detail: "未找到对应的助手自动化任务"
580
+ });
581
+ }
582
+ return task;
583
+ }
584
+ buildUpdatedTrigger(task, currentTriggerConfig, input, referenceAt) {
585
+ switch (currentTriggerConfig.type) {
586
+ case "once": {
587
+ const nextDueAt = input.dueAt !== undefined
588
+ ? requireIsoTimestamp(input.dueAt, "dueAt")
589
+ : currentTriggerConfig.dueAt;
590
+ return {
591
+ triggerConfigJson: JSON.stringify({
592
+ type: "once",
593
+ dueAt: nextDueAt
594
+ }),
595
+ nextRunAt: nextDueAt
596
+ };
597
+ }
598
+ case "interval": {
599
+ const nextTrigger = createTriggerConfig({
600
+ type: "interval",
601
+ seconds: input.everySeconds !== undefined ? input.everySeconds : currentTriggerConfig.seconds,
602
+ minutes: input.everyMinutes !== undefined ? input.everyMinutes : currentTriggerConfig.minutes,
603
+ hours: input.everyHours !== undefined ? input.everyHours : currentTriggerConfig.hours,
604
+ stopAt: input.stopAt !== undefined ? input.stopAt : currentTriggerConfig.stopAt
605
+ }, referenceAt);
606
+ return {
607
+ triggerConfigJson: nextTrigger.triggerConfigJson,
608
+ nextRunAt: nextTrigger.nextRunAt
609
+ };
610
+ }
611
+ case "cron": {
612
+ const nextTrigger = createTriggerConfig({
613
+ type: "cron",
614
+ minute: input.cronMinute !== undefined ? input.cronMinute : currentTriggerConfig.minute,
615
+ hour: input.cronHour !== undefined ? input.cronHour : currentTriggerConfig.hour,
616
+ daysOfWeek: input.cronDaysOfWeek !== undefined
617
+ ? input.cronDaysOfWeek
618
+ : currentTriggerConfig.daysOfWeek,
619
+ stopAt: input.stopAt !== undefined ? input.stopAt : currentTriggerConfig.stopAt
620
+ }, referenceAt);
621
+ return {
622
+ triggerConfigJson: nextTrigger.triggerConfigJson,
623
+ nextRunAt: nextTrigger.nextRunAt
624
+ };
625
+ }
626
+ case "condition": {
627
+ const nextTriggerConfig = {
628
+ ...currentTriggerConfig,
629
+ pollIntervalSeconds: input.pollIntervalSeconds !== undefined
630
+ ? input.pollIntervalSeconds || currentTriggerConfig.pollIntervalSeconds
631
+ : currentTriggerConfig.pollIntervalSeconds,
632
+ expiresAt: input.expiresAt !== undefined
633
+ ? input.expiresAt
634
+ : currentTriggerConfig.expiresAt,
635
+ maxChecks: input.maxChecks !== undefined
636
+ ? input.maxChecks
637
+ : currentTriggerConfig.maxChecks
638
+ };
639
+ return {
640
+ triggerConfigJson: JSON.stringify(nextTriggerConfig),
641
+ nextRunAt: computeNextRunAt(nextTriggerConfig, referenceAt)
642
+ };
643
+ }
644
+ default:
645
+ return assertNeverTriggerConfig(currentTriggerConfig);
646
+ }
647
+ }
648
+ reconcileTaskWithLatestRun(task, referenceAt) {
649
+ if (task.status !== "active" || !task.nextRunAt) {
650
+ return task;
651
+ }
652
+ const latestRun = this.runRepository.findLatestByAutomation(task.id);
653
+ if (!latestRun || latestRun.scheduledAt !== task.nextRunAt) {
654
+ return task;
655
+ }
656
+ const triggerConfig = parseTriggerConfig(task.triggerType, task.triggerConfigJson);
657
+ if (latestRun.status === "succeeded") {
658
+ const reconciled = this.finalizeSuccessfulTask(task, triggerConfig, latestRun.finishedAt ?? latestRun.startedAt ?? referenceAt, latestRun.summary ?? summarizeMessage(parseActionConfig(task.actionConfigJson).content));
659
+ this.taskRepository.update(reconciled);
660
+ return null;
661
+ }
662
+ if (latestRun.status === "failed") {
663
+ this.taskRepository.update({
664
+ ...task,
665
+ status: "failed",
666
+ nextRunAt: null,
667
+ lastRunAt: latestRun.finishedAt ?? latestRun.startedAt,
668
+ lastRunSummary: latestRun.summary,
669
+ lastError: latestRun.error ?? "ASSISTANT_AUTOMATION_RUN_FAILED",
670
+ updatedAt: latestRun.finishedAt ?? referenceAt
671
+ });
672
+ return null;
673
+ }
674
+ if (latestRun.status === "running") {
675
+ this.runRepository.update({
676
+ ...latestRun,
677
+ status: "failed",
678
+ error: latestRun.error ?? "ASSISTANT_AUTOMATION_RUN_INTERRUPTED",
679
+ finishedAt: referenceAt
680
+ });
681
+ }
682
+ return this.requireTask(task.id);
683
+ }
684
+ async readLatestRemoteTag(repositoryUrl) {
685
+ if (!this.gitCommandRunner) {
686
+ throw new AppError({
687
+ statusCode: 500,
688
+ errorCode: "ASSISTANT_AUTOMATION_CONDITION_UNSUPPORTED",
689
+ detail: "当前环境未配置 git 能力,无法检查 git.remote_tag_changed"
690
+ });
691
+ }
692
+ const result = await this.gitCommandRunner.run(this.gitWorkingDirectory, ["ls-remote", "--refs", "--tags", "--sort=-v:refname", repositoryUrl], {
693
+ timeoutMs: 15_000,
694
+ allowNonZeroExit: false,
695
+ operation: "assistant_automation_git_remote_tag_changed"
696
+ });
697
+ const firstLine = result.stdout
698
+ .split(/\r?\n/)
699
+ .map((line) => line.trim())
700
+ .find((line) => line.length > 0);
701
+ if (!firstLine) {
702
+ return {
703
+ tag: null,
704
+ ref: null
705
+ };
706
+ }
707
+ const [ref, fullName] = firstLine.split(/\s+/, 2);
708
+ return {
709
+ tag: fullName?.replace(/^refs\/tags\//, "") || null,
710
+ ref: ref?.trim() || null
711
+ };
712
+ }
713
+ toTaskView(record, userId) {
714
+ return {
715
+ ...record,
716
+ controlSession: this.butlerControlSessionService.getSession(record.controlSessionId, userId),
717
+ triggerConfig: parseTriggerConfig(record.triggerType, record.triggerConfigJson),
718
+ actionConfig: parseActionConfig(record.actionConfigJson)
719
+ };
720
+ }
721
+ toRunView(record) {
722
+ const triggerSnapshot = parseTriggerConfig(record.triggerType, record.triggerSnapshotJson);
723
+ const parsedSnapshot = tryParseJson(record.triggerSnapshotJson);
724
+ if (parsedSnapshot?.triggerContext && typeof parsedSnapshot.triggerContext === "object") {
725
+ triggerSnapshot.triggerContext = parsedSnapshot.triggerContext;
726
+ }
727
+ return {
728
+ ...record,
729
+ triggerSnapshot,
730
+ actionSnapshot: parseActionConfig(record.actionSnapshotJson)
731
+ };
732
+ }
733
+ }
734
+ function requireContent(value) {
735
+ const normalized = value.trim();
736
+ if (!normalized) {
737
+ throw new AppError({
738
+ statusCode: 400,
739
+ errorCode: "INVALID_INPUT",
740
+ detail: "创建助手自动化必须提供 content",
741
+ field: "content"
742
+ });
743
+ }
744
+ return normalized;
745
+ }
746
+ function requireIsoTimestamp(value, field) {
747
+ const normalized = normalizeNullableText(value);
748
+ if (!normalized) {
749
+ throw new AppError({
750
+ statusCode: 400,
751
+ errorCode: "INVALID_INPUT",
752
+ detail: `${field} 必须是合法的 ISO 时间`,
753
+ field
754
+ });
755
+ }
756
+ const timestamp = Date.parse(normalized);
757
+ if (Number.isNaN(timestamp)) {
758
+ throw new AppError({
759
+ statusCode: 400,
760
+ errorCode: "INVALID_INPUT",
761
+ detail: `${field} 必须是合法的 ISO 时间`,
762
+ field
763
+ });
764
+ }
765
+ return new Date(timestamp).toISOString();
766
+ }
767
+ function assertNeverTriggerConfig(value) {
768
+ throw new Error(`Unsupported trigger config: ${JSON.stringify(value)}`);
769
+ }
770
+ function normalizeNullableText(value) {
771
+ const normalized = value?.trim();
772
+ return normalized ? normalized : null;
773
+ }
774
+ function buildAutomationClientRequestId(taskId, referenceAt) {
775
+ return `assistant-automation:${taskId}:${Date.parse(referenceAt) || Date.now()}`;
776
+ }
777
+ function summarizeMessage(content) {
778
+ return content.length > 120 ? `${content.slice(0, 117)}...` : content;
779
+ }
780
+ function shouldCompleteConditionWithoutCheck(config, state, referenceAt) {
781
+ if (config.maxChecks !== null && state.checkCount >= config.maxChecks) {
782
+ return true;
783
+ }
784
+ return config.expiresAt !== null && referenceAt > config.expiresAt;
785
+ }
786
+ function bumpConditionStateOnError(conditionKind, state, referenceAt) {
787
+ if (conditionKind === "git.remote_tag_changed") {
788
+ return {
789
+ ...state,
790
+ checkCount: state.checkCount + 1,
791
+ lastCheckedAt: referenceAt
792
+ };
793
+ }
794
+ return {
795
+ ...state,
796
+ checkCount: state.checkCount + 1,
797
+ lastCheckedAt: referenceAt
798
+ };
799
+ }
800
+ function mergeTriggerContext(content, includeTriggerContext, triggerContext) {
801
+ return includeTriggerContext ? `${triggerContext}\n\n${content}` : content;
802
+ }
803
+ function buildGitTagChangedContextMessage(context) {
804
+ return [
805
+ "触发条件:远端仓库出现新 tag",
806
+ `仓库:${context.repositoryUrl}`,
807
+ `旧基线:${context.previousTag ?? "-"} @ ${context.previousRef ?? "-"}`,
808
+ `新状态:${context.currentTag ?? "-"} @ ${context.currentRef ?? "-"}`,
809
+ `检查时间:${context.checkedAt}`
810
+ ].join("\n");
811
+ }
812
+ function buildSessionRuntimeIdleContextMessage(context) {
813
+ return [
814
+ "触发条件:目标会话已进入空闲状态",
815
+ `会话:${context.sessionId}`,
816
+ `上一轮状态:${context.previousRunningState ?? "-"} / hasActiveRun=${String(context.previousHasActiveRun)}`,
817
+ `当前状态:${context.currentRunningState ?? "-"} / hasActiveRun=${String(context.currentHasActiveRun)}`,
818
+ `检查时间:${context.checkedAt}`
819
+ ].join("\n");
820
+ }
821
+ function tryParseJson(value) {
822
+ try {
823
+ const parsed = JSON.parse(value);
824
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed)
825
+ ? parsed
826
+ : null;
827
+ }
828
+ catch {
829
+ return null;
830
+ }
831
+ }
832
+ //# sourceMappingURL=assistant-automation-service.js.map