@meetquinn/animactl 0.1.2 → 0.1.3

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 (289) hide show
  1. package/README.md +11 -6
  2. package/dist/server/{runtime/activity-payload.d.ts → activities/format.d.ts} +4 -1
  3. package/dist/server/activities/format.d.ts.map +1 -0
  4. package/dist/server/{runtime/activity-payload.js → activities/format.js} +16 -1
  5. package/dist/server/agents/agent-skills.d.ts +7 -3
  6. package/dist/server/agents/agent-skills.d.ts.map +1 -1
  7. package/dist/server/agents/agent-skills.js +243 -38
  8. package/dist/server/agents/agent-slack.service.d.ts +15 -0
  9. package/dist/server/agents/agent-slack.service.d.ts.map +1 -1
  10. package/dist/server/agents/agent-slack.service.js +43 -6
  11. package/dist/server/agents/default-skills.d.ts +9 -0
  12. package/dist/server/agents/default-skills.d.ts.map +1 -0
  13. package/dist/server/agents/default-skills.js +52 -0
  14. package/dist/server/cli/runtime-cli.d.ts +7 -1
  15. package/dist/server/cli/runtime-cli.d.ts.map +1 -1
  16. package/dist/server/cli/runtime-cli.js +107 -3
  17. package/dist/server/cli/services-cli.d.ts.map +1 -1
  18. package/dist/server/cli/services-cli.js +39 -0
  19. package/dist/server/inbox/slack-subscriber.d.ts +2 -0
  20. package/dist/server/inbox/slack-subscriber.d.ts.map +1 -1
  21. package/dist/server/inbox/slack-subscriber.js +28 -2
  22. package/dist/server/inbox/slack-subscription.service.d.ts.map +1 -1
  23. package/dist/server/inbox/slack-subscription.service.js +13 -1
  24. package/dist/server/inbox/wake-queue.service.d.ts +3 -1
  25. package/dist/server/inbox/wake-queue.service.d.ts.map +1 -1
  26. package/dist/server/inbox/wake-queue.service.js +5 -3
  27. package/dist/server/provider-usage/http.d.ts +1 -0
  28. package/dist/server/provider-usage/http.d.ts.map +1 -1
  29. package/dist/server/provider-usage/http.js +23 -1
  30. package/dist/server/provider-usage/provider-usage.service.d.ts +1 -4
  31. package/dist/server/provider-usage/provider-usage.service.d.ts.map +1 -1
  32. package/dist/server/provider-usage/provider-usage.service.js +1 -18
  33. package/dist/server/provider-usage/providers/claude.d.ts +1 -1
  34. package/dist/server/provider-usage/providers/claude.d.ts.map +1 -1
  35. package/dist/server/provider-usage/providers/claude.js +1 -1
  36. package/dist/server/provider-usage/providers/codex.d.ts +1 -1
  37. package/dist/server/provider-usage/providers/codex.d.ts.map +1 -1
  38. package/dist/server/provider-usage/providers/codex.js +1 -1
  39. package/dist/server/provider-usage/providers/kimi.d.ts +1 -1
  40. package/dist/server/provider-usage/providers/kimi.d.ts.map +1 -1
  41. package/dist/server/provider-usage/providers/kimi.js +4 -4
  42. package/dist/server/provider-usage/result.d.ts +5 -0
  43. package/dist/server/provider-usage/result.d.ts.map +1 -0
  44. package/dist/server/provider-usage/result.js +18 -0
  45. package/dist/server/providers/active-runtime.d.ts +1 -1
  46. package/dist/server/providers/active-runtime.d.ts.map +1 -1
  47. package/dist/server/providers/claude-events.d.ts +1 -1
  48. package/dist/server/providers/claude-events.d.ts.map +1 -1
  49. package/dist/server/providers/claude-events.js +2 -2
  50. package/dist/server/providers/claude.d.ts +1 -1
  51. package/dist/server/providers/claude.d.ts.map +1 -1
  52. package/dist/server/providers/claude.js +2 -2
  53. package/dist/server/providers/codex-app-server.d.ts +1 -1
  54. package/dist/server/providers/codex-app-server.d.ts.map +1 -1
  55. package/dist/server/providers/codex-app-server.js +1 -1
  56. package/dist/server/providers/codex-events.js +1 -1
  57. package/dist/server/providers/codex.d.ts +1 -1
  58. package/dist/server/providers/codex.d.ts.map +1 -1
  59. package/dist/server/providers/codex.js +2 -2
  60. package/dist/server/{runtime/provider-contract.d.ts → providers/contract.d.ts} +1 -1
  61. package/dist/server/providers/contract.d.ts.map +1 -0
  62. package/dist/server/providers/factory.d.ts +1 -1
  63. package/dist/server/providers/factory.d.ts.map +1 -1
  64. package/dist/server/providers/kimi-events.d.ts +1 -1
  65. package/dist/server/providers/kimi-events.d.ts.map +1 -1
  66. package/dist/server/providers/kimi-events.js +1 -1
  67. package/dist/server/providers/kimi.d.ts +1 -1
  68. package/dist/server/providers/kimi.d.ts.map +1 -1
  69. package/dist/server/providers/kimi.js +3 -2
  70. package/dist/server/providers/reasoning-events.js +1 -1
  71. package/dist/server/runtime/active-run-control.d.ts +19 -0
  72. package/dist/server/runtime/active-run-control.d.ts.map +1 -0
  73. package/dist/server/runtime/active-run-control.js +89 -0
  74. package/dist/server/runtime/activity.js +1 -1
  75. package/dist/server/runtime/agent-runner.d.ts +1 -1
  76. package/dist/server/runtime/agent-runner.d.ts.map +1 -1
  77. package/dist/server/runtime/delivery-prompt.d.ts +6 -0
  78. package/dist/server/runtime/delivery-prompt.d.ts.map +1 -1
  79. package/dist/server/runtime/delivery-prompt.js +53 -34
  80. package/dist/server/runtime/followup-appender.d.ts +20 -0
  81. package/dist/server/runtime/followup-appender.d.ts.map +1 -0
  82. package/dist/server/runtime/followup-appender.js +128 -0
  83. package/dist/server/runtime/host.d.ts +2 -0
  84. package/dist/server/runtime/host.d.ts.map +1 -1
  85. package/dist/server/runtime/host.js +8 -0
  86. package/dist/server/runtime/provider-runner.d.ts +16 -0
  87. package/dist/server/runtime/provider-runner.d.ts.map +1 -0
  88. package/dist/server/runtime/provider-runner.js +86 -0
  89. package/dist/server/runtime/runtime-bridge.d.ts +1 -1
  90. package/dist/server/runtime/runtime-bridge.d.ts.map +1 -1
  91. package/dist/server/runtime/runtime-session.service.d.ts +1 -1
  92. package/dist/server/runtime/runtime-session.service.d.ts.map +1 -1
  93. package/dist/server/runtime/runtime-session.service.js +1 -1
  94. package/dist/server/runtime/runtime-worker.d.ts +2 -10
  95. package/dist/server/runtime/runtime-worker.d.ts.map +1 -1
  96. package/dist/server/runtime/runtime-worker.js +60 -286
  97. package/dist/server/runtime-management/managed-runtime.d.ts.map +1 -0
  98. package/dist/server/runtime-management/runtime-release.d.ts.map +1 -0
  99. package/dist/server/{runtime → runtime-management}/runtime-upgrade.d.ts +1 -0
  100. package/dist/server/runtime-management/runtime-upgrade.d.ts.map +1 -0
  101. package/dist/server/{runtime → runtime-management}/runtime-upgrade.js +14 -0
  102. package/dist/server/services/system.service.d.ts +41 -0
  103. package/dist/server/services/system.service.d.ts.map +1 -0
  104. package/dist/server/services/system.service.js +154 -0
  105. package/dist/server/settings/settings.service.d.ts +2 -1
  106. package/dist/server/settings/settings.service.d.ts.map +1 -1
  107. package/dist/server/settings/settings.service.js +9 -1
  108. package/dist/server/slack/shortcuts.d.ts +0 -3
  109. package/dist/server/slack/shortcuts.d.ts.map +1 -1
  110. package/dist/server/slack/shortcuts.js +0 -3
  111. package/dist/server/slack-interactions/shortcut-ids.d.ts +4 -0
  112. package/dist/server/slack-interactions/shortcut-ids.d.ts.map +1 -0
  113. package/dist/server/slack-interactions/shortcut-ids.js +3 -0
  114. package/dist/server/slack-interactions/shortcut-views.d.ts +65 -0
  115. package/dist/server/slack-interactions/shortcut-views.d.ts.map +1 -0
  116. package/dist/server/slack-interactions/shortcut-views.js +211 -0
  117. package/dist/server/{slack → slack-interactions}/shortcut.service.d.ts +2 -47
  118. package/dist/server/slack-interactions/shortcut.service.d.ts.map +1 -0
  119. package/dist/server/slack-interactions/shortcut.service.js +227 -0
  120. package/dist/server/storage/jsonl-log.d.ts +9 -0
  121. package/dist/server/storage/jsonl-log.d.ts.map +1 -1
  122. package/dist/server/storage/jsonl-log.js +36 -1
  123. package/dist/server/storage/schema/server.store.d.ts +5 -0
  124. package/dist/server/storage/schema/server.store.d.ts.map +1 -1
  125. package/dist/server/storage/schema/server.store.js +2 -1
  126. package/dist/server/storage/schema/wake-queue.store.d.ts +15 -1
  127. package/dist/server/storage/schema/wake-queue.store.d.ts.map +1 -1
  128. package/dist/server/storage/schema/wake-queue.store.js +5 -3
  129. package/dist/server/tests/agent-config.test.d.ts +2 -0
  130. package/dist/server/tests/agent-config.test.d.ts.map +1 -0
  131. package/dist/server/tests/agent-config.test.js +229 -0
  132. package/dist/server/tests/agent-runtime.test.d.ts +2 -0
  133. package/dist/server/tests/agent-runtime.test.d.ts.map +1 -0
  134. package/dist/server/tests/agent-runtime.test.js +1110 -0
  135. package/dist/server/tests/agent-seed-memory.test.d.ts +2 -0
  136. package/dist/server/tests/agent-seed-memory.test.d.ts.map +1 -0
  137. package/dist/server/tests/agent-seed-memory.test.js +16 -0
  138. package/dist/server/tests/agent-skills.test.d.ts +2 -0
  139. package/dist/server/tests/agent-skills.test.d.ts.map +1 -0
  140. package/dist/server/tests/agent-skills.test.js +140 -0
  141. package/dist/server/tests/anima-home.d.ts +2 -0
  142. package/dist/server/tests/anima-home.d.ts.map +1 -0
  143. package/dist/server/tests/anima-home.js +4 -0
  144. package/dist/server/tests/cli-file.test.d.ts +2 -0
  145. package/dist/server/tests/cli-file.test.d.ts.map +1 -0
  146. package/dist/server/tests/cli-file.test.js +596 -0
  147. package/dist/server/tests/cli-message.test.d.ts +2 -0
  148. package/dist/server/tests/cli-message.test.d.ts.map +1 -0
  149. package/dist/server/tests/cli-message.test.js +1196 -0
  150. package/dist/server/tests/client-error-routes.test.d.ts +2 -0
  151. package/dist/server/tests/client-error-routes.test.d.ts.map +1 -0
  152. package/dist/server/tests/client-error-routes.test.js +163 -0
  153. package/dist/server/tests/config.test.d.ts +2 -0
  154. package/dist/server/tests/config.test.d.ts.map +1 -0
  155. package/dist/server/tests/config.test.js +497 -0
  156. package/dist/server/tests/default-skills.test.d.ts +2 -0
  157. package/dist/server/tests/default-skills.test.d.ts.map +1 -0
  158. package/dist/server/tests/default-skills.test.js +57 -0
  159. package/dist/server/tests/helpers/inbox.d.ts +10 -0
  160. package/dist/server/tests/helpers/inbox.d.ts.map +1 -0
  161. package/dist/server/tests/helpers/inbox.js +21 -0
  162. package/dist/server/tests/helpers/slack.d.ts +11 -0
  163. package/dist/server/tests/helpers/slack.d.ts.map +1 -0
  164. package/dist/server/tests/helpers/slack.js +17 -0
  165. package/dist/server/tests/helpers/state.d.ts +19 -0
  166. package/dist/server/tests/helpers/state.d.ts.map +1 -0
  167. package/dist/server/tests/helpers/state.js +69 -0
  168. package/dist/server/tests/inbox-slack-events.test.d.ts +2 -0
  169. package/dist/server/tests/inbox-slack-events.test.d.ts.map +1 -0
  170. package/dist/server/tests/inbox-slack-events.test.js +271 -0
  171. package/dist/server/tests/inbox.test.d.ts +2 -0
  172. package/dist/server/tests/inbox.test.d.ts.map +1 -0
  173. package/dist/server/tests/inbox.test.js +144 -0
  174. package/dist/server/tests/interactive-ask.test.d.ts +2 -0
  175. package/dist/server/tests/interactive-ask.test.d.ts.map +1 -0
  176. package/dist/server/tests/interactive-ask.test.js +387 -0
  177. package/dist/server/tests/kb.test.d.ts +2 -0
  178. package/dist/server/tests/kb.test.d.ts.map +1 -0
  179. package/dist/server/tests/kb.test.js +371 -0
  180. package/dist/server/tests/message.service.test.d.ts +2 -0
  181. package/dist/server/tests/message.service.test.d.ts.map +1 -0
  182. package/dist/server/tests/message.service.test.js +151 -0
  183. package/dist/server/tests/messages.test.d.ts +2 -0
  184. package/dist/server/tests/messages.test.d.ts.map +1 -0
  185. package/dist/server/tests/messages.test.js +12 -0
  186. package/dist/server/tests/prompt-attachments.test.d.ts +2 -0
  187. package/dist/server/tests/prompt-attachments.test.d.ts.map +1 -0
  188. package/dist/server/tests/prompt-attachments.test.js +274 -0
  189. package/dist/server/tests/provider-usage.test.d.ts +2 -0
  190. package/dist/server/tests/provider-usage.test.d.ts.map +1 -0
  191. package/dist/server/tests/provider-usage.test.js +97 -0
  192. package/dist/server/tests/reminders.test.d.ts +2 -0
  193. package/dist/server/tests/reminders.test.d.ts.map +1 -0
  194. package/dist/server/tests/reminders.test.js +383 -0
  195. package/dist/server/tests/runtime-cli.test.d.ts +2 -0
  196. package/dist/server/tests/runtime-cli.test.d.ts.map +1 -0
  197. package/dist/server/tests/runtime-cli.test.js +21 -0
  198. package/dist/server/tests/runtime-upgrade.test.d.ts +2 -0
  199. package/dist/server/tests/runtime-upgrade.test.d.ts.map +1 -0
  200. package/dist/server/tests/runtime-upgrade.test.js +307 -0
  201. package/dist/server/tests/runtime-worker.test.d.ts +2 -0
  202. package/dist/server/tests/runtime-worker.test.d.ts.map +1 -0
  203. package/dist/server/tests/runtime-worker.test.js +1021 -0
  204. package/dist/server/tests/runtime.test.d.ts +2 -0
  205. package/dist/server/tests/runtime.test.d.ts.map +1 -0
  206. package/dist/server/tests/runtime.test.js +354 -0
  207. package/dist/server/tests/services.test.d.ts +2 -0
  208. package/dist/server/tests/services.test.d.ts.map +1 -0
  209. package/dist/server/tests/services.test.js +636 -0
  210. package/dist/server/tests/slack-files.test.d.ts +2 -0
  211. package/dist/server/tests/slack-files.test.d.ts.map +1 -0
  212. package/dist/server/tests/slack-files.test.js +118 -0
  213. package/dist/server/tests/slack-shortcuts.test.d.ts +2 -0
  214. package/dist/server/tests/slack-shortcuts.test.d.ts.map +1 -0
  215. package/dist/server/tests/slack-shortcuts.test.js +310 -0
  216. package/dist/server/tests/slack.test.d.ts +2 -0
  217. package/dist/server/tests/slack.test.d.ts.map +1 -0
  218. package/dist/server/tests/slack.test.js +213 -0
  219. package/dist/server/tests/state-cache.test.d.ts +2 -0
  220. package/dist/server/tests/state-cache.test.d.ts.map +1 -0
  221. package/dist/server/tests/state-cache.test.js +184 -0
  222. package/dist/server/tests/subscriptions.test.d.ts +2 -0
  223. package/dist/server/tests/subscriptions.test.d.ts.map +1 -0
  224. package/dist/server/tests/subscriptions.test.js +292 -0
  225. package/dist/server/tests/system-service.test.d.ts +2 -0
  226. package/dist/server/tests/system-service.test.d.ts.map +1 -0
  227. package/dist/server/tests/system-service.test.js +20 -0
  228. package/dist/server/tests/url-routes.test.d.ts +2 -0
  229. package/dist/server/tests/url-routes.test.d.ts.map +1 -0
  230. package/dist/server/tests/url-routes.test.js +217 -0
  231. package/dist/server/tests/web-api.test.d.ts +2 -0
  232. package/dist/server/tests/web-api.test.d.ts.map +1 -0
  233. package/dist/server/tests/web-api.test.js +1759 -0
  234. package/dist/server/web/app.d.ts.map +1 -1
  235. package/dist/server/web/app.js +2 -0
  236. package/dist/server/web/client-error-routes.d.ts +3 -0
  237. package/dist/server/web/client-error-routes.d.ts.map +1 -0
  238. package/dist/server/web/client-error-routes.js +101 -0
  239. package/dist/server/web/system-routes.d.ts.map +1 -1
  240. package/dist/server/web/system-routes.js +21 -131
  241. package/dist/shared/agent-config.d.ts +8 -18
  242. package/dist/shared/agent-config.d.ts.map +1 -1
  243. package/dist/shared/agent-config.js +3 -4
  244. package/dist/shared/inbox.d.ts +27 -0
  245. package/dist/shared/inbox.d.ts.map +1 -1
  246. package/dist/shared/inbox.js +1 -0
  247. package/dist/shared/server-info.d.ts +6 -5
  248. package/dist/shared/server-info.d.ts.map +1 -1
  249. package/dist/shared/server-info.js +3 -1
  250. package/dist/shared/server-settings.d.ts +6 -0
  251. package/dist/shared/server-settings.d.ts.map +1 -1
  252. package/dist/shared/server-settings.js +1 -0
  253. package/dist/shared/skills.d.ts +24 -3
  254. package/dist/shared/skills.d.ts.map +1 -1
  255. package/dist/web/assets/activity-DHjip8tY.js +7 -0
  256. package/dist/web/assets/clipboard-D2NSC52v.js +1 -0
  257. package/dist/web/assets/{external-link-Dt0qTpmV.js → external-link-Bhr1WdRS.js} +1 -1
  258. package/dist/web/assets/{file-text-Dd9ys6py.js → file-text-CYMA_SMA.js} +1 -1
  259. package/dist/web/assets/{index-CzAQnbuO.js → index-CVpew409.js} +5 -5
  260. package/dist/web/assets/index-mh0uJTkY.css +2 -0
  261. package/dist/web/assets/kb-DDVpYkT9.js +35 -0
  262. package/dist/web/assets/profile-CBy6GNzp.js +1 -0
  263. package/dist/web/assets/reminders-Bbwb9QNT.js +1 -0
  264. package/dist/web/favicon.svg +1 -1
  265. package/dist/web/index.html +2 -2
  266. package/package.json +1 -1
  267. package/templates/runtime-standing-prompt.md +16 -2
  268. package/templates/skills/find-skills/SKILL.md +133 -0
  269. package/dist/server/runtime/activity-payload.d.ts.map +0 -1
  270. package/dist/server/runtime/activity-text.d.ts +0 -4
  271. package/dist/server/runtime/activity-text.d.ts.map +0 -1
  272. package/dist/server/runtime/activity-text.js +0 -16
  273. package/dist/server/runtime/managed-runtime.d.ts.map +0 -1
  274. package/dist/server/runtime/provider-contract.d.ts.map +0 -1
  275. package/dist/server/runtime/runtime-release.d.ts.map +0 -1
  276. package/dist/server/runtime/runtime-upgrade.d.ts.map +0 -1
  277. package/dist/server/slack/shortcut.service.d.ts.map +0 -1
  278. package/dist/server/slack/shortcut.service.js +0 -493
  279. package/dist/web/assets/activity-BP0C81IV.js +0 -7
  280. package/dist/web/assets/globe-DmDZSgDP.js +0 -1
  281. package/dist/web/assets/index-DKecrvN0.css +0 -2
  282. package/dist/web/assets/kb-3wFeP2Jt.js +0 -32
  283. package/dist/web/assets/profile-D7wPZXW_.js +0 -1
  284. package/dist/web/assets/reminders-DOhroVwo.js +0 -1
  285. /package/dist/server/{runtime/provider-contract.js → providers/contract.js} +0 -0
  286. /package/dist/server/{runtime → runtime-management}/managed-runtime.d.ts +0 -0
  287. /package/dist/server/{runtime → runtime-management}/managed-runtime.js +0 -0
  288. /package/dist/server/{runtime → runtime-management}/runtime-release.d.ts +0 -0
  289. /package/dist/server/{runtime → runtime-management}/runtime-release.js +0 -0
@@ -5,16 +5,13 @@ import { isRestartDrainActive } from '../services/restart-drain.js';
5
5
  import { AgentRuntimeBridge } from './runtime-bridge.js';
6
6
  import { runtimeContextForItemId } from './context.js';
7
7
  import { clearActiveRuntimeItem, setActiveRuntimeItem } from './active-item.js';
8
- import { recordRuntimeAborted, recordRuntimeActivity, recordRuntimeEvent, recordRuntimeFollowupAppended, recordRuntimeFollowupFailed, recordRuntimePending, } from './activity.js';
9
- import { runtimeErrorPayload } from './activity-text.js';
8
+ import { recordRuntimeAborted, recordRuntimeEvent, } from './activity.js';
9
+ import { startActiveRunControl } from './active-run-control.js';
10
+ import { appendQueuedFollowupsUntilFinished } from './followup-appender.js';
11
+ import { recordFinalRuntimeFailure, runProviderWithCrashRetries } from './provider-runner.js';
10
12
  // Executor for one agent: claims queued inbox items, runs the provider runtime,
11
13
  // appends follow-up items into the active run, and settles item lifecycle state.
12
14
  const IDLE_TIMEOUT_MS_DEFAULT = PROVIDER_IDLE_TIMEOUT_MS_DEFAULT;
13
- const IDLE_CHECK_INTERVAL_FLOOR_MS = 50;
14
- const IDLE_CHECK_INTERVAL_CAP_MS = 1_000;
15
- const FOLLOWUP_POLL_MS = 100;
16
- const PROVIDER_CRASH_MAX_RETRIES = 3;
17
- const PROVIDER_CRASH_RETRY_BACKOFF_MS = 500;
18
15
  export class AgentRuntimeWorker {
19
16
  options;
20
17
  logger;
@@ -120,7 +117,23 @@ export class AgentRuntimeWorker {
120
117
  let followupError;
121
118
  try {
122
119
  context = await runtimeContextForItemId(item.id, this.options);
123
- followupLoop = this.appendQueuedFollowupsUntilFinished(context, itemAbort.signal, handle).catch((error) => {
120
+ const activeContext = context;
121
+ followupLoop = appendQueuedFollowupsUntilFinished({
122
+ activeContext,
123
+ agentRuntime: this.options.agentRuntime,
124
+ itemDone: itemAbort.signal,
125
+ logger: this.logger,
126
+ onFollowupAccepted: () => handle.noteActivity(),
127
+ onFollowupAppended: async (followupContext, _text) => {
128
+ handle.appendedFollowups.push(followupContext);
129
+ await this.notifyItemFollowupAppended(activeContext, followupContext);
130
+ },
131
+ onFollowupSettled: (followupContext) => this.notifySettledItems([followupContext]),
132
+ queue: this.queue,
133
+ runtimeBridge: this.runtimeBridge,
134
+ runtimeConfig: this.options,
135
+ workerId: this.workerId,
136
+ }).catch((error) => {
124
137
  followupError = error;
125
138
  });
126
139
  const agentConfig = await defaultAgentRegistryService.serviceFor(this.options.agentId).getConfig();
@@ -131,17 +144,28 @@ export class AgentRuntimeWorker {
131
144
  workerId: this.workerId,
132
145
  });
133
146
  await this.notifyItemStarted(context);
134
- const result = await this.runProviderWithCrashRetries({
135
- context,
136
- handle,
147
+ if (context.item.handling.resumeReason === 'runtime_restart') {
148
+ await this.recordRestartResumeActivity(context);
149
+ }
150
+ const runContext = context;
151
+ const result = await runProviderWithCrashRetries({
152
+ agentId: this.options.agentId,
153
+ agentRuntime: this.options.agentRuntime,
154
+ buildInput: (retryNotice) => this.runtimeBridge.runInput({
155
+ context: runContext,
156
+ onActivity: () => handle.noteActivity(),
157
+ profile: {
158
+ displayName: agentConfig.profile?.displayName ?? this.options.agentId,
159
+ ...(agentConfig.profile?.role ? { role: agentConfig.profile.role } : {}),
160
+ },
161
+ retryNotice,
162
+ session: runContext.session,
163
+ signal: itemAbort.signal,
164
+ suppressFailureRecord: true,
165
+ }),
137
166
  onFinalFailureRecorded: () => {
138
167
  runtimeFailureRecorded = true;
139
168
  },
140
- profile: {
141
- displayName: agentConfig.profile?.displayName ?? this.options.agentId,
142
- ...(agentConfig.profile?.role ? { role: agentConfig.profile.role } : {}),
143
- },
144
- session: context.session,
145
169
  signal: itemAbort.signal,
146
170
  });
147
171
  itemAbort.abort('completed');
@@ -171,7 +195,12 @@ export class AgentRuntimeWorker {
171
195
  itemSettled = true;
172
196
  }
173
197
  else if (context && !runtimeFailureRecorded) {
174
- await this.recordFinalRuntimeFailure(error, 0);
198
+ await recordFinalRuntimeFailure({
199
+ agentId: this.options.agentId,
200
+ agentRuntime: this.options.agentRuntime,
201
+ error,
202
+ retryAttempts: 0,
203
+ });
175
204
  }
176
205
  if (!itemSettled)
177
206
  await this.queue.fail(item.id);
@@ -201,209 +230,31 @@ export class AgentRuntimeWorker {
201
230
  }
202
231
  }
203
232
  registerActiveItem(itemId, abortController) {
204
- const startedAt = Date.now();
205
- const tickInterval = Math.max(IDLE_CHECK_INTERVAL_FLOOR_MS, Math.min(IDLE_CHECK_INTERVAL_CAP_MS, Math.floor(this.idleTimeoutMs / 2)));
206
- const handle = {
233
+ const handle = startActiveRunControl({
207
234
  abortController,
208
- appendedFollowups: [],
209
- drainRequestInFlight: false,
210
- lastActivityAt: startedAt,
211
- startedAt,
212
- watchdog: setInterval(() => {
213
- if (abortController.signal.aborted)
214
- return;
215
- const now = Date.now();
216
- if (now - handle.lastActivityAt >= this.idleTimeoutMs) {
217
- abortController.abort('idle_timeout');
218
- return;
219
- }
220
- void this.checkExternalRequests(itemId, abortController, handle);
221
- }, tickInterval),
222
- };
235
+ agentRuntime: this.options.agentRuntime,
236
+ idleTimeoutMs: this.idleTimeoutMs,
237
+ itemId,
238
+ logger: this.logger,
239
+ queue: this.queue,
240
+ });
223
241
  this.activeItem = handle;
224
242
  return handle;
225
243
  }
226
- noteProviderActivity(handle) {
227
- handle.lastActivityAt = Date.now();
228
- }
229
- async runProviderWithCrashRetries(input) {
230
- let retryCount = 0;
231
- let previousError;
232
- for (;;) {
233
- try {
234
- return await this.options.agentRuntime.run(await this.runtimeBridge.runInput({
235
- context: input.context,
236
- onActivity: () => this.noteProviderActivity(input.handle),
237
- profile: input.profile,
238
- retryNotice: retryCount > 0
239
- ? providerCrashRetryPrompt({
240
- attempt: retryCount,
241
- maxRetries: PROVIDER_CRASH_MAX_RETRIES,
242
- previousError: errorMessage(previousError),
243
- })
244
- : undefined,
245
- session: input.session,
246
- signal: input.signal,
247
- suppressFailureRecord: true,
248
- }));
249
- }
250
- catch (error) {
251
- previousError = error;
252
- if (input.signal.aborted)
253
- throw error;
254
- if (!isProviderCrashError(error) || retryCount >= PROVIDER_CRASH_MAX_RETRIES) {
255
- await this.recordFinalRuntimeFailure(error, retryCount, { providerFailure: true });
256
- input.onFinalFailureRecorded();
257
- throw error;
258
- }
259
- retryCount += 1;
260
- const retryAfterMs = PROVIDER_CRASH_RETRY_BACKOFF_MS * retryCount;
261
- await recordRuntimeEvent({ agentId: this.options.agentId }, this.options.agentRuntime.kind, this.options.agentRuntime.env, {
262
- attempt: retryCount,
263
- error: errorMessage(error),
264
- eventType: 'provider.crash.retry',
265
- maxRetries: PROVIDER_CRASH_MAX_RETRIES,
266
- retryAfterMs,
267
- });
268
- await this.options.agentRuntime.close?.();
269
- await sleep(retryAfterMs, input.signal);
270
- }
271
- }
272
- }
273
- async recordFinalRuntimeFailure(error, retryAttempts, options = {}) {
274
- const processCrash = isProviderCrashError(error);
275
- await recordRuntimeActivity({ agentId: this.options.agentId }, this.options.agentRuntime.kind, 'runtime.failed', {
276
- ...runtimeErrorPayload(error),
277
- ...(options.providerFailure
278
- ? {
279
- failureSource: 'provider',
280
- maxRetries: PROVIDER_CRASH_MAX_RETRIES,
281
- providerReason: processCrash ? 'process_crash' : 'provider_error',
282
- retryAttempts,
283
- retryable: processCrash && retryAttempts < PROVIDER_CRASH_MAX_RETRIES,
284
- }
285
- : {}),
244
+ async recordRestartResumeActivity(context) {
245
+ await recordRuntimeEvent({ agentId: this.options.agentId }, this.options.agentRuntime.kind, this.options.agentRuntime.env, {
246
+ eventType: 'runtime.restart_resumed',
247
+ itemId: context.item.id,
248
+ message: 'Resumed after restart',
286
249
  });
287
250
  }
288
- async checkExternalRequests(itemId, abortController, handle) {
289
- try {
290
- const item = await this.queue.find(itemId);
291
- if (item?.handling.stopRequestedAt && !abortController.signal.aborted) {
292
- abortController.abort('user_stop');
293
- return;
294
- }
295
- const drainRequestedAt = item?.handling.drainRequestedAt;
296
- if (drainRequestedAt &&
297
- !handle.drainRequestInFlight &&
298
- handle.drainRequestedAt !== drainRequestedAt &&
299
- !abortController.signal.aborted) {
300
- handle.drainRequestInFlight = true;
301
- handle.drainRequestedAt = drainRequestedAt;
302
- void this.drainActiveItem(itemId, item.handling.drainTimeoutMs, abortController, handle);
303
- }
304
- }
305
- catch (error) {
306
- this.logger.error(`Runtime worker control check failed for item ${itemId}: ${errorMessage(error)}`);
307
- }
308
- }
309
- async drainActiveItem(itemId, timeoutMs, abortController, handle) {
310
- try {
311
- if (!this.options.agentRuntime.requestDrain)
312
- return;
313
- await withTimeout(this.options.agentRuntime.requestDrain({ activeItemId: itemId, signal: abortController.signal }), timeoutMs ?? 15_000, `Timed out waiting for item ${itemId} to reach a restart drain point`);
314
- const current = await this.queue.find(itemId);
315
- if (current?.handling.drainRequestedAt !== handle.drainRequestedAt)
316
- return;
317
- if (!abortController.signal.aborted)
318
- abortController.abort('restart_drain');
319
- }
320
- catch (error) {
321
- this.logger.error(`Runtime worker drain request failed for item ${itemId}: ${errorMessage(error)}`);
322
- }
323
- finally {
324
- handle.drainRequestInFlight = false;
325
- }
326
- }
327
251
  releaseActiveItem() {
328
252
  const handle = this.activeItem;
329
253
  if (!handle)
330
254
  return;
331
- clearInterval(handle.watchdog);
255
+ handle.release();
332
256
  this.activeItem = undefined;
333
257
  }
334
- async appendQueuedFollowupsUntilFinished(activeContext, itemDone, handle) {
335
- const skippedItemIds = new Set();
336
- while (!itemDone.aborted) {
337
- if (await isRestartDrainActive()) {
338
- await sleep(FOLLOWUP_POLL_MS, itemDone);
339
- continue;
340
- }
341
- const item = await this.queue.claimNextFollowup({
342
- activeItemId: activeContext.item.id,
343
- excludedItemIds: skippedItemIds,
344
- workerId: this.workerId,
345
- });
346
- if (!item) {
347
- await sleep(FOLLOWUP_POLL_MS, itemDone);
348
- continue;
349
- }
350
- await this.tryOneFollowupItem(activeContext, item, handle, itemDone, skippedItemIds);
351
- }
352
- }
353
- async tryOneFollowupItem(activeContext, item, handle, itemDone, skippedItemIds) {
354
- let appended = false;
355
- let context;
356
- try {
357
- context = await runtimeContextForItemId(item.id, this.options);
358
- const followup = await appendRuntimeFollowup({
359
- activeContext,
360
- agentRuntime: this.options.agentRuntime,
361
- context,
362
- runtimeBridge: this.runtimeBridge,
363
- });
364
- if (followup.status === 'appended') {
365
- await this.recordFollowupAppendSuccess(activeContext, context, followup.text, handle);
366
- appended = true;
367
- return;
368
- }
369
- await this.recordFollowupAppendSkip(activeContext, item, followup);
370
- skippedItemIds.add(item.id);
371
- await this.queue.requeue(item.id);
372
- await sleep(FOLLOWUP_POLL_MS, itemDone);
373
- }
374
- catch (error) {
375
- skippedItemIds.add(item.id);
376
- await this.queue.requeue(item.id);
377
- await recordRuntimeFollowupFailed({ agentId: this.options.agentId }, {
378
- activeItemId: activeContext.item.id,
379
- agentRuntime: this.options.agentRuntime.kind,
380
- error: errorMessage(error),
381
- reason: 'followup_failed',
382
- });
383
- this.logger.error(`Runtime worker follow-up append failed for item ${item.id}: ${errorMessage(error)}`);
384
- await sleep(FOLLOWUP_POLL_MS, itemDone);
385
- }
386
- finally {
387
- const current = context && !appended ? await this.queue.find(context.item.id).catch(() => undefined) : undefined;
388
- if (context && (current?.handling.status === 'completed' || current?.handling.status === 'failed')) {
389
- await this.notifySettledItems([context]);
390
- }
391
- }
392
- }
393
- async recordFollowupAppendSuccess(activeContext, context, text, handle) {
394
- this.noteProviderActivity(handle);
395
- await this.queue.complete(context.item.id);
396
- handle.appendedFollowups.push(context);
397
- await this.notifyItemFollowupAppended(activeContext, context);
398
- this.logger.log(JSON.stringify({
399
- activeItemId: activeContext.item.id,
400
- agentRuntime: this.options.agentRuntime.kind,
401
- event: 'runtime.followup_appended',
402
- itemId: context.item.id,
403
- text,
404
- workerId: this.workerId,
405
- }, null, 2));
406
- }
407
258
  async notifyItemStarted(context) {
408
259
  try {
409
260
  await this.options.onItemStarted?.(context);
@@ -430,22 +281,10 @@ export class AgentRuntimeWorker {
430
281
  }
431
282
  }
432
283
  }
433
- async recordFollowupAppendSkip(activeContext, item, followup) {
434
- if (followup.status === 'rejected') {
435
- await recordRuntimePending({ agentId: this.options.agentId }, {
436
- activeItemId: activeContext.item.id,
437
- agentRuntime: this.options.agentRuntime.kind,
438
- reason: 'followup_rejected',
439
- });
440
- }
441
- if (followup.status === 'failed') {
442
- this.logger.error(`Runtime worker follow-up append failed for item ${item.id}: ${followup.error}`);
443
- }
444
- }
445
284
  async settleAbortedItem(context, abortReason) {
446
285
  await recordRuntimeAborted({ agentId: this.options.agentId }, abortReason, abortReason === 'idle_timeout' ? { timeoutMs: this.idleTimeoutMs } : undefined);
447
286
  if (abortReason === 'restart_drain') {
448
- await this.queue.requeue(context.item.id);
287
+ await this.queue.requeue(context.item.id, { resumeReason: 'runtime_restart' });
449
288
  return;
450
289
  }
451
290
  await this.queue.fail(context.item.id);
@@ -460,32 +299,6 @@ function abortReasonOf(signal) {
460
299
  ? reason
461
300
  : undefined;
462
301
  }
463
- async function appendRuntimeFollowup(input) {
464
- try {
465
- const result = await input.agentRuntime.appendToActiveRun(await input.runtimeBridge.followupInput({
466
- activeContext: input.activeContext,
467
- context: input.context,
468
- }));
469
- if (!result.accepted)
470
- return { status: 'rejected' };
471
- await recordRuntimeFollowupAppended({ agentId: input.context.agentId }, {
472
- activeItemId: input.activeContext.item.id,
473
- agentRuntime: input.agentRuntime.kind,
474
- text: result.text,
475
- });
476
- return { status: 'appended', text: result.text };
477
- }
478
- catch (error) {
479
- const message = errorMessage(error);
480
- await recordRuntimeFollowupFailed({ agentId: input.context.agentId }, {
481
- activeItemId: input.activeContext.item.id,
482
- agentRuntime: input.agentRuntime.kind,
483
- error: message,
484
- reason: 'followup_failed',
485
- });
486
- return { error: message, status: 'failed' };
487
- }
488
- }
489
302
  function isWorkerAlive(workerId) {
490
303
  const pidText = workerId.split(':').at(-1);
491
304
  const pid = pidText ? Number.parseInt(pidText, 10) : Number.NaN;
@@ -499,42 +312,3 @@ function isWorkerAlive(workerId) {
499
312
  return false;
500
313
  }
501
314
  }
502
- function isProviderCrashError(error) {
503
- const message = errorMessage(error);
504
- return (/runtime exited before completing/i.test(message) ||
505
- /runtime terminated by/i.test(message) ||
506
- /runtime exited with code/i.test(message) ||
507
- /stdin is closed/i.test(message));
508
- }
509
- function providerCrashRetryPrompt(input) {
510
- return [
511
- 'Anima system note: the previous provider process crashed before completing this same item.',
512
- `This is retry ${input.attempt}/${input.maxRetries}.`,
513
- `Previous error: ${input.previousError}`,
514
- 'Continue the original task from the current files, conversation, and Slack state.',
515
- 'Do not repeat completed external side effects such as Slack messages, file sends, or file edits; inspect state first if needed.',
516
- ].join('\n');
517
- }
518
- function sleep(ms, signal) {
519
- if (signal.aborted)
520
- return Promise.resolve();
521
- return new Promise((resolve) => {
522
- const done = () => {
523
- clearTimeout(timer);
524
- signal.removeEventListener('abort', done);
525
- resolve();
526
- };
527
- const timer = setTimeout(done, ms);
528
- signal.addEventListener('abort', done, { once: true });
529
- });
530
- }
531
- function withTimeout(promise, timeoutMs, message) {
532
- let timer;
533
- const timeout = new Promise((_, reject) => {
534
- timer = setTimeout(() => reject(new Error(message)), timeoutMs);
535
- });
536
- return Promise.race([promise, timeout]).finally(() => {
537
- if (timer)
538
- clearTimeout(timer);
539
- });
540
- }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"managed-runtime.d.ts","sourceRoot":"","sources":["../../../server/runtime-management/managed-runtime.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-release.d.ts","sourceRoot":"","sources":["../../../server/runtime-management/runtime-release.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAKrG,MAAM,MAAM,oBAAoB,GAAG,CAAC,KAAK,EAAE;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;CACb,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAEtB,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,mBAAmB,GAAG,MAAM,CAExE;AAED,wBAAsB,gBAAgB,CAAC,KAAK,EAAE;IAC5C,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;CACb,GAAG,OAAO,CAAC,MAAM,CAAC,CAsBlB;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,wBAAwB,CAQjF;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAmB1E"}
@@ -51,6 +51,7 @@ export declare class RuntimeUpgradeService {
51
51
  private readonly settings;
52
52
  constructor(options?: RuntimeUpgradeServiceOptions);
53
53
  status(): Promise<RuntimeUpgradeStatusResponse>;
54
+ checkNow(): Promise<RuntimeUpgradeStatusResponse>;
54
55
  prepareApply(input: {
55
56
  animactlScript: string;
56
57
  dashboardHost?: string;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-upgrade.d.ts","sourceRoot":"","sources":["../../../server/runtime-management/runtime-upgrade.ts"],"names":[],"mappings":"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"}
@@ -74,6 +74,20 @@ export class RuntimeUpgradeService {
74
74
  updateAvailable,
75
75
  };
76
76
  }
77
+ async checkNow() {
78
+ const [currentVersion, releaseTrack, operation] = await Promise.all([
79
+ this.packageVersion(),
80
+ this.settings.getReleaseTrack(),
81
+ this.operationStore.read(),
82
+ ]);
83
+ const refreshed = await this.refreshCheckCache(releaseTrack);
84
+ return this.statusFromCheck({
85
+ check: refreshed,
86
+ currentVersion,
87
+ operation,
88
+ releaseTrack,
89
+ });
90
+ }
77
91
  async prepareApply(input) {
78
92
  const [currentVersion, releaseTrack, operation] = await Promise.all([
79
93
  this.packageVersion(),
@@ -0,0 +1,41 @@
1
+ import { type ServerSettingsService } from '../settings/settings.service.js';
2
+ import type { ServerInfo, ServicesRestartResponse } from '../../shared/server-info.js';
3
+ import { type ProviderAvailability } from '../../shared/provider-catalog.js';
4
+ export interface PreparedServicesRestart {
5
+ response: ServicesRestartResponse;
6
+ spawn: () => Promise<void>;
7
+ }
8
+ export interface SystemServiceOptions {
9
+ animactlScript?: string;
10
+ commandPresent?: (command: string) => Promise<boolean>;
11
+ commit?: Promise<string | undefined> | string;
12
+ now?: () => Date;
13
+ packageVersion?: () => Promise<string>;
14
+ projectRoot?: string;
15
+ restartDelayMs?: number;
16
+ settings?: ServerSettingsService;
17
+ startedAt?: string;
18
+ }
19
+ export declare class SystemServiceError extends Error {
20
+ }
21
+ export declare class SystemService {
22
+ private readonly animactlScript;
23
+ private readonly commandPresent;
24
+ private readonly commit;
25
+ private readonly now;
26
+ private readonly packageVersion;
27
+ private readonly projectRoot;
28
+ private readonly restartDelayMs;
29
+ private readonly settings;
30
+ private readonly startedAt;
31
+ constructor(options?: SystemServiceOptions);
32
+ providerAvailability(): Promise<{
33
+ providers: ProviderAvailability[];
34
+ }>;
35
+ serverInfo(): Promise<ServerInfo>;
36
+ serverStartedAt(): string;
37
+ prepareServicesRestart(): PreparedServicesRestart;
38
+ }
39
+ export declare const defaultSystemService: SystemService;
40
+ export declare function docsUrl(track: 'dev' | 'canary' | 'stable'): string;
41
+ //# sourceMappingURL=system.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"system.service.d.ts","sourceRoot":"","sources":["../../../server/services/system.service.ts"],"names":[],"mappings":"AAQA,OAAO,EAAgC,KAAK,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAO3G,OAAO,KAAK,EAAE,UAAU,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AACvF,OAAO,EAAoB,KAAK,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AAM/F,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,uBAAuB,CAAC;IAClC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B;AAED,MAAM,WAAW,oBAAoB;IACnC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACvD,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,GAAG,MAAM,CAAC;IAC9C,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,qBAAqB,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,kBAAmB,SAAQ,KAAK;CAAG;AAEhD,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAwC;IACvE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA8B;IACrD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAa;IACjC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAwB;IACvD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAwB;IACjD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAEvB,OAAO,GAAE,oBAAyB;IAYxC,oBAAoB,IAAI,OAAO,CAAC;QAAE,SAAS,EAAE,oBAAoB,EAAE,CAAA;KAAE,CAAC;IAStE,UAAU,IAAI,OAAO,CAAC,UAAU,CAAC;IAuBvC,eAAe,IAAI,MAAM;IAIzB,sBAAsB,IAAI,uBAAuB;CAyBlD;AAED,eAAO,MAAM,oBAAoB,eAAsB,CAAC;AAsDxD,wBAAgB,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAKlE"}
@@ -0,0 +1,154 @@
1
+ import { execFile, spawn } from 'node:child_process';
2
+ import { existsSync } from 'node:fs';
3
+ import { mkdir, open, readFile, rm } from 'node:fs/promises';
4
+ import { dirname, join, resolve } from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+ import { promisify } from 'node:util';
7
+ import { resolveAnimaHome } from '../anima-home.js';
8
+ import { defaultServerSettingsService } from '../settings/settings.service.js';
9
+ import { cleanServiceEnv } from './env.js';
10
+ import { readLastServicesRestart, servicesRestartLogPath, servicesRestartResultPath, } from './restart-result.js';
11
+ import { PROVIDER_CATALOG } from '../../shared/provider-catalog.js';
12
+ const execFileAsync = promisify(execFile);
13
+ const PROJECT_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '../../..');
14
+ const RESTART_AFTER_RESPONSE_DELAY_MS = 250;
15
+ export class SystemServiceError extends Error {
16
+ }
17
+ export class SystemService {
18
+ animactlScript;
19
+ commandPresent;
20
+ commit;
21
+ now;
22
+ packageVersion;
23
+ projectRoot;
24
+ restartDelayMs;
25
+ settings;
26
+ startedAt;
27
+ constructor(options = {}) {
28
+ this.projectRoot = options.projectRoot ?? PROJECT_ROOT;
29
+ this.animactlScript = options.animactlScript ?? join(this.projectRoot, 'dist/server/cli/animactl.js');
30
+ this.commandPresent = options.commandPresent ?? commandPresent;
31
+ this.commit = Promise.resolve(options.commit ?? gitShortCommit(this.projectRoot));
32
+ this.now = options.now ?? (() => new Date());
33
+ this.packageVersion = options.packageVersion ?? (() => packageVersion(this.projectRoot));
34
+ this.restartDelayMs = options.restartDelayMs ?? RESTART_AFTER_RESPONSE_DELAY_MS;
35
+ this.settings = options.settings ?? defaultServerSettingsService;
36
+ this.startedAt = options.startedAt ?? this.now().toISOString();
37
+ }
38
+ async providerAvailability() {
39
+ return {
40
+ providers: await Promise.all(PROVIDER_CATALOG.map(async (entry) => ({
41
+ kind: entry.kind,
42
+ present: await this.commandPresent(entry.command),
43
+ }))),
44
+ };
45
+ }
46
+ async serverInfo() {
47
+ const animaHome = resolveAnimaHome();
48
+ const [config, version, commit, lastRestart] = await Promise.all([
49
+ this.settings.readConfig(),
50
+ this.packageVersion(),
51
+ this.commit,
52
+ readLastServicesRestart(animaHome),
53
+ ]);
54
+ const track = config.track ?? config.releaseTrack ?? 'stable';
55
+ return {
56
+ animaHome,
57
+ ...(commit ? { commit } : {}),
58
+ dashboardPort: config.dashboardPort ?? 4174,
59
+ docsUrl: docsUrl(track),
60
+ ...(lastRestart ? { lastRestart } : {}),
61
+ ok: true,
62
+ startedAt: this.startedAt,
63
+ track,
64
+ uptimeSeconds: Math.max(0, Math.floor((this.now().getTime() - Date.parse(this.startedAt)) / 1000)),
65
+ version,
66
+ };
67
+ }
68
+ serverStartedAt() {
69
+ return this.startedAt;
70
+ }
71
+ prepareServicesRestart() {
72
+ if (!existsSync(this.animactlScript)) {
73
+ throw new SystemServiceError(`animactl not found: ${this.animactlScript}`);
74
+ }
75
+ const animaHome = resolveAnimaHome();
76
+ const logPath = servicesRestartLogPath(animaHome);
77
+ const resultPath = servicesRestartResultPath(animaHome);
78
+ return {
79
+ response: {
80
+ ok: true,
81
+ animaHome,
82
+ delayMs: this.restartDelayMs,
83
+ logPath,
84
+ scheduled: true,
85
+ },
86
+ spawn: () => restartServicesDetached({
87
+ animaHome,
88
+ animactlScript: this.animactlScript,
89
+ logPath,
90
+ now: this.now,
91
+ projectRoot: this.projectRoot,
92
+ resultPath,
93
+ }),
94
+ };
95
+ }
96
+ }
97
+ export const defaultSystemService = new SystemService();
98
+ async function restartServicesDetached(input) {
99
+ let log;
100
+ try {
101
+ await mkdir(dirname(input.logPath), { recursive: true });
102
+ await rm(input.resultPath, { force: true });
103
+ log = await open(input.logPath, 'a');
104
+ await log.write(`\n[${input.now().toISOString()}] web app requested services restart\n`);
105
+ }
106
+ catch (error) {
107
+ console.error(`Failed to open restart log ${input.logPath}: ${error instanceof Error ? error.message : String(error)}`);
108
+ }
109
+ const child = spawn(process.execPath, [input.animactlScript, 'services', 'restart', '--drain-active', '--resume-running'], {
110
+ cwd: input.projectRoot,
111
+ detached: true,
112
+ env: { ...cleanServiceEnv(), ANIMA_HOME: input.animaHome, ANIMA_RESTART_RESULT_FILE: input.resultPath },
113
+ stdio: log ? ['ignore', log.fd, log.fd] : 'ignore',
114
+ });
115
+ child.on('error', (error) => {
116
+ console.error(`Failed to start services restart: ${error.message}`);
117
+ });
118
+ child.unref();
119
+ await log?.close();
120
+ }
121
+ async function packageVersion(projectRoot) {
122
+ try {
123
+ const pkg = JSON.parse(await readFile(join(projectRoot, 'package.json'), 'utf8'));
124
+ return typeof pkg.version === 'string' && pkg.version ? pkg.version : 'unknown';
125
+ }
126
+ catch {
127
+ return 'unknown';
128
+ }
129
+ }
130
+ async function gitShortCommit(projectRoot) {
131
+ try {
132
+ const { stdout } = await execFileAsync('git', ['rev-parse', '--short', 'HEAD'], { cwd: projectRoot });
133
+ return stdout.trim() || undefined;
134
+ }
135
+ catch {
136
+ return undefined;
137
+ }
138
+ }
139
+ export function docsUrl(track) {
140
+ const configured = process.env.ANIMA_DOCS_URL?.trim();
141
+ if (configured)
142
+ return configured;
143
+ if (track === 'dev')
144
+ return 'http://127.0.0.1:14175/';
145
+ return 'https://anima.meetquinn.ai/';
146
+ }
147
+ function commandPresent(command) {
148
+ return new Promise((resolvePresent) => {
149
+ const child = execFile(command, ['--version'], { encoding: 'utf8', timeout: 2_000 }, (error) => {
150
+ resolvePresent(!error);
151
+ });
152
+ child.stdin?.end();
153
+ });
154
+ }