@alan-ai-hq/agent-manager 0.1.89 → 0.1.91

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 (342) hide show
  1. package/dist/index.cjs +874 -717
  2. package/package.json +1 -1
  3. package/dist/__tests__/binding-switch-git.test.d.ts +0 -2
  4. package/dist/__tests__/binding-switch-git.test.d.ts.map +0 -1
  5. package/dist/__tests__/binding-switch-git.test.js +0 -610
  6. package/dist/__tests__/binding-switch-git.test.js.map +0 -1
  7. package/dist/__tests__/cli-ensure-install.test.d.ts +0 -2
  8. package/dist/__tests__/cli-ensure-install.test.d.ts.map +0 -1
  9. package/dist/__tests__/cli-ensure-install.test.js +0 -109
  10. package/dist/__tests__/cli-ensure-install.test.js.map +0 -1
  11. package/dist/__tests__/cli-executable.test.d.ts +0 -2
  12. package/dist/__tests__/cli-executable.test.d.ts.map +0 -1
  13. package/dist/__tests__/cli-executable.test.js +0 -129
  14. package/dist/__tests__/cli-executable.test.js.map +0 -1
  15. package/dist/__tests__/cli-help.test.d.ts +0 -2
  16. package/dist/__tests__/cli-help.test.d.ts.map +0 -1
  17. package/dist/__tests__/cli-help.test.js +0 -34
  18. package/dist/__tests__/cli-help.test.js.map +0 -1
  19. package/dist/__tests__/computer-readiness.test.d.ts +0 -2
  20. package/dist/__tests__/computer-readiness.test.d.ts.map +0 -1
  21. package/dist/__tests__/computer-readiness.test.js +0 -63
  22. package/dist/__tests__/computer-readiness.test.js.map +0 -1
  23. package/dist/__tests__/core-agent-workflow-context.test.d.ts +0 -2
  24. package/dist/__tests__/core-agent-workflow-context.test.d.ts.map +0 -1
  25. package/dist/__tests__/core-agent-workflow-context.test.js +0 -139
  26. package/dist/__tests__/core-agent-workflow-context.test.js.map +0 -1
  27. package/dist/__tests__/daemon-reconcile-ask.test.d.ts +0 -2
  28. package/dist/__tests__/daemon-reconcile-ask.test.d.ts.map +0 -1
  29. package/dist/__tests__/daemon-reconcile-ask.test.js +0 -86
  30. package/dist/__tests__/daemon-reconcile-ask.test.js.map +0 -1
  31. package/dist/__tests__/daemon-socket.integration.test.d.ts +0 -2
  32. package/dist/__tests__/daemon-socket.integration.test.d.ts.map +0 -1
  33. package/dist/__tests__/daemon-socket.integration.test.js +0 -450
  34. package/dist/__tests__/daemon-socket.integration.test.js.map +0 -1
  35. package/dist/__tests__/daemon.test.d.ts +0 -2
  36. package/dist/__tests__/daemon.test.d.ts.map +0 -1
  37. package/dist/__tests__/daemon.test.js +0 -3975
  38. package/dist/__tests__/daemon.test.js.map +0 -1
  39. package/dist/__tests__/ensure-shared-checkout-branch.test.d.ts +0 -2
  40. package/dist/__tests__/ensure-shared-checkout-branch.test.d.ts.map +0 -1
  41. package/dist/__tests__/ensure-shared-checkout-branch.test.js +0 -129
  42. package/dist/__tests__/ensure-shared-checkout-branch.test.js.map +0 -1
  43. package/dist/__tests__/event-outbox-persist-failure.test.d.ts +0 -2
  44. package/dist/__tests__/event-outbox-persist-failure.test.d.ts.map +0 -1
  45. package/dist/__tests__/event-outbox-persist-failure.test.js +0 -84
  46. package/dist/__tests__/event-outbox-persist-failure.test.js.map +0 -1
  47. package/dist/__tests__/event-outbox.test.d.ts +0 -2
  48. package/dist/__tests__/event-outbox.test.d.ts.map +0 -1
  49. package/dist/__tests__/event-outbox.test.js +0 -256
  50. package/dist/__tests__/event-outbox.test.js.map +0 -1
  51. package/dist/__tests__/fake-provider-cli.test.d.ts +0 -2
  52. package/dist/__tests__/fake-provider-cli.test.d.ts.map +0 -1
  53. package/dist/__tests__/fake-provider-cli.test.js +0 -46
  54. package/dist/__tests__/fake-provider-cli.test.js.map +0 -1
  55. package/dist/__tests__/generated-images.test.d.ts +0 -2
  56. package/dist/__tests__/generated-images.test.d.ts.map +0 -1
  57. package/dist/__tests__/generated-images.test.js +0 -132
  58. package/dist/__tests__/generated-images.test.js.map +0 -1
  59. package/dist/__tests__/lifecycle-logger.test.d.ts +0 -2
  60. package/dist/__tests__/lifecycle-logger.test.d.ts.map +0 -1
  61. package/dist/__tests__/lifecycle-logger.test.js +0 -49
  62. package/dist/__tests__/lifecycle-logger.test.js.map +0 -1
  63. package/dist/__tests__/local-skill-scan.test.d.ts +0 -2
  64. package/dist/__tests__/local-skill-scan.test.d.ts.map +0 -1
  65. package/dist/__tests__/local-skill-scan.test.js +0 -91
  66. package/dist/__tests__/local-skill-scan.test.js.map +0 -1
  67. package/dist/__tests__/local-workspace-migration.test.d.ts +0 -2
  68. package/dist/__tests__/local-workspace-migration.test.d.ts.map +0 -1
  69. package/dist/__tests__/local-workspace-migration.test.js +0 -195
  70. package/dist/__tests__/local-workspace-migration.test.js.map +0 -1
  71. package/dist/__tests__/mcp-inspect-timeout.test.d.ts +0 -2
  72. package/dist/__tests__/mcp-inspect-timeout.test.d.ts.map +0 -1
  73. package/dist/__tests__/mcp-inspect-timeout.test.js +0 -97
  74. package/dist/__tests__/mcp-inspect-timeout.test.js.map +0 -1
  75. package/dist/__tests__/mcp-readiness.test.d.ts +0 -2
  76. package/dist/__tests__/mcp-readiness.test.d.ts.map +0 -1
  77. package/dist/__tests__/mcp-readiness.test.js +0 -267
  78. package/dist/__tests__/mcp-readiness.test.js.map +0 -1
  79. package/dist/__tests__/mcp-registration-cli.test.d.ts +0 -2
  80. package/dist/__tests__/mcp-registration-cli.test.d.ts.map +0 -1
  81. package/dist/__tests__/mcp-registration-cli.test.js +0 -71
  82. package/dist/__tests__/mcp-registration-cli.test.js.map +0 -1
  83. package/dist/__tests__/mcp-registration.test.d.ts +0 -2
  84. package/dist/__tests__/mcp-registration.test.d.ts.map +0 -1
  85. package/dist/__tests__/mcp-registration.test.js +0 -426
  86. package/dist/__tests__/mcp-registration.test.js.map +0 -1
  87. package/dist/__tests__/model-scan-runner.test.d.ts +0 -2
  88. package/dist/__tests__/model-scan-runner.test.d.ts.map +0 -1
  89. package/dist/__tests__/model-scan-runner.test.js +0 -67
  90. package/dist/__tests__/model-scan-runner.test.js.map +0 -1
  91. package/dist/__tests__/network-diagnostics.test.d.ts +0 -2
  92. package/dist/__tests__/network-diagnostics.test.d.ts.map +0 -1
  93. package/dist/__tests__/network-diagnostics.test.js +0 -26
  94. package/dist/__tests__/network-diagnostics.test.js.map +0 -1
  95. package/dist/__tests__/observable-map.test.d.ts +0 -2
  96. package/dist/__tests__/observable-map.test.d.ts.map +0 -1
  97. package/dist/__tests__/observable-map.test.js +0 -54
  98. package/dist/__tests__/observable-map.test.js.map +0 -1
  99. package/dist/__tests__/provider-auth-preflight.test.d.ts +0 -2
  100. package/dist/__tests__/provider-auth-preflight.test.d.ts.map +0 -1
  101. package/dist/__tests__/provider-auth-preflight.test.js +0 -123
  102. package/dist/__tests__/provider-auth-preflight.test.js.map +0 -1
  103. package/dist/__tests__/provider-model-discovery.test.d.ts +0 -2
  104. package/dist/__tests__/provider-model-discovery.test.d.ts.map +0 -1
  105. package/dist/__tests__/provider-model-discovery.test.js +0 -472
  106. package/dist/__tests__/provider-model-discovery.test.js.map +0 -1
  107. package/dist/__tests__/remove-worktrees-if-clean.test.d.ts +0 -2
  108. package/dist/__tests__/remove-worktrees-if-clean.test.d.ts.map +0 -1
  109. package/dist/__tests__/remove-worktrees-if-clean.test.js +0 -221
  110. package/dist/__tests__/remove-worktrees-if-clean.test.js.map +0 -1
  111. package/dist/__tests__/resume-fallback-env.test.d.ts +0 -2
  112. package/dist/__tests__/resume-fallback-env.test.d.ts.map +0 -1
  113. package/dist/__tests__/resume-fallback-env.test.js +0 -28
  114. package/dist/__tests__/resume-fallback-env.test.js.map +0 -1
  115. package/dist/__tests__/run-journal.test.d.ts +0 -2
  116. package/dist/__tests__/run-journal.test.d.ts.map +0 -1
  117. package/dist/__tests__/run-journal.test.js +0 -121
  118. package/dist/__tests__/run-journal.test.js.map +0 -1
  119. package/dist/__tests__/run-start-gate.test.d.ts +0 -2
  120. package/dist/__tests__/run-start-gate.test.d.ts.map +0 -1
  121. package/dist/__tests__/run-start-gate.test.js +0 -29
  122. package/dist/__tests__/run-start-gate.test.js.map +0 -1
  123. package/dist/__tests__/runtime-capabilities-sync.test.d.ts +0 -2
  124. package/dist/__tests__/runtime-capabilities-sync.test.d.ts.map +0 -1
  125. package/dist/__tests__/runtime-capabilities-sync.test.js +0 -66
  126. package/dist/__tests__/runtime-capabilities-sync.test.js.map +0 -1
  127. package/dist/__tests__/runtime-config.test.d.ts +0 -2
  128. package/dist/__tests__/runtime-config.test.d.ts.map +0 -1
  129. package/dist/__tests__/runtime-config.test.js +0 -102
  130. package/dist/__tests__/runtime-config.test.js.map +0 -1
  131. package/dist/__tests__/runtime-presenter-heartbeat.test.d.ts +0 -2
  132. package/dist/__tests__/runtime-presenter-heartbeat.test.d.ts.map +0 -1
  133. package/dist/__tests__/runtime-presenter-heartbeat.test.js +0 -159
  134. package/dist/__tests__/runtime-presenter-heartbeat.test.js.map +0 -1
  135. package/dist/__tests__/sandbox-outbox.test.d.ts +0 -2
  136. package/dist/__tests__/sandbox-outbox.test.d.ts.map +0 -1
  137. package/dist/__tests__/sandbox-outbox.test.js +0 -214
  138. package/dist/__tests__/sandbox-outbox.test.js.map +0 -1
  139. package/dist/__tests__/sandbox-workflow-context.test.d.ts +0 -2
  140. package/dist/__tests__/sandbox-workflow-context.test.d.ts.map +0 -1
  141. package/dist/__tests__/sandbox-workflow-context.test.js +0 -396
  142. package/dist/__tests__/sandbox-workflow-context.test.js.map +0 -1
  143. package/dist/__tests__/service-manager.test.d.ts +0 -2
  144. package/dist/__tests__/service-manager.test.d.ts.map +0 -1
  145. package/dist/__tests__/service-manager.test.js +0 -50
  146. package/dist/__tests__/service-manager.test.js.map +0 -1
  147. package/dist/__tests__/sleep-inhibitor.test.d.ts +0 -2
  148. package/dist/__tests__/sleep-inhibitor.test.d.ts.map +0 -1
  149. package/dist/__tests__/sleep-inhibitor.test.js +0 -236
  150. package/dist/__tests__/sleep-inhibitor.test.js.map +0 -1
  151. package/dist/__tests__/status-local-workspace.test.d.ts +0 -2
  152. package/dist/__tests__/status-local-workspace.test.d.ts.map +0 -1
  153. package/dist/__tests__/status-local-workspace.test.js +0 -121
  154. package/dist/__tests__/status-local-workspace.test.js.map +0 -1
  155. package/dist/__tests__/suspension-detector.test.d.ts +0 -2
  156. package/dist/__tests__/suspension-detector.test.d.ts.map +0 -1
  157. package/dist/__tests__/suspension-detector.test.js +0 -112
  158. package/dist/__tests__/suspension-detector.test.js.map +0 -1
  159. package/dist/__tests__/web-presenter-parent-events.test.d.ts +0 -2
  160. package/dist/__tests__/web-presenter-parent-events.test.d.ts.map +0 -1
  161. package/dist/__tests__/web-presenter-parent-events.test.js +0 -130
  162. package/dist/__tests__/web-presenter-parent-events.test.js.map +0 -1
  163. package/dist/__tests__/workspace-relocation.test.d.ts +0 -2
  164. package/dist/__tests__/workspace-relocation.test.d.ts.map +0 -1
  165. package/dist/__tests__/workspace-relocation.test.js +0 -66
  166. package/dist/__tests__/workspace-relocation.test.js.map +0 -1
  167. package/dist/__tests__/workspace-run-lease.test.d.ts +0 -2
  168. package/dist/__tests__/workspace-run-lease.test.d.ts.map +0 -1
  169. package/dist/__tests__/workspace-run-lease.test.js +0 -230
  170. package/dist/__tests__/workspace-run-lease.test.js.map +0 -1
  171. package/dist/__tests__/ws-client-heartbeat-volatile.test.d.ts +0 -2
  172. package/dist/__tests__/ws-client-heartbeat-volatile.test.d.ts.map +0 -1
  173. package/dist/__tests__/ws-client-heartbeat-volatile.test.js +0 -61
  174. package/dist/__tests__/ws-client-heartbeat-volatile.test.js.map +0 -1
  175. package/dist/__tests__/ws-client-heartbeat.integration.test.d.ts +0 -2
  176. package/dist/__tests__/ws-client-heartbeat.integration.test.d.ts.map +0 -1
  177. package/dist/__tests__/ws-client-heartbeat.integration.test.js +0 -109
  178. package/dist/__tests__/ws-client-heartbeat.integration.test.js.map +0 -1
  179. package/dist/__tests__/ws-client-user-message-ack.integration.test.d.ts +0 -2
  180. package/dist/__tests__/ws-client-user-message-ack.integration.test.d.ts.map +0 -1
  181. package/dist/__tests__/ws-client-user-message-ack.integration.test.js +0 -167
  182. package/dist/__tests__/ws-client-user-message-ack.integration.test.js.map +0 -1
  183. package/dist/aiden-system-prompt.d.ts +0 -6
  184. package/dist/aiden-system-prompt.d.ts.map +0 -1
  185. package/dist/aiden-system-prompt.js +0 -6
  186. package/dist/aiden-system-prompt.js.map +0 -1
  187. package/dist/binding-switch-git.d.ts +0 -26
  188. package/dist/binding-switch-git.d.ts.map +0 -1
  189. package/dist/binding-switch-git.js +0 -973
  190. package/dist/binding-switch-git.js.map +0 -1
  191. package/dist/cli-ensure-install.d.ts +0 -39
  192. package/dist/cli-ensure-install.d.ts.map +0 -1
  193. package/dist/cli-ensure-install.js +0 -133
  194. package/dist/cli-ensure-install.js.map +0 -1
  195. package/dist/cli-executable.d.ts +0 -97
  196. package/dist/cli-executable.d.ts.map +0 -1
  197. package/dist/cli-executable.js +0 -432
  198. package/dist/cli-executable.js.map +0 -1
  199. package/dist/cli-help.d.ts +0 -7
  200. package/dist/cli-help.d.ts.map +0 -1
  201. package/dist/cli-help.js +0 -49
  202. package/dist/cli-help.js.map +0 -1
  203. package/dist/computer-readiness.d.ts +0 -42
  204. package/dist/computer-readiness.d.ts.map +0 -1
  205. package/dist/computer-readiness.js +0 -191
  206. package/dist/computer-readiness.js.map +0 -1
  207. package/dist/core-agent.d.ts +0 -47
  208. package/dist/core-agent.d.ts.map +0 -1
  209. package/dist/core-agent.js +0 -364
  210. package/dist/core-agent.js.map +0 -1
  211. package/dist/daemon.d.ts +0 -392
  212. package/dist/daemon.d.ts.map +0 -1
  213. package/dist/daemon.js +0 -4711
  214. package/dist/daemon.js.map +0 -1
  215. package/dist/event-outbox.d.ts +0 -83
  216. package/dist/event-outbox.d.ts.map +0 -1
  217. package/dist/event-outbox.js +0 -440
  218. package/dist/event-outbox.js.map +0 -1
  219. package/dist/fake-provider-cli.d.ts +0 -13
  220. package/dist/fake-provider-cli.d.ts.map +0 -1
  221. package/dist/fake-provider-cli.js +0 -53
  222. package/dist/fake-provider-cli.js.map +0 -1
  223. package/dist/generated-images.d.ts +0 -2
  224. package/dist/generated-images.d.ts.map +0 -1
  225. package/dist/generated-images.js +0 -2
  226. package/dist/generated-images.js.map +0 -1
  227. package/dist/index.d.ts +0 -6
  228. package/dist/index.d.ts.map +0 -1
  229. package/dist/index.js +0 -209
  230. package/dist/index.js.map +0 -1
  231. package/dist/lifecycle-logger.d.ts +0 -25
  232. package/dist/lifecycle-logger.d.ts.map +0 -1
  233. package/dist/lifecycle-logger.js +0 -73
  234. package/dist/lifecycle-logger.js.map +0 -1
  235. package/dist/local-skill-scan.d.ts +0 -21
  236. package/dist/local-skill-scan.d.ts.map +0 -1
  237. package/dist/local-skill-scan.js +0 -109
  238. package/dist/local-skill-scan.js.map +0 -1
  239. package/dist/local-workspace-migration.d.ts +0 -68
  240. package/dist/local-workspace-migration.d.ts.map +0 -1
  241. package/dist/local-workspace-migration.js +0 -157
  242. package/dist/local-workspace-migration.js.map +0 -1
  243. package/dist/mcp-readiness.d.ts +0 -59
  244. package/dist/mcp-readiness.d.ts.map +0 -1
  245. package/dist/mcp-readiness.js +0 -202
  246. package/dist/mcp-readiness.js.map +0 -1
  247. package/dist/mcp-registration.d.ts +0 -75
  248. package/dist/mcp-registration.d.ts.map +0 -1
  249. package/dist/mcp-registration.js +0 -563
  250. package/dist/mcp-registration.js.map +0 -1
  251. package/dist/model-scan-runner.d.ts +0 -15
  252. package/dist/model-scan-runner.d.ts.map +0 -1
  253. package/dist/model-scan-runner.js +0 -51
  254. package/dist/model-scan-runner.js.map +0 -1
  255. package/dist/network-diagnostics.d.ts +0 -8
  256. package/dist/network-diagnostics.d.ts.map +0 -1
  257. package/dist/network-diagnostics.js +0 -56
  258. package/dist/network-diagnostics.js.map +0 -1
  259. package/dist/observable-map.d.ts +0 -25
  260. package/dist/observable-map.d.ts.map +0 -1
  261. package/dist/observable-map.js +0 -42
  262. package/dist/observable-map.js.map +0 -1
  263. package/dist/provider-auth-preflight.d.ts +0 -22
  264. package/dist/provider-auth-preflight.d.ts.map +0 -1
  265. package/dist/provider-auth-preflight.js +0 -110
  266. package/dist/provider-auth-preflight.js.map +0 -1
  267. package/dist/provider-model-discovery.d.ts +0 -38
  268. package/dist/provider-model-discovery.d.ts.map +0 -1
  269. package/dist/provider-model-discovery.js +0 -519
  270. package/dist/provider-model-discovery.js.map +0 -1
  271. package/dist/resume-fallback-env.d.ts +0 -20
  272. package/dist/resume-fallback-env.d.ts.map +0 -1
  273. package/dist/resume-fallback-env.js +0 -30
  274. package/dist/resume-fallback-env.js.map +0 -1
  275. package/dist/run-journal.d.ts +0 -53
  276. package/dist/run-journal.d.ts.map +0 -1
  277. package/dist/run-journal.js +0 -193
  278. package/dist/run-journal.js.map +0 -1
  279. package/dist/run-start-gate.d.ts +0 -9
  280. package/dist/run-start-gate.d.ts.map +0 -1
  281. package/dist/run-start-gate.js +0 -24
  282. package/dist/run-start-gate.js.map +0 -1
  283. package/dist/runtime-backends.d.ts +0 -2
  284. package/dist/runtime-backends.d.ts.map +0 -1
  285. package/dist/runtime-backends.js +0 -2
  286. package/dist/runtime-backends.js.map +0 -1
  287. package/dist/runtime-capabilities-sync.d.ts +0 -33
  288. package/dist/runtime-capabilities-sync.d.ts.map +0 -1
  289. package/dist/runtime-capabilities-sync.js +0 -56
  290. package/dist/runtime-capabilities-sync.js.map +0 -1
  291. package/dist/runtime-config.d.ts +0 -24
  292. package/dist/runtime-config.d.ts.map +0 -1
  293. package/dist/runtime-config.js +0 -124
  294. package/dist/runtime-config.js.map +0 -1
  295. package/dist/sandbox-outbox.d.ts +0 -122
  296. package/dist/sandbox-outbox.d.ts.map +0 -1
  297. package/dist/sandbox-outbox.js +0 -180
  298. package/dist/sandbox-outbox.js.map +0 -1
  299. package/dist/sandbox.d.ts +0 -44
  300. package/dist/sandbox.d.ts.map +0 -1
  301. package/dist/sandbox.js +0 -438
  302. package/dist/sandbox.js.map +0 -1
  303. package/dist/service-manager.d.ts +0 -28
  304. package/dist/service-manager.d.ts.map +0 -1
  305. package/dist/service-manager.js +0 -259
  306. package/dist/service-manager.js.map +0 -1
  307. package/dist/sleep-inhibitor.d.ts +0 -111
  308. package/dist/sleep-inhibitor.d.ts.map +0 -1
  309. package/dist/sleep-inhibitor.js +0 -412
  310. package/dist/sleep-inhibitor.js.map +0 -1
  311. package/dist/suspension-detector.d.ts +0 -48
  312. package/dist/suspension-detector.d.ts.map +0 -1
  313. package/dist/suspension-detector.js +0 -89
  314. package/dist/suspension-detector.js.map +0 -1
  315. package/dist/types.d.ts +0 -6
  316. package/dist/types.d.ts.map +0 -1
  317. package/dist/types.js +0 -6
  318. package/dist/types.js.map +0 -1
  319. package/dist/updater.d.ts +0 -15
  320. package/dist/updater.d.ts.map +0 -1
  321. package/dist/updater.js +0 -50
  322. package/dist/updater.js.map +0 -1
  323. package/dist/version.d.ts +0 -2
  324. package/dist/version.d.ts.map +0 -1
  325. package/dist/version.js +0 -2
  326. package/dist/version.js.map +0 -1
  327. package/dist/web-presenter.d.ts +0 -55
  328. package/dist/web-presenter.d.ts.map +0 -1
  329. package/dist/web-presenter.js +0 -265
  330. package/dist/web-presenter.js.map +0 -1
  331. package/dist/workspace-relocation.d.ts +0 -22
  332. package/dist/workspace-relocation.d.ts.map +0 -1
  333. package/dist/workspace-relocation.js +0 -90
  334. package/dist/workspace-relocation.js.map +0 -1
  335. package/dist/workspace-run-lease.d.ts +0 -97
  336. package/dist/workspace-run-lease.d.ts.map +0 -1
  337. package/dist/workspace-run-lease.js +0 -241
  338. package/dist/workspace-run-lease.js.map +0 -1
  339. package/dist/ws-client.d.ts +0 -194
  340. package/dist/ws-client.d.ts.map +0 -1
  341. package/dist/ws-client.js +0 -282
  342. package/dist/ws-client.js.map +0 -1
package/dist/index.cjs CHANGED
@@ -15167,6 +15167,10 @@ function hasRunSessionEnv(env) {
15167
15167
  env.ALAN_WS_URL && env.ALAN_SESSION_ID && env.ALAN_TASK_ID && env.ALAN_SESSION_TOKEN && env.ALAN_TASK !== void 0
15168
15168
  );
15169
15169
  }
15170
+ function resolveInstallConfigurationMode(args, configured) {
15171
+ if (args.includes("--setup-token")) return "setup";
15172
+ return configured.runtimeId && configured.runtimeToken ? "reuse" : "login";
15173
+ }
15170
15174
  function resolveCommand(args, env) {
15171
15175
  const [command, ...commandArgs] = args;
15172
15176
  if (!command) {
@@ -15447,7 +15451,7 @@ function describeError(error61) {
15447
15451
  }
15448
15452
 
15449
15453
  // src/version.ts
15450
- var AGENT_VERSION = "0.1.89";
15454
+ var AGENT_VERSION = "0.1.91";
15451
15455
 
15452
15456
  // src/daemon-worktree.ts
15453
15457
  var import_node_child_process3 = require("child_process");
@@ -35648,14 +35652,14 @@ function configuredConfigPathFromEnvironment() {
35648
35652
  const explicit = process.env.ALAN_AGENT_CONFIG_PATH?.trim() || process.env.ALAN_AGENT_CONFIG?.trim();
35649
35653
  return explicit || void 0;
35650
35654
  }
35651
- function resolveIsolatedAgentBaseDir(profile) {
35655
+ function resolveIsolatedAgentBaseDir(profile, homeDirectory2 = (0, import_node_os4.homedir)()) {
35652
35656
  switch (profile) {
35653
35657
  case "local":
35654
- return (0, import_node_path5.join)((0, import_node_os4.homedir)(), ".alan-dev", "agent");
35658
+ return (0, import_node_path5.join)(homeDirectory2, ".alan-dev", "agent");
35655
35659
  case "staging":
35656
- return (0, import_node_path5.join)((0, import_node_os4.homedir)(), ".alan-staging", "agent");
35660
+ return (0, import_node_path5.join)(homeDirectory2, ".alan-staging", "agent");
35657
35661
  case "custom":
35658
- return (0, import_node_path5.join)((0, import_node_os4.homedir)(), ".alan-prod", "agent");
35662
+ return (0, import_node_path5.join)(homeDirectory2, ".alan-prod", "agent");
35659
35663
  default:
35660
35664
  return null;
35661
35665
  }
@@ -35732,6 +35736,9 @@ function migrateLegacyAgentConfig(input2) {
35732
35736
  return false;
35733
35737
  }
35734
35738
  }
35739
+ function resolveAgentConfigDirectory(profile = "production", homeDirectory2 = (0, import_node_os4.homedir)()) {
35740
+ return resolveIsolatedAgentBaseDir(profile, homeDirectory2) ?? (0, import_node_path5.join)(homeDirectory2, ".alan", "agent");
35741
+ }
35735
35742
  function resolveAgentConfigPath(input2) {
35736
35743
  if (input2?.explicitPath?.trim()) return input2.explicitPath.trim();
35737
35744
  const profile = normalizeAgentEndpointProfile(
@@ -35740,10 +35747,8 @@ function resolveAgentConfigPath(input2) {
35740
35747
  if (input2?.baseDir !== void 0) {
35741
35748
  return (0, import_node_path5.join)(input2.baseDir, resolveAgentConfigFileName(profile));
35742
35749
  }
35743
- const isolatedBaseDir = profile === "production" ? null : resolveIsolatedAgentBaseDir(profile);
35744
- if (isolatedBaseDir) return (0, import_node_path5.join)(isolatedBaseDir, "config.json");
35745
- migrateLegacyAgentConfig({ profile });
35746
- return (0, import_node_path5.join)(DEFAULT_AGENT_DIR, resolveAgentConfigFileName(profile));
35750
+ if (profile === "production") migrateLegacyAgentConfig({ profile });
35751
+ return (0, import_node_path5.join)(resolveAgentConfigDirectory(profile), "config.json");
35747
35752
  }
35748
35753
  function configExistsAtPath(configPath) {
35749
35754
  return (0, import_node_fs5.existsSync)(configPath);
@@ -42790,6 +42795,7 @@ function buildCodexEffortArgs(selectedEffortLevel, options) {
42790
42795
  return ["-c", `model_reasoning_effort=${level}`];
42791
42796
  }
42792
42797
  var CODEX_STARTUP_TIMEOUT_MS = 3e5;
42798
+ var ALAN_MCP_STARTUP_TIMEOUT_SEC = 30;
42793
42799
  function buildCodexManagedMcpArgs(registration) {
42794
42800
  const serverName = managedMcpServerName(registration);
42795
42801
  return [
@@ -42797,7 +42803,11 @@ function buildCodexManagedMcpArgs(registration) {
42797
42803
  "-c",
42798
42804
  `mcp_servers.${serverName}.url=${JSON.stringify(registration.url)}`,
42799
42805
  "-c",
42800
- `mcp_servers.${serverName}.env_http_headers.x-alan-run-reference=${JSON.stringify(ALAN_RUN_REFERENCE_ENV)}`
42806
+ `mcp_servers.${serverName}.env_http_headers.x-alan-run-reference=${JSON.stringify(ALAN_RUN_REFERENCE_ENV)}`,
42807
+ "-c",
42808
+ `mcp_servers.${serverName}.required=true`,
42809
+ "-c",
42810
+ `mcp_servers.${serverName}.startup_timeout_sec=${ALAN_MCP_STARTUP_TIMEOUT_SEC}`
42801
42811
  ];
42802
42812
  }
42803
42813
  function createCodexRuntimeBackend(command = "codex", defaultArgs = []) {
@@ -49460,7 +49470,7 @@ function bindConfigPath(args) {
49460
49470
  return boundAgentConfigPath;
49461
49471
  }
49462
49472
  function getConfigPath() {
49463
- return process.env.ALAN_AGENT_CONFIG_PATH ?? boundAgentConfigPath ?? resolveAgentConfigPath({ profile: "production" });
49473
+ return boundAgentConfigPath ?? process.env.ALAN_AGENT_CONFIG_PATH ?? resolveAgentConfigPath({ profile: "production" });
49464
49474
  }
49465
49475
  function getEndpointDefaultsPath() {
49466
49476
  return process.env.ALAN_AGENT_ENDPOINTS_PATH ?? (0, import_node_path11.join)((0, import_node_path11.dirname)(getConfigPath()), "endpoints.json");
@@ -49515,7 +49525,7 @@ function readLocalDaemonMaintenanceLease(configPath, nowMs = Date.now()) {
49515
49525
  if (!(0, import_node_fs13.existsSync)(path2)) return null;
49516
49526
  try {
49517
49527
  const lease = JSON.parse((0, import_node_fs13.readFileSync)(path2, "utf8"));
49518
- if (lease.version !== 1 || typeof lease.id !== "string" || lease.reason !== "credential_cleanup" && lease.reason !== "daemon_startup" && lease.reason !== "watchdog" || !(lease.reason === "credential_cleanup" && lease.expiresAtMs === null || typeof lease.expiresAtMs === "number" && Number.isFinite(lease.expiresAtMs))) {
49528
+ if (lease.version !== 1 || typeof lease.id !== "string" || lease.reason !== "credential_cleanup" && lease.reason !== "credential_swap" && lease.reason !== "daemon_startup" && lease.reason !== "watchdog" || !(lease.reason === "credential_cleanup" && lease.expiresAtMs === null || typeof lease.expiresAtMs === "number" && Number.isFinite(lease.expiresAtMs))) {
49519
49529
  throw new Error("invalid maintenance lease");
49520
49530
  }
49521
49531
  if (lease.reason !== "credential_cleanup" && lease.expiresAtMs <= nowMs) {
@@ -76529,6 +76539,7 @@ async function createRuntimeSetupGrant(input2) {
76529
76539
  }
76530
76540
  async function exchangeRuntimeSetupGrant(input2) {
76531
76541
  const registrationAttemptId = getOrCreateSetupAttemptId(input2.setupToken);
76542
+ const signal = AbortSignal.timeout(15e3);
76532
76543
  const registrationInit = {
76533
76544
  method: "POST",
76534
76545
  headers: { "content-type": "application/json" },
@@ -76547,7 +76558,8 @@ async function exchangeRuntimeSetupGrant(input2) {
76547
76558
  ...await collectRuntimeMetadataWithProviderLimits(),
76548
76559
  installationId: input2.installationId
76549
76560
  }
76550
- })
76561
+ }),
76562
+ signal
76551
76563
  };
76552
76564
  let response;
76553
76565
  let transportError;
@@ -79398,11 +79410,24 @@ async function startDaemon(args) {
79398
79410
  releaseStartupLease();
79399
79411
  throw error61;
79400
79412
  }
79413
+ let runtimeCredentialOperationTail = Promise.resolve();
79414
+ const runCredentialOperation = (operation) => {
79415
+ const result = runtimeCredentialOperationTail.catch(() => {
79416
+ }).then(operation);
79417
+ runtimeCredentialOperationTail = result.then(
79418
+ () => {
79419
+ },
79420
+ () => {
79421
+ }
79422
+ );
79423
+ return result;
79424
+ };
79401
79425
  let runtimeRenewalInFlight = null;
79402
79426
  const renewRuntimeLease = () => {
79403
79427
  if (runtimeRenewalInFlight) return runtimeRenewalInFlight;
79404
- const attempt = (async () => {
79405
- if (!stored.apiUrl || !runtimeRenewalToken) {
79428
+ const attempt = runCredentialOperation(async () => {
79429
+ const renewalToken = runtimeRenewalToken;
79430
+ if (!stored.apiUrl || !renewalToken) {
79406
79431
  return false;
79407
79432
  }
79408
79433
  let response = null;
@@ -79412,7 +79437,7 @@ async function startDaemon(args) {
79412
79437
  response = await fetch(`${stored.apiUrl}/public/runtimes/${runtimeId}/tokens/renew`, {
79413
79438
  method: "POST",
79414
79439
  headers: {
79415
- authorization: `Bearer ${runtimeRenewalToken}`,
79440
+ authorization: `Bearer ${renewalToken}`,
79416
79441
  "content-type": "application/json"
79417
79442
  },
79418
79443
  body: "{}",
@@ -79448,7 +79473,7 @@ async function startDaemon(args) {
79448
79473
  return false;
79449
79474
  }
79450
79475
  const current = readConfig();
79451
- if (current.runtimeId !== runtimeId || current.runtimeRenewalToken !== runtimeRenewalToken) {
79476
+ if (current.runtimeId !== runtimeId || current.runtimeRenewalToken !== renewalToken) {
79452
79477
  rememberConnectErrorCode("runtime_renewal_superseded");
79453
79478
  lastConnectError = "Runtime credentials changed while renewal was in progress";
79454
79479
  pushLog("runtime-renewal-superseded");
@@ -79468,7 +79493,7 @@ async function startDaemon(args) {
79468
79493
  pushLog("runtime-renewal-succeeded");
79469
79494
  socket.connect();
79470
79495
  return true;
79471
- })();
79496
+ });
79472
79497
  runtimeRenewalInFlight = attempt;
79473
79498
  void attempt.finally(() => {
79474
79499
  if (runtimeRenewalInFlight === attempt) runtimeRenewalInFlight = null;
@@ -79476,10 +79501,18 @@ async function startDaemon(args) {
79476
79501
  });
79477
79502
  return attempt;
79478
79503
  };
79504
+ let queueIdentityRestart = () => {
79505
+ };
79479
79506
  let runtimeSetupInFlight = null;
79480
79507
  const adoptRuntimeSetupGrant = (input2) => {
79481
79508
  if (runtimeSetupInFlight) return runtimeSetupInFlight;
79482
- const attempt = (async () => {
79509
+ const attempt = runCredentialOperation(async () => {
79510
+ const activeRunCount = activeAgents.size + pendingRunStarts.size;
79511
+ if (activeRunCount > 0) {
79512
+ throw new Error(
79513
+ `credential setup is deferred while ${activeRunCount} active run${activeRunCount === 1 ? " finishes" : "s finish"}`
79514
+ );
79515
+ }
79483
79516
  const current = readConfig();
79484
79517
  if (current.runtimeId !== runtimeId || current.installationId !== installationId || input2.installationId !== installationId) {
79485
79518
  throw new Error("credential setup does not belong to this daemon installation");
@@ -79489,7 +79522,23 @@ async function startDaemon(args) {
79489
79522
  }
79490
79523
  const bundle = await exchangeRuntimeSetupGrant(input2);
79491
79524
  if (bundle.runtimeId !== runtimeId) {
79492
- throw new Error("credential setup resolved to a different runtime");
79525
+ writeConfig({
79526
+ ...current,
79527
+ runtimeId: bundle.runtimeId,
79528
+ runtimeToken: bundle.runtimeToken,
79529
+ runtimeRenewalToken: bundle.runtimeRenewalToken,
79530
+ displayName: bundle.displayName
79531
+ });
79532
+ clearPendingSetupIntent();
79533
+ pushLog(
79534
+ `runtime-identity-switch-queued from=${runtimeId} to=${bundle.runtimeId} generation=${bundle.credentialGeneration}`
79535
+ );
79536
+ const restartTimer = setTimeout(queueIdentityRestart, 100);
79537
+ restartTimer.unref?.();
79538
+ return {
79539
+ runtimeId: bundle.runtimeId,
79540
+ credentialGeneration: bundle.credentialGeneration
79541
+ };
79493
79542
  }
79494
79543
  writeConfig({
79495
79544
  ...current,
@@ -79526,7 +79575,7 @@ async function startDaemon(args) {
79526
79575
  runtimeId: bundle.runtimeId,
79527
79576
  credentialGeneration: bundle.credentialGeneration
79528
79577
  };
79529
- })();
79578
+ });
79530
79579
  runtimeSetupInFlight = attempt;
79531
79580
  void attempt.finally(() => {
79532
79581
  if (runtimeSetupInFlight === attempt) runtimeSetupInFlight = null;
@@ -79741,6 +79790,16 @@ async function startDaemon(args) {
79741
79790
  const wsHint = isLocalEndpoint(wsUrl) ? ` Nothing is listening at ${wsUrl}. For local dev run setup with --profile local and start the stack (WS on ws://localhost:8401).` : ` Verify wsUrl in ${getConfigPath()} and that you can reach ${wsUrl}.`;
79742
79791
  console.warn("[alan-agent] Daemon connection error:", `${error61.message}.${wsHint}`);
79743
79792
  });
79793
+ socket.on("connection_directive", (value2) => {
79794
+ if (!value2 || typeof value2 !== "object") return;
79795
+ const directive = value2;
79796
+ if (directive.retryable !== false || typeof directive.code !== "string") return;
79797
+ rememberConnectErrorCode(directive.code);
79798
+ if (typeof directive.reason === "string") lastConnectError = directive.reason;
79799
+ pushLog(
79800
+ `connection_directive ${directive.code}${lastConnectError ? ` reason=${lastConnectError}` : ""}`
79801
+ );
79802
+ });
79744
79803
  socket.on("disconnect", (reason) => {
79745
79804
  setConnectedRuntimeSocket(null);
79746
79805
  relocationInFlight.clear();
@@ -80093,6 +80152,9 @@ async function startDaemon(args) {
80093
80152
  queueFullShutdown = () => {
80094
80153
  void stop().then(() => controller.whenExternallyStopped?.());
80095
80154
  };
80155
+ queueIdentityRestart = () => {
80156
+ void stop().then(() => controller.whenExternallyStopped?.("runtime_identity_changed"));
80157
+ };
80096
80158
  return controller;
80097
80159
  }
80098
80160
 
@@ -80191,17 +80253,23 @@ async function setupDaemon(args) {
80191
80253
  if (!liveConfig.localApiToken) {
80192
80254
  throw new Error("running daemon could not be authenticated for credential setup");
80193
80255
  }
80256
+ const liveSetup = {
80257
+ ...setup,
80258
+ apiUrl: liveConfig.apiUrl ?? setup.apiUrl,
80259
+ wsUrl: liveConfig.wsUrl ?? setup.wsUrl,
80260
+ endpointProfile: liveConfig.endpointProfile ?? setup.endpointProfile
80261
+ };
80194
80262
  const body2 = await handoffRuntimeSetupGrant({
80195
80263
  port: localApiPort,
80196
80264
  localApiToken: liveConfig.localApiToken,
80197
- setup
80265
+ setup: liveSetup
80198
80266
  });
80199
80267
  console.info("[alan-agent] Runtime credentials adopted by running daemon", {
80200
80268
  runtimeId: body2.runtimeId,
80201
80269
  credentialGeneration: body2.credentialGeneration,
80202
80270
  configPath: getConfigPath()
80203
80271
  });
80204
- return;
80272
+ return { daemonAlreadyRunning: true };
80205
80273
  }
80206
80274
  if (readLocalDaemonOwnerLease(getConfigPath())) {
80207
80275
  throw new Error(
@@ -80215,7 +80283,7 @@ async function setupDaemon(args) {
80215
80283
  if (setupToken && error61 instanceof RuntimeSetupGrantExpiredError) {
80216
80284
  console.info("[alan-agent] Setup link expired; continuing with browser authorization");
80217
80285
  await loginWithDeviceCode(args);
80218
- return;
80286
+ return { daemonAlreadyRunning: false };
80219
80287
  }
80220
80288
  throw error61;
80221
80289
  }
@@ -80240,6 +80308,7 @@ async function setupDaemon(args) {
80240
80308
  runtimeId: body.runtimeId,
80241
80309
  configPath: getConfigPath()
80242
80310
  });
80311
+ return { daemonAlreadyRunning: false };
80243
80312
  }
80244
80313
  async function loginWithDeviceCode(args) {
80245
80314
  bindConfigPath(args);
@@ -80428,8 +80497,8 @@ async function runDaemon(args) {
80428
80497
  return;
80429
80498
  }
80430
80499
  const controller = await startDaemon(args);
80431
- const shutdown = () => {
80432
- void controller.stop().finally(() => process.exit(0));
80500
+ const shutdown = (reason) => {
80501
+ void controller.stop().finally(() => process.exit(daemonExternalStopExitCode(reason)));
80433
80502
  };
80434
80503
  controller.whenExternallyStopped = shutdown;
80435
80504
  process.once("SIGINT", shutdown);
@@ -80437,6 +80506,9 @@ async function runDaemon(args) {
80437
80506
  await new Promise(() => {
80438
80507
  });
80439
80508
  }
80509
+ function daemonExternalStopExitCode(reason) {
80510
+ return reason === "runtime_identity_changed" ? 1 : 0;
80511
+ }
80440
80512
  async function recoverDaemonConnection(args = [], options) {
80441
80513
  bindConfigPath(args);
80442
80514
  const getStatus = async () => {
@@ -82078,107 +82150,728 @@ function runMcpIntegrationCommand(args, options = {}) {
82078
82150
  throw new Error(`Unknown integrations action: ${action}`);
82079
82151
  }
82080
82152
 
82081
- // src/lifecycle-logger.ts
82082
- var AgentLifecycleLogger = class _AgentLifecycleLogger {
82083
- context;
82084
- constructor(context = {}) {
82085
- this.context = normalizeContext(context);
82086
- }
82087
- setContext(context) {
82088
- this.context = normalizeContext({ ...this.context, ...context });
82089
- }
82090
- child(context) {
82091
- return new _AgentLifecycleLogger({ ...this.context, ...context });
82153
+ // src/service-manager.ts
82154
+ var import_node_child_process9 = require("child_process");
82155
+ var import_node_fs25 = require("fs");
82156
+ var import_node_os16 = require("os");
82157
+ var import_node_path27 = require("path");
82158
+ var SERVICE_LABEL = "ai.tryalan.agent";
82159
+ var SYSTEMD_UNIT = "alan-agent.service";
82160
+ var WINDOWS_TASK = "Alan Agent";
82161
+ function xml(value2) {
82162
+ return value2.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&apos;");
82163
+ }
82164
+ function systemdArg(value2) {
82165
+ return `"${value2.replaceAll("\\", "\\\\").replaceAll('"', '\\"')}"`;
82166
+ }
82167
+ function powershellLiteral(value2) {
82168
+ return `'${value2.replaceAll("'", "''")}'`;
82169
+ }
82170
+ function serviceNames(profile) {
82171
+ if (profile === "production") {
82172
+ return { launchd: SERVICE_LABEL, systemd: SYSTEMD_UNIT, windows: WINDOWS_TASK };
82092
82173
  }
82093
- debug(event, fields = {}) {
82094
- this.log("debug", event, fields);
82174
+ const suffix = profile === "custom" ? "prod" : profile;
82175
+ const title = `${suffix[0]?.toUpperCase()}${suffix.slice(1)}`;
82176
+ return {
82177
+ launchd: `${SERVICE_LABEL}.${suffix}`,
82178
+ systemd: `alan-agent-${suffix}.service`,
82179
+ windows: `${WINDOWS_TASK} ${title}`
82180
+ };
82181
+ }
82182
+ function buildDaemonServicePlan(input2) {
82183
+ const daemonArgs = [input2.nodeExecutable, input2.cliEntry, "daemon", "--profile", input2.profile];
82184
+ const names = serviceNames(input2.profile);
82185
+ if (input2.platform === "darwin") {
82186
+ const userId = input2.userId ?? process.getuid?.();
82187
+ if (userId === void 0) throw new Error("Cannot determine the current macOS user ID");
82188
+ const domain2 = `gui/${userId}`;
82189
+ const serviceTarget = `${domain2}/${names.launchd}`;
82190
+ const manifestPath = (0, import_node_path27.join)(input2.homeDir, "Library", "LaunchAgents", `${names.launchd}.plist`);
82191
+ const logDir = (0, import_node_path27.join)(resolveAgentConfigDirectory(input2.profile, input2.homeDir), "logs");
82192
+ const programArguments = daemonArgs.map((arg) => ` <string>${xml(arg)}</string>`).join("\n");
82193
+ const environmentEntries = Object.entries(input2.environment ?? {}).map(([key, value2]) => ` <key>${xml(key)}</key>
82194
+ <string>${xml(value2)}</string>`).join("\n");
82195
+ const environmentBlock = environmentEntries ? ` <key>EnvironmentVariables</key>
82196
+ <dict>
82197
+ ${environmentEntries}
82198
+ </dict>
82199
+ ` : "";
82200
+ const manifest = `<?xml version="1.0" encoding="UTF-8"?>
82201
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
82202
+ <plist version="1.0">
82203
+ <dict>
82204
+ <key>Label</key>
82205
+ <string>${names.launchd}</string>
82206
+ <key>ProgramArguments</key>
82207
+ <array>
82208
+ ${programArguments}
82209
+ </array>
82210
+ ${environmentBlock} <key>RunAtLoad</key>
82211
+ <true/>
82212
+ <key>KeepAlive</key>
82213
+ <dict>
82214
+ <key>SuccessfulExit</key>
82215
+ <false/>
82216
+ </dict>
82217
+ <key>ThrottleInterval</key>
82218
+ <integer>5</integer>
82219
+ <key>StandardOutPath</key>
82220
+ <string>${xml((0, import_node_path27.join)(logDir, "daemon.log"))}</string>
82221
+ <key>StandardErrorPath</key>
82222
+ <string>${xml((0, import_node_path27.join)(logDir, "daemon-error.log"))}</string>
82223
+ </dict>
82224
+ </plist>
82225
+ `;
82226
+ return {
82227
+ platform: "darwin",
82228
+ manifestPath,
82229
+ manifest,
82230
+ logDirectory: logDir,
82231
+ loadDefinitionCommands: [
82232
+ {
82233
+ command: "launchctl",
82234
+ args: ["bootstrap", domain2, manifestPath],
82235
+ tolerateFailure: true
82236
+ }
82237
+ ],
82238
+ reloadDefinitionCommands: [
82239
+ {
82240
+ command: "launchctl",
82241
+ args: ["bootout", domain2, manifestPath],
82242
+ tolerateFailure: true
82243
+ },
82244
+ {
82245
+ command: "launchctl",
82246
+ args: ["bootstrap", domain2, manifestPath],
82247
+ tolerateFailure: false
82248
+ }
82249
+ ],
82250
+ enableCommands: [
82251
+ {
82252
+ command: "launchctl",
82253
+ args: ["enable", serviceTarget],
82254
+ tolerateFailure: true
82255
+ }
82256
+ ],
82257
+ startCommands: [
82258
+ {
82259
+ command: "launchctl",
82260
+ args: ["kickstart", serviceTarget],
82261
+ tolerateFailure: false
82262
+ }
82263
+ ],
82264
+ stopCommands: [
82265
+ {
82266
+ command: "launchctl",
82267
+ args: ["kill", "SIGTERM", serviceTarget],
82268
+ tolerateFailure: true
82269
+ }
82270
+ ],
82271
+ replaceCommands: [
82272
+ {
82273
+ command: "launchctl",
82274
+ args: ["bootout", domain2, manifestPath],
82275
+ tolerateFailure: true
82276
+ },
82277
+ {
82278
+ command: "launchctl",
82279
+ args: ["bootstrap", domain2, manifestPath],
82280
+ tolerateFailure: false
82281
+ },
82282
+ {
82283
+ command: "launchctl",
82284
+ args: ["kickstart", "-k", serviceTarget],
82285
+ tolerateFailure: false
82286
+ }
82287
+ ],
82288
+ uninstallCommands: [
82289
+ {
82290
+ command: "launchctl",
82291
+ args: ["bootout", domain2, manifestPath],
82292
+ tolerateFailure: true
82293
+ }
82294
+ ],
82295
+ statusCommand: {
82296
+ command: "launchctl",
82297
+ args: ["print", serviceTarget],
82298
+ tolerateFailure: true
82299
+ },
82300
+ isActiveCommand: {
82301
+ command: "launchctl",
82302
+ args: ["print", serviceTarget],
82303
+ tolerateFailure: true
82304
+ },
82305
+ lingerStatusCommand: null
82306
+ };
82095
82307
  }
82096
- info(event, fields = {}) {
82097
- this.log("info", event, fields);
82308
+ if (input2.platform === "linux") {
82309
+ const manifestPath = (0, import_node_path27.join)(input2.homeDir, ".config", "systemd", "user", names.systemd);
82310
+ const environmentLines = Object.entries(input2.environment ?? {}).map(([key, value2]) => `Environment=${systemdArg(`${key}=${value2}`)}`).join("\n");
82311
+ const manifest = `[Unit]
82312
+ Description=Alan local agent daemon
82313
+ After=network-online.target
82314
+ Wants=network-online.target
82315
+ StartLimitIntervalSec=300
82316
+ StartLimitBurst=3
82317
+
82318
+ [Service]
82319
+ Type=simple
82320
+ ${environmentLines ? `${environmentLines}
82321
+ ` : ""}ExecStart=${daemonArgs.map(systemdArg).join(" ")}
82322
+ Restart=on-failure
82323
+ RestartSec=5
82324
+
82325
+ [Install]
82326
+ WantedBy=default.target
82327
+ `;
82328
+ return {
82329
+ platform: "linux",
82330
+ manifestPath,
82331
+ manifest,
82332
+ logDirectory: null,
82333
+ loadDefinitionCommands: [
82334
+ {
82335
+ command: "systemctl",
82336
+ args: ["--user", "daemon-reload"],
82337
+ tolerateFailure: false
82338
+ }
82339
+ ],
82340
+ reloadDefinitionCommands: [
82341
+ {
82342
+ command: "systemctl",
82343
+ args: ["--user", "daemon-reload"],
82344
+ tolerateFailure: false
82345
+ }
82346
+ ],
82347
+ enableCommands: [
82348
+ {
82349
+ command: "systemctl",
82350
+ args: ["--user", "enable", names.systemd],
82351
+ tolerateFailure: false
82352
+ }
82353
+ ],
82354
+ startCommands: [
82355
+ {
82356
+ command: "systemctl",
82357
+ args: ["--user", "start", names.systemd],
82358
+ tolerateFailure: false
82359
+ }
82360
+ ],
82361
+ stopCommands: [
82362
+ {
82363
+ command: "systemctl",
82364
+ args: ["--user", "stop", names.systemd],
82365
+ tolerateFailure: true
82366
+ }
82367
+ ],
82368
+ replaceCommands: [
82369
+ {
82370
+ command: "systemctl",
82371
+ args: ["--user", "daemon-reload"],
82372
+ tolerateFailure: false
82373
+ },
82374
+ {
82375
+ command: "systemctl",
82376
+ args: ["--user", "restart", names.systemd],
82377
+ tolerateFailure: false
82378
+ }
82379
+ ],
82380
+ uninstallCommands: [
82381
+ {
82382
+ command: "systemctl",
82383
+ args: ["--user", "disable", "--now", names.systemd],
82384
+ tolerateFailure: true
82385
+ },
82386
+ {
82387
+ command: "systemctl",
82388
+ args: ["--user", "daemon-reload"],
82389
+ tolerateFailure: false
82390
+ }
82391
+ ],
82392
+ statusCommand: {
82393
+ command: "systemctl",
82394
+ args: ["--user", "status", names.systemd, "--no-pager"],
82395
+ tolerateFailure: true
82396
+ },
82397
+ isActiveCommand: {
82398
+ command: "systemctl",
82399
+ args: ["--user", "is-active", names.systemd],
82400
+ tolerateFailure: true
82401
+ },
82402
+ lingerStatusCommand: {
82403
+ command: "loginctl",
82404
+ args: ["show-user", "$(id -un)", "-p", "Linger"],
82405
+ tolerateFailure: true
82406
+ }
82407
+ };
82098
82408
  }
82099
- warn(event, fields = {}) {
82100
- this.log("warn", event, fields);
82409
+ const environmentPrefix = Object.entries(input2.environment ?? {}).map(([key, value2]) => `$env:${key} = ${powershellLiteral(value2)}`).join("; ");
82410
+ const directArgument = [input2.cliEntry, "daemon", "--profile", input2.profile].map((part) => part.includes(" ") ? `"${part}"` : part).join(" ");
82411
+ const executable = powershellLiteral(environmentPrefix ? "powershell.exe" : input2.nodeExecutable);
82412
+ const argument = powershellLiteral(
82413
+ environmentPrefix ? `-NoProfile -NonInteractive -WindowStyle Hidden -Command "${environmentPrefix}; & ${powershellLiteral(input2.nodeExecutable)} ${powershellLiteral(input2.cliEntry)} daemon --profile ${input2.profile}"` : directArgument
82414
+ );
82415
+ const registerScript = [
82416
+ "$currentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name",
82417
+ `$action = New-ScheduledTaskAction -Execute ${executable} -Argument ${argument}`,
82418
+ "$trigger = New-ScheduledTaskTrigger -AtLogOn -User $currentUser",
82419
+ "$principal = New-ScheduledTaskPrincipal -UserId $currentUser -LogonType Interactive -RunLevel Limited",
82420
+ "$settings = New-ScheduledTaskSettingsSet -RestartCount 3 -RestartInterval (New-TimeSpan -Minutes 1) -ExecutionTimeLimit ([TimeSpan]::Zero)",
82421
+ `Register-ScheduledTask -TaskName ${powershellLiteral(names.windows)} -Action $action -Trigger $trigger -Principal $principal -Settings $settings -Force | Out-Null`
82422
+ ].join("; ");
82423
+ return {
82424
+ platform: "win32",
82425
+ manifestPath: null,
82426
+ manifest: null,
82427
+ logDirectory: null,
82428
+ loadDefinitionCommands: [
82429
+ {
82430
+ command: "powershell.exe",
82431
+ args: ["-NoProfile", "-NonInteractive", "-Command", registerScript],
82432
+ tolerateFailure: false
82433
+ }
82434
+ ],
82435
+ reloadDefinitionCommands: [
82436
+ {
82437
+ command: "powershell.exe",
82438
+ args: ["-NoProfile", "-NonInteractive", "-Command", registerScript],
82439
+ tolerateFailure: false
82440
+ }
82441
+ ],
82442
+ enableCommands: [],
82443
+ startCommands: [
82444
+ {
82445
+ command: "powershell.exe",
82446
+ args: [
82447
+ "-NoProfile",
82448
+ "-NonInteractive",
82449
+ "-Command",
82450
+ `Start-ScheduledTask -TaskName ${powershellLiteral(names.windows)}`
82451
+ ],
82452
+ tolerateFailure: false
82453
+ }
82454
+ ],
82455
+ stopCommands: [
82456
+ {
82457
+ command: "powershell.exe",
82458
+ args: [
82459
+ "-NoProfile",
82460
+ "-NonInteractive",
82461
+ "-Command",
82462
+ `Stop-ScheduledTask -TaskName ${powershellLiteral(names.windows)} -ErrorAction SilentlyContinue`
82463
+ ],
82464
+ tolerateFailure: true
82465
+ }
82466
+ ],
82467
+ replaceCommands: [
82468
+ {
82469
+ command: "powershell.exe",
82470
+ args: [
82471
+ "-NoProfile",
82472
+ "-NonInteractive",
82473
+ "-Command",
82474
+ `${registerScript}; Start-ScheduledTask -TaskName ${powershellLiteral(names.windows)}`
82475
+ ],
82476
+ tolerateFailure: false
82477
+ }
82478
+ ],
82479
+ uninstallCommands: [
82480
+ {
82481
+ command: "powershell.exe",
82482
+ args: [
82483
+ "-NoProfile",
82484
+ "-NonInteractive",
82485
+ "-Command",
82486
+ `Unregister-ScheduledTask -TaskName ${powershellLiteral(names.windows)} -Confirm:$false -ErrorAction SilentlyContinue`
82487
+ ],
82488
+ tolerateFailure: true
82489
+ }
82490
+ ],
82491
+ statusCommand: {
82492
+ command: "powershell.exe",
82493
+ args: [
82494
+ "-NoProfile",
82495
+ "-NonInteractive",
82496
+ "-Command",
82497
+ `Get-ScheduledTask -TaskName ${powershellLiteral(names.windows)} | Format-List TaskName,State`
82498
+ ],
82499
+ tolerateFailure: true
82500
+ },
82501
+ isActiveCommand: {
82502
+ command: "powershell.exe",
82503
+ args: [
82504
+ "-NoProfile",
82505
+ "-NonInteractive",
82506
+ "-Command",
82507
+ `(Get-ScheduledTask -TaskName ${powershellLiteral(names.windows)} -ErrorAction SilentlyContinue).State`
82508
+ ],
82509
+ tolerateFailure: true
82510
+ },
82511
+ lingerStatusCommand: null
82512
+ };
82513
+ }
82514
+ function resolveCurrentPlatform() {
82515
+ const currentPlatform = (0, import_node_os16.platform)();
82516
+ if (currentPlatform !== "darwin" && currentPlatform !== "linux" && currentPlatform !== "win32") {
82517
+ throw new Error(`Daemon service installation is not supported on ${currentPlatform}`);
82101
82518
  }
82102
- error(event, fields = {}) {
82103
- this.log("error", event, fields);
82519
+ return currentPlatform;
82520
+ }
82521
+ function currentServicePlan(args, runtime) {
82522
+ const currentPlatform = resolveCurrentPlatform();
82523
+ const profile = resolveEndpointProfileFromArgs(args);
82524
+ const cliEntry = runtime?.cliEntry ?? process.argv[1];
82525
+ if (!cliEntry) throw new Error("Cannot determine the alan-agent executable path");
82526
+ return buildDaemonServicePlan({
82527
+ platform: currentPlatform,
82528
+ homeDir: (0, import_node_os16.homedir)(),
82529
+ nodeExecutable: runtime?.executable ?? process.execPath,
82530
+ cliEntry: (0, import_node_path27.resolve)(cliEntry),
82531
+ profile,
82532
+ environment: runtime?.environment
82533
+ });
82534
+ }
82535
+ function writeManifestAtomic(path2, contents) {
82536
+ (0, import_node_fs25.mkdirSync)((0, import_node_path27.dirname)(path2), { recursive: true, mode: 448 });
82537
+ const pendingPath = `${path2}.pending-${process.pid}`;
82538
+ try {
82539
+ (0, import_node_fs25.writeFileSync)(pendingPath, contents, { mode: 384 });
82540
+ (0, import_node_fs25.chmodSync)(pendingPath, 384);
82541
+ (0, import_node_fs25.renameSync)(pendingPath, path2);
82542
+ } finally {
82543
+ (0, import_node_fs25.rmSync)(pendingPath, { force: true });
82104
82544
  }
82105
- log(level, event, fields) {
82106
- const record2 = omitUndefined({
82107
- ts: (/* @__PURE__ */ new Date()).toISOString(),
82108
- level,
82109
- component: "agent-manager",
82110
- event,
82111
- ...this.context,
82112
- ...normalizeFields(fields)
82113
- });
82114
- console[level](JSON.stringify(record2));
82545
+ }
82546
+ function defaultReadManifest(path2) {
82547
+ if (!(0, import_node_fs25.existsSync)(path2)) return null;
82548
+ return (0, import_node_fs25.readFileSync)(path2, "utf8");
82549
+ }
82550
+ function runServiceCommand(command) {
82551
+ const result = (0, import_node_child_process9.spawnSync)(command.command, command.args, { encoding: "utf8", shell: false });
82552
+ const status = result.status ?? 1;
82553
+ const output2 = `${result.stdout ?? ""}${result.stderr ?? ""}`.trim();
82554
+ if (status !== 0 && !command.tolerateFailure) {
82555
+ throw new Error(
82556
+ `Service command failed (${command.command} ${command.args.join(" ")}): ${output2 || `exit ${status}`}`
82557
+ );
82115
82558
  }
82116
- };
82117
- function lifecycleContextFromEnv(env) {
82118
- return normalizeContext({
82119
- taskId: env.ALAN_TASK_ID,
82120
- conversationId: env.ALAN_SESSION_ID,
82121
- runId: env.ALAN_RUN_ID,
82122
- sandboxId: env.ALAN_SANDBOX_ID,
82123
- provider: env.ALAN_SANDBOX_PROVIDER,
82124
- backendKind: env.ALAN_BACKEND_KIND,
82125
- agentVersion: AGENT_VERSION
82126
- });
82559
+ return { status, output: output2 };
82127
82560
  }
82128
- function normalizeContext(context) {
82129
- return omitUndefined({
82130
- ...context,
82131
- agentVersion: context.agentVersion ?? AGENT_VERSION
82561
+ function defaultSleep(ms) {
82562
+ return new Promise((resolveSleep) => {
82563
+ setTimeout(resolveSleep, ms);
82132
82564
  });
82133
82565
  }
82134
- function normalizeFields(fields) {
82135
- const normalized = {};
82136
- for (const [key, value2] of Object.entries(fields)) {
82137
- if (value2 instanceof Error) {
82138
- normalized[key] = {
82139
- name: value2.name,
82140
- message: value2.message,
82141
- stack: value2.stack
82142
- };
82143
- } else {
82144
- normalized[key] = value2;
82566
+ function parseServiceHostState(servicePlatform, result) {
82567
+ const output2 = result.output;
82568
+ if (servicePlatform === "linux") {
82569
+ const trimmed = output2.trim().toLowerCase();
82570
+ if (trimmed === "inactive" || trimmed === "failed" || trimmed === "dead" || /\binactive\b/i.test(output2) || /\bfailed\b/i.test(output2)) {
82571
+ return "stopped";
82145
82572
  }
82146
82573
  }
82147
- return normalized;
82148
- }
82149
- function omitUndefined(record2) {
82150
- return Object.fromEntries(Object.entries(record2).filter(([, value2]) => value2 !== void 0));
82574
+ if (result.status !== 0) return "unknown";
82575
+ if (servicePlatform === "darwin") {
82576
+ if (/\bstate\s*=\s*running\b/i.test(output2)) return "running";
82577
+ if (/\bstate\s*=\s*(not running|waiting|stopped)\b/i.test(output2)) return "stopped";
82578
+ if (/\bpid\s*=\s*[1-9]\d*\b/i.test(output2)) return "running";
82579
+ if (/could not find service/i.test(output2)) return "stopped";
82580
+ return "unknown";
82581
+ }
82582
+ if (servicePlatform === "linux") {
82583
+ const trimmed = output2.trim().toLowerCase();
82584
+ if (trimmed === "active" || /\bactive\s*\(running\)/i.test(output2)) return "running";
82585
+ if (trimmed === "activating" || trimmed === "reloading") return "starting";
82586
+ return "unknown";
82587
+ }
82588
+ const stateMatch = output2.match(/\b(?:State|state)\s*[:=]\s*(\w+)/);
82589
+ const state = (stateMatch?.[1] ?? output2.trim()).toLowerCase();
82590
+ if (state === "running") return "running";
82591
+ if (state === "ready" || state === "disabled" || state === "queued") return "stopped";
82592
+ return "unknown";
82151
82593
  }
82152
-
82153
- // ../../node_modules/@modelcontextprotocol/server/dist/chunk-Br0eD_fh.mjs
82154
- var __create3 = Object.create;
82155
- var __defProp3 = Object.defineProperty;
82156
- var __getOwnPropDesc3 = Object.getOwnPropertyDescriptor;
82157
- var __getOwnPropNames3 = Object.getOwnPropertyNames;
82158
- var __getProtoOf3 = Object.getPrototypeOf;
82159
- var __hasOwnProp3 = Object.prototype.hasOwnProperty;
82160
- var __commonJSMin2 = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
82161
- var __exportAll2 = (all, symbols) => {
82162
- let target = {};
82163
- for (var name in all) {
82164
- __defProp3(target, name, {
82165
- get: all[name],
82166
- enumerable: true
82167
- });
82594
+ function resolveEnsureDefinitionOutcome(input2) {
82595
+ if (!input2.definitionChanged) {
82596
+ return { changed: false, updatePending: false };
82168
82597
  }
82169
- if (symbols) {
82170
- __defProp3(target, Symbol.toStringTag, { value: "Module" });
82598
+ if (input2.hostState === "running" || input2.hostState === "starting") {
82599
+ return { changed: true, updatePending: true };
82171
82600
  }
82172
- return target;
82173
- };
82174
- var __copyProps3 = (to, from, except, desc) => {
82175
- if (from && typeof from === "object" || typeof from === "function") {
82176
- for (var keys = __getOwnPropNames3(from), i = 0, n = keys.length, key; i < n; i++) {
82177
- key = keys[i];
82178
- if (!__hasOwnProp3.call(to, key) && key !== except) {
82179
- __defProp3(to, key, {
82180
- get: ((k) => from[k]).bind(null, key),
82181
- enumerable: !(desc = __getOwnPropDesc3(from, key)) || desc.enumerable
82601
+ return { changed: true, updatePending: false };
82602
+ }
82603
+ function shouldStartOnInstall(hostState) {
82604
+ return hostState === "stopped";
82605
+ }
82606
+ function resolveUsername(options) {
82607
+ if (options?.username) return options.username;
82608
+ try {
82609
+ return (0, import_node_os16.userInfo)().username;
82610
+ } catch {
82611
+ return process.env.USER || process.env.USERNAME || "unknown";
82612
+ }
82613
+ }
82614
+ function buildLingerStatusCommand(username) {
82615
+ return {
82616
+ command: "loginctl",
82617
+ args: ["show-user", username, "-p", "Linger"],
82618
+ tolerateFailure: true
82619
+ };
82620
+ }
82621
+ function assertSystemdUserLingerEnabled(options = {}) {
82622
+ const username = resolveUsername(options);
82623
+ const run = options.runCommand ?? runServiceCommand;
82624
+ const result = run(buildLingerStatusCommand(username));
82625
+ if (result.status !== 0) {
82626
+ throw new Error(
82627
+ `Cannot verify systemd user linger for ${username} (loginctl failed). For durable headless VM boot run: sudo loginctl enable-linger ${username}`
82628
+ );
82629
+ }
82630
+ if (!/Linger=yes/i.test(result.output)) {
82631
+ throw new Error(
82632
+ `systemd user linger is disabled for ${username}. For durable headless VM boot run: sudo loginctl enable-linger ${username}`
82633
+ );
82634
+ }
82635
+ }
82636
+ function createHostContext(options = {}) {
82637
+ const args = options.args ?? [];
82638
+ const plan = currentServicePlan(args, options.runtime);
82639
+ const run = options.runCommand ?? runServiceCommand;
82640
+ const sleep4 = options.sleep ?? defaultSleep;
82641
+ const nowMs = options.nowMs ?? Date.now;
82642
+ const readManifest = options.readManifest ?? defaultReadManifest;
82643
+ const writeManifest = options.writeManifest ?? writeManifestAtomic;
82644
+ const removeManifest = options.removeManifest ?? ((path2) => (0, import_node_fs25.rmSync)(path2, { force: true }));
82645
+ const ensureLogDir = options.ensureLogDir ?? (() => {
82646
+ if (plan.logDirectory) (0, import_node_fs25.mkdirSync)(plan.logDirectory, { recursive: true, mode: 448 });
82647
+ });
82648
+ return {
82649
+ args,
82650
+ plan,
82651
+ run,
82652
+ sleep: sleep4,
82653
+ nowMs,
82654
+ readManifest,
82655
+ writeManifest,
82656
+ removeManifest,
82657
+ ensureLogDir,
82658
+ profile: resolveEndpointProfileFromArgs(args)
82659
+ };
82660
+ }
82661
+ function inspectDaemonService(options = {}) {
82662
+ const { plan, run, nowMs } = createHostContext(options);
82663
+ const result = run(plan.isActiveCommand);
82664
+ const state = parseServiceHostState(plan.platform, result);
82665
+ return {
82666
+ state,
82667
+ platform: plan.platform,
82668
+ detail: result.output || void 0,
82669
+ observedAtMs: nowMs()
82670
+ };
82671
+ }
82672
+ function ensureDaemonServiceDefinition(options = {}) {
82673
+ const ctx = createHostContext(options);
82674
+ const { plan, run, readManifest, writeManifest, ensureLogDir } = ctx;
82675
+ let definitionChanged = false;
82676
+ if (plan.manifestPath && plan.manifest) {
82677
+ ensureLogDir();
82678
+ const existing = readManifest(plan.manifestPath);
82679
+ definitionChanged = existing !== plan.manifest;
82680
+ if (definitionChanged) {
82681
+ writeManifest(plan.manifestPath, plan.manifest);
82682
+ }
82683
+ } else if (plan.platform === "win32") {
82684
+ definitionChanged = true;
82685
+ }
82686
+ const inspection = inspectDaemonService(options);
82687
+ const outcome = resolveEnsureDefinitionOutcome({
82688
+ definitionChanged,
82689
+ hostState: inspection.state
82690
+ });
82691
+ if (outcome.updatePending) {
82692
+ return outcome;
82693
+ }
82694
+ if (inspection.state === "running" || inspection.state === "starting") {
82695
+ return outcome;
82696
+ }
82697
+ const definitionCommands = inspection.state === "stopped" ? plan.reloadDefinitionCommands : plan.loadDefinitionCommands;
82698
+ for (const command of definitionCommands) run(command);
82699
+ return outcome;
82700
+ }
82701
+ function enableDaemonService(options = {}) {
82702
+ const { plan, run } = createHostContext(options);
82703
+ for (const command of plan.enableCommands) run(command);
82704
+ }
82705
+ function startDaemonService(options = {}) {
82706
+ const { plan, run } = createHostContext(options);
82707
+ for (const command of plan.startCommands) run(command);
82708
+ }
82709
+ function uninstallDaemonService(args = [], options = {}) {
82710
+ const ctx = createHostContext({ ...options, args: options.args ?? args });
82711
+ for (const command of ctx.plan.uninstallCommands) ctx.run(command);
82712
+ if (ctx.plan.manifestPath) ctx.removeManifest(ctx.plan.manifestPath);
82713
+ console.info("[alan-agent] Per-user daemon service removed");
82714
+ }
82715
+ function installDaemonService(args = [], runtime, options = {}) {
82716
+ const profile = resolveEndpointProfileFromArgs(args);
82717
+ const configPath = resolveAgentConfigPath({ profile });
82718
+ if (!configExistsAtPath(configPath)) {
82719
+ throw new Error(`No ${profile} runtime is configured. Run alan-agent setup or login first.`);
82720
+ }
82721
+ const headless = options.headless ?? args.includes("--headless");
82722
+ const merged = { ...options, args, runtime, headless };
82723
+ const ctx = createHostContext(merged);
82724
+ if (headless) {
82725
+ if (ctx.plan.platform !== "linux") {
82726
+ throw new Error("--headless is only supported on Linux systemd user services");
82727
+ }
82728
+ assertSystemdUserLingerEnabled(merged);
82729
+ }
82730
+ const ensured = ensureDaemonServiceDefinition(merged);
82731
+ enableDaemonService(merged);
82732
+ const inspection = inspectDaemonService(merged);
82733
+ if (ensured.updatePending) {
82734
+ console.info("[alan-agent] Daemon service definition update pending; leaving running service", {
82735
+ profile,
82736
+ state: inspection.state
82737
+ });
82738
+ return;
82739
+ }
82740
+ if (!shouldStartOnInstall(inspection.state)) {
82741
+ console.info("[alan-agent] Per-user daemon service already present", {
82742
+ profile,
82743
+ state: inspection.state
82744
+ });
82745
+ return;
82746
+ }
82747
+ startDaemonService(merged);
82748
+ console.info("[alan-agent] Per-user daemon service installed", { profile });
82749
+ }
82750
+ function printDaemonServiceStatus(args = []) {
82751
+ const plan = currentServicePlan(args);
82752
+ const result = runServiceCommand({ ...plan.statusCommand, tolerateFailure: true });
82753
+ if (result.status !== 0) {
82754
+ process.stdout.write(`unknown
82755
+ ${result.output}
82756
+ `);
82757
+ return;
82758
+ }
82759
+ process.stdout.write(`${result.output}
82760
+ `);
82761
+ }
82762
+
82763
+ // src/install-command.ts
82764
+ async function runInstallCommand(commandArgs) {
82765
+ bindConfigPath(commandArgs);
82766
+ const configured = readConfig();
82767
+ const configurationMode = resolveInstallConfigurationMode(commandArgs, configured);
82768
+ if (configurationMode === "setup") await setupDaemon(commandArgs);
82769
+ if (configurationMode === "login") await loginWithDeviceCode(commandArgs);
82770
+ installDaemonService(commandArgs);
82771
+ runMcpIntegrationCommand(["reconcile", ...commandArgs]);
82772
+ }
82773
+
82774
+ // src/lifecycle-logger.ts
82775
+ var AgentLifecycleLogger = class _AgentLifecycleLogger {
82776
+ context;
82777
+ constructor(context = {}) {
82778
+ this.context = normalizeContext(context);
82779
+ }
82780
+ setContext(context) {
82781
+ this.context = normalizeContext({ ...this.context, ...context });
82782
+ }
82783
+ child(context) {
82784
+ return new _AgentLifecycleLogger({ ...this.context, ...context });
82785
+ }
82786
+ debug(event, fields = {}) {
82787
+ this.log("debug", event, fields);
82788
+ }
82789
+ info(event, fields = {}) {
82790
+ this.log("info", event, fields);
82791
+ }
82792
+ warn(event, fields = {}) {
82793
+ this.log("warn", event, fields);
82794
+ }
82795
+ error(event, fields = {}) {
82796
+ this.log("error", event, fields);
82797
+ }
82798
+ log(level, event, fields) {
82799
+ const record2 = omitUndefined({
82800
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
82801
+ level,
82802
+ component: "agent-manager",
82803
+ event,
82804
+ ...this.context,
82805
+ ...normalizeFields(fields)
82806
+ });
82807
+ console[level](JSON.stringify(record2));
82808
+ }
82809
+ };
82810
+ function lifecycleContextFromEnv(env) {
82811
+ return normalizeContext({
82812
+ taskId: env.ALAN_TASK_ID,
82813
+ conversationId: env.ALAN_SESSION_ID,
82814
+ runId: env.ALAN_RUN_ID,
82815
+ sandboxId: env.ALAN_SANDBOX_ID,
82816
+ provider: env.ALAN_SANDBOX_PROVIDER,
82817
+ backendKind: env.ALAN_BACKEND_KIND,
82818
+ agentVersion: AGENT_VERSION
82819
+ });
82820
+ }
82821
+ function normalizeContext(context) {
82822
+ return omitUndefined({
82823
+ ...context,
82824
+ agentVersion: context.agentVersion ?? AGENT_VERSION
82825
+ });
82826
+ }
82827
+ function normalizeFields(fields) {
82828
+ const normalized = {};
82829
+ for (const [key, value2] of Object.entries(fields)) {
82830
+ if (value2 instanceof Error) {
82831
+ normalized[key] = {
82832
+ name: value2.name,
82833
+ message: value2.message,
82834
+ stack: value2.stack
82835
+ };
82836
+ } else {
82837
+ normalized[key] = value2;
82838
+ }
82839
+ }
82840
+ return normalized;
82841
+ }
82842
+ function omitUndefined(record2) {
82843
+ return Object.fromEntries(Object.entries(record2).filter(([, value2]) => value2 !== void 0));
82844
+ }
82845
+
82846
+ // ../../node_modules/@modelcontextprotocol/server/dist/chunk-Br0eD_fh.mjs
82847
+ var __create3 = Object.create;
82848
+ var __defProp3 = Object.defineProperty;
82849
+ var __getOwnPropDesc3 = Object.getOwnPropertyDescriptor;
82850
+ var __getOwnPropNames3 = Object.getOwnPropertyNames;
82851
+ var __getProtoOf3 = Object.getPrototypeOf;
82852
+ var __hasOwnProp3 = Object.prototype.hasOwnProperty;
82853
+ var __commonJSMin2 = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
82854
+ var __exportAll2 = (all, symbols) => {
82855
+ let target = {};
82856
+ for (var name in all) {
82857
+ __defProp3(target, name, {
82858
+ get: all[name],
82859
+ enumerable: true
82860
+ });
82861
+ }
82862
+ if (symbols) {
82863
+ __defProp3(target, Symbol.toStringTag, { value: "Module" });
82864
+ }
82865
+ return target;
82866
+ };
82867
+ var __copyProps3 = (to, from, except, desc) => {
82868
+ if (from && typeof from === "object" || typeof from === "function") {
82869
+ for (var keys = __getOwnPropNames3(from), i = 0, n = keys.length, key; i < n; i++) {
82870
+ key = keys[i];
82871
+ if (!__hasOwnProp3.call(to, key) && key !== except) {
82872
+ __defProp3(to, key, {
82873
+ get: ((k) => from[k]).bind(null, key),
82874
+ enumerable: !(desc = __getOwnPropDesc3(from, key)) || desc.enumerable
82182
82875
  });
82183
82876
  }
82184
82877
  }
@@ -94517,27 +95210,27 @@ async function runMcpStdioProxy(env = process.env, local = new StdioServerTransp
94517
95210
 
94518
95211
  // src/native-hook-command.ts
94519
95212
  var import_node_crypto21 = require("crypto");
94520
- var import_node_fs26 = require("fs");
94521
- var import_node_os16 = require("os");
94522
- var import_node_path28 = require("path");
95213
+ var import_node_fs27 = require("fs");
95214
+ var import_node_os17 = require("os");
95215
+ var import_node_path29 = require("path");
94523
95216
 
94524
95217
  // src/native-project-config.ts
94525
- var import_node_fs25 = require("fs");
94526
- var import_node_path27 = require("path");
95218
+ var import_node_fs26 = require("fs");
95219
+ var import_node_path28 = require("path");
94527
95220
  var MAX_ALAN_PROJECT_CONFIG_BYTES = 64 * 1024;
94528
95221
  var ORGANIZATION_SLUG_PATTERN = /^[a-z0-9-]+$/;
94529
95222
  var TEAM_IDENTIFIER_PATTERN = /^[A-Z0-9]{2,4}$/i;
94530
95223
  function readAlanProjectPin(cwd) {
94531
95224
  let fd;
94532
95225
  try {
94533
- fd = (0, import_node_fs25.openSync)(
94534
- (0, import_node_path27.join)(cwd, "alan.json"),
94535
- import_node_fs25.constants.O_RDONLY | import_node_fs25.constants.O_NONBLOCK | (import_node_fs25.constants.O_NOFOLLOW ?? 0)
95226
+ fd = (0, import_node_fs26.openSync)(
95227
+ (0, import_node_path28.join)(cwd, "alan.json"),
95228
+ import_node_fs26.constants.O_RDONLY | import_node_fs26.constants.O_NONBLOCK | (import_node_fs26.constants.O_NOFOLLOW ?? 0)
94536
95229
  );
94537
- const stat2 = (0, import_node_fs25.fstatSync)(fd);
95230
+ const stat2 = (0, import_node_fs26.fstatSync)(fd);
94538
95231
  if (!stat2.isFile() || stat2.size > MAX_ALAN_PROJECT_CONFIG_BYTES) return void 0;
94539
95232
  const buffer = Buffer.allocUnsafe(MAX_ALAN_PROJECT_CONFIG_BYTES + 1);
94540
- const bytesRead = (0, import_node_fs25.readSync)(fd, buffer, 0, buffer.byteLength, 0);
95233
+ const bytesRead = (0, import_node_fs26.readSync)(fd, buffer, 0, buffer.byteLength, 0);
94541
95234
  if (bytesRead > MAX_ALAN_PROJECT_CONFIG_BYTES) return void 0;
94542
95235
  const parsed = JSON.parse(buffer.subarray(0, bytesRead).toString("utf8"));
94543
95236
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return void 0;
@@ -94553,7 +95246,7 @@ function readAlanProjectPin(cwd) {
94553
95246
  } finally {
94554
95247
  if (fd !== void 0) {
94555
95248
  try {
94556
- (0, import_node_fs25.closeSync)(fd);
95249
+ (0, import_node_fs26.closeSync)(fd);
94557
95250
  } catch {
94558
95251
  }
94559
95252
  }
@@ -94792,19 +95485,19 @@ function nonNegativeIntegerField(payload, ...names) {
94792
95485
  return void 0;
94793
95486
  }
94794
95487
  function resolveCodexSessionIdFromTranscriptPath(transcriptPath) {
94795
- const fileName = (0, import_node_path28.basename)(transcriptPath);
95488
+ const fileName = (0, import_node_path29.basename)(transcriptPath);
94796
95489
  const match = /^rollout-.*-([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.jsonl$/i.exec(
94797
95490
  fileName
94798
95491
  );
94799
95492
  return match?.[1];
94800
95493
  }
94801
- function resolveKimiTranscriptPath(externalSessionId, kimiHomeDir = process.env.KIMI_CODE_HOME?.trim() || (0, import_node_path28.join)((0, import_node_os16.homedir)(), ".kimi-code")) {
94802
- if ((0, import_node_path28.basename)(externalSessionId) !== externalSessionId) return void 0;
94803
- const sessionsDir = (0, import_node_path28.join)(kimiHomeDir, "sessions");
94804
- if (!(0, import_node_fs26.existsSync)(sessionsDir)) return void 0;
94805
- for (const workspace of (0, import_node_fs26.readdirSync)(sessionsDir, { withFileTypes: true })) {
95494
+ function resolveKimiTranscriptPath(externalSessionId, kimiHomeDir = process.env.KIMI_CODE_HOME?.trim() || (0, import_node_path29.join)((0, import_node_os17.homedir)(), ".kimi-code")) {
95495
+ if ((0, import_node_path29.basename)(externalSessionId) !== externalSessionId) return void 0;
95496
+ const sessionsDir = (0, import_node_path29.join)(kimiHomeDir, "sessions");
95497
+ if (!(0, import_node_fs27.existsSync)(sessionsDir)) return void 0;
95498
+ for (const workspace of (0, import_node_fs27.readdirSync)(sessionsDir, { withFileTypes: true })) {
94806
95499
  if (!workspace.isDirectory()) continue;
94807
- const transcriptPath = (0, import_node_path28.join)(
95500
+ const transcriptPath = (0, import_node_path29.join)(
94808
95501
  sessionsDir,
94809
95502
  workspace.name,
94810
95503
  externalSessionId,
@@ -94812,7 +95505,7 @@ function resolveKimiTranscriptPath(externalSessionId, kimiHomeDir = process.env.
94812
95505
  "main",
94813
95506
  "wire.jsonl"
94814
95507
  );
94815
- if ((0, import_node_fs26.existsSync)(transcriptPath)) return transcriptPath;
95508
+ if ((0, import_node_fs27.existsSync)(transcriptPath)) return transcriptPath;
94816
95509
  }
94817
95510
  return void 0;
94818
95511
  }
@@ -94847,7 +95540,7 @@ function parseNativeHookEnvelope(input2) {
94847
95540
  const rawHookEvent = input2.hookEvent ?? stringField4(payload, "hook_event_name", "hookEvent", "hookEventName", "type") ?? "notification";
94848
95541
  const eventType = normalizeHookEvent(rawHookEvent);
94849
95542
  const cwd = stringField4(payload, "cwd", "working_directory", "workingDirectory") ?? firstStringArrayField(payload, "workspace_roots", "workspaceRoots");
94850
- const resolvedCwd = cwd ? (0, import_node_path28.resolve)(cwd) : void 0;
95543
+ const resolvedCwd = cwd ? (0, import_node_path29.resolve)(cwd) : void 0;
94851
95544
  const transcriptPath = eventType === "subagent_start" || eventType === "subagent_end" ? stringField4(
94852
95545
  payload,
94853
95546
  "agent_transcript_path",
@@ -94893,7 +95586,7 @@ function parseNativeHookEnvelope(input2) {
94893
95586
  ...(eventType === "subagent_start" || eventType === "subagent_end") && parentSessionId ? { parentExternalSessionId: parentSessionId } : {},
94894
95587
  ...resolvedCwd ? { cwd: resolvedCwd } : {},
94895
95588
  ...projectPin,
94896
- ...transcriptPath ? { transcriptPath: (0, import_node_path28.resolve)(transcriptPath) } : {},
95589
+ ...transcriptPath ? { transcriptPath: (0, import_node_path29.resolve)(transcriptPath) } : {},
94897
95590
  ...cursor ? { sourceCursor: cursor } : {},
94898
95591
  providerPayload
94899
95592
  };
@@ -94940,7 +95633,7 @@ function readBoundedHookPayload(fd = 0, maxBytes = MAX_NATIVE_HOOK_STDIN_BYTES)
94940
95633
  let totalBytes = 0;
94941
95634
  while (true) {
94942
95635
  const chunk = Buffer.allocUnsafe(Math.min(64 * 1024, maxBytes + 1 - totalBytes));
94943
- const bytesRead = (0, import_node_fs26.readSync)(fd, chunk, 0, chunk.byteLength, null);
95636
+ const bytesRead = (0, import_node_fs27.readSync)(fd, chunk, 0, chunk.byteLength, null);
94944
95637
  if (bytesRead === 0) break;
94945
95638
  totalBytes += bytesRead;
94946
95639
  if (totalBytes > maxBytes) throw new Error(`hook input exceeds ${maxBytes} bytes`);
@@ -95023,7 +95716,7 @@ function collectNativeIntegrationStatus(args = []) {
95023
95716
  const config2 = readConfig();
95024
95717
  const configPath = getConfigPath();
95025
95718
  const env = getDaemonCliEnvironment();
95026
- const homeDir = (0, import_node_os16.homedir)();
95719
+ const homeDir = (0, import_node_os17.homedir)();
95027
95720
  return NATIVE_SESSION_PROVIDER_CAPABILITIES.map((capability) => ({
95028
95721
  provider: capability.providerKind,
95029
95722
  command: capability.command,
@@ -95052,7 +95745,7 @@ function decodeResumeFallbackContext(encoded) {
95052
95745
  }
95053
95746
 
95054
95747
  // src/sandbox.ts
95055
- var import_node_os17 = require("os");
95748
+ var import_node_os18 = require("os");
95056
95749
 
95057
95750
  // src/execution-activity-tracker.ts
95058
95751
  var ExecutionActivityTracker = class {
@@ -95666,7 +96359,7 @@ var agentProbeAckSchema = external_exports.object({
95666
96359
 
95667
96360
  // src/sandbox-outbox.ts
95668
96361
  var import_node_crypto23 = require("crypto");
95669
- var import_node_fs27 = require("fs");
96362
+ var import_node_fs28 = require("fs");
95670
96363
  function deriveSandboxOutboxKey(sessionToken) {
95671
96364
  if (!sessionToken) {
95672
96365
  throw new Error("sandbox event outbox requires ALAN_SESSION_TOKEN for key derivation");
@@ -95676,17 +96369,50 @@ function deriveSandboxOutboxKey(sessionToken) {
95676
96369
  function sandboxOutboxSpoolPath(conversationId) {
95677
96370
  return `/tmp/alan-agent-outbox-${conversationId}.enc`;
95678
96371
  }
96372
+ function sandboxOutboxKeyPath(spoolPath) {
96373
+ return `${spoolPath}.key`;
96374
+ }
96375
+ function assertValidOutboxKey(key, path2) {
96376
+ if (Buffer.from(key, "base64url").length !== 32) {
96377
+ throw new Error(`sandbox event outbox key at ${path2} must contain exactly 32 bytes`);
96378
+ }
96379
+ return key;
96380
+ }
96381
+ function loadOrCreateSandboxOutboxKey(input2) {
96382
+ const keyPath = sandboxOutboxKeyPath(input2.spoolPath);
96383
+ if ((0, import_node_fs28.existsSync)(keyPath)) {
96384
+ (0, import_node_fs28.chmodSync)(keyPath, 384);
96385
+ return assertValidOutboxKey((0, import_node_fs28.readFileSync)(keyPath, "utf8").trim(), keyPath);
96386
+ }
96387
+ const initialKey = deriveSandboxOutboxKey(input2.sessionToken);
96388
+ try {
96389
+ (0, import_node_fs28.writeFileSync)(keyPath, initialKey, { encoding: "utf8", flag: "wx", mode: 384 });
96390
+ return initialKey;
96391
+ } catch (error61) {
96392
+ if (error61.code !== "EEXIST") throw error61;
96393
+ (0, import_node_fs28.chmodSync)(keyPath, 384);
96394
+ return assertValidOutboxKey((0, import_node_fs28.readFileSync)(keyPath, "utf8").trim(), keyPath);
96395
+ }
96396
+ }
96397
+ function quarantineUnusableOutbox(path2) {
96398
+ const suffix = `corrupt-${Date.now()}-${process.pid}`;
96399
+ for (const candidate of [path2, eventJournalDir(path2)]) {
96400
+ if ((0, import_node_fs28.existsSync)(candidate)) (0, import_node_fs28.renameSync)(candidate, `${candidate}.${suffix}`);
96401
+ }
96402
+ }
95679
96403
  function createSandboxEventOutbox(input2) {
95680
96404
  const path2 = input2.spoolPath ?? sandboxOutboxSpoolPath(input2.conversationId);
95681
- const key = deriveSandboxOutboxKey(input2.sessionToken);
96405
+ const key = loadOrCreateSandboxOutboxKey({
96406
+ spoolPath: path2,
96407
+ sessionToken: input2.sessionToken
96408
+ });
95682
96409
  try {
95683
96410
  return new EncryptedEventOutbox(path2, key, input2.pushLog, input2.options);
95684
96411
  } catch (error61) {
95685
96412
  input2.pushLog?.(
95686
- `sandbox_outbox_spool_reset ${error61 instanceof Error ? error61.message : String(error61)}`
96413
+ `sandbox_outbox_spool_quarantined ${error61 instanceof Error ? error61.message : String(error61)}`
95687
96414
  );
95688
- (0, import_node_fs27.rmSync)(path2, { force: true });
95689
- (0, import_node_fs27.rmSync)(eventJournalDir(path2), { recursive: true, force: true });
96415
+ quarantineUnusableOutbox(path2);
95690
96416
  return new EncryptedEventOutbox(path2, key, input2.pushLog, input2.options);
95691
96417
  }
95692
96418
  }
@@ -95758,6 +96484,10 @@ var SandboxEventDispatcher = class {
95758
96484
  pendingCount() {
95759
96485
  return this.outbox.pendingCount();
95760
96486
  }
96487
+ /** Drain the async writer so a replacement process can recover the journal. */
96488
+ flushDurable() {
96489
+ return this.outbox.flushDurable();
96490
+ }
95761
96491
  };
95762
96492
 
95763
96493
  // src/ws-client.ts
@@ -96327,7 +97057,7 @@ async function runSandbox(config2) {
96327
97057
  }
96328
97058
  const presenter = new WebPresenter(wsClient, config2.sessionId, config2.projectPath);
96329
97059
  presenter.setSuppressSessionLifecycle(true);
96330
- const runtimeSkillManager = await RuntimeSkillManager.open({ homeDirectory: (0, import_node_os17.homedir)() });
97060
+ const runtimeSkillManager = await RuntimeSkillManager.open({ homeDirectory: (0, import_node_os18.homedir)() });
96331
97061
  let lastProviderSessionId = config2.providerSessionId;
96332
97062
  let resumeFallbackContext = config2.resumeFallbackContext;
96333
97063
  let activeBackendKind = config2.backendKind || "claude_cli";
@@ -96624,572 +97354,6 @@ async function runSandbox(config2) {
96624
97354
  wsClient.close();
96625
97355
  }
96626
97356
 
96627
- // src/service-manager.ts
96628
- var import_node_child_process9 = require("child_process");
96629
- var import_node_fs28 = require("fs");
96630
- var import_node_os18 = require("os");
96631
- var import_node_path29 = require("path");
96632
- var SERVICE_LABEL = "ai.tryalan.agent";
96633
- var SYSTEMD_UNIT = "alan-agent.service";
96634
- var WINDOWS_TASK = "Alan Agent";
96635
- function xml(value2) {
96636
- return value2.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&apos;");
96637
- }
96638
- function systemdArg(value2) {
96639
- return `"${value2.replaceAll("\\", "\\\\").replaceAll('"', '\\"')}"`;
96640
- }
96641
- function powershellLiteral(value2) {
96642
- return `'${value2.replaceAll("'", "''")}'`;
96643
- }
96644
- function buildDaemonServicePlan(input2) {
96645
- const daemonArgs = [input2.nodeExecutable, input2.cliEntry, "daemon", "--profile", input2.profile];
96646
- if (input2.platform === "darwin") {
96647
- const userId = input2.userId ?? process.getuid?.();
96648
- if (userId === void 0) throw new Error("Cannot determine the current macOS user ID");
96649
- const domain2 = `gui/${userId}`;
96650
- const serviceTarget = `${domain2}/${SERVICE_LABEL}`;
96651
- const manifestPath = (0, import_node_path29.join)(input2.homeDir, "Library", "LaunchAgents", `${SERVICE_LABEL}.plist`);
96652
- const logDir = (0, import_node_path29.join)(input2.homeDir, ".alan", "agent", "logs");
96653
- const programArguments = daemonArgs.map((arg) => ` <string>${xml(arg)}</string>`).join("\n");
96654
- const environmentEntries = Object.entries(input2.environment ?? {}).map(([key, value2]) => ` <key>${xml(key)}</key>
96655
- <string>${xml(value2)}</string>`).join("\n");
96656
- const environmentBlock = environmentEntries ? ` <key>EnvironmentVariables</key>
96657
- <dict>
96658
- ${environmentEntries}
96659
- </dict>
96660
- ` : "";
96661
- const manifest = `<?xml version="1.0" encoding="UTF-8"?>
96662
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
96663
- <plist version="1.0">
96664
- <dict>
96665
- <key>Label</key>
96666
- <string>${SERVICE_LABEL}</string>
96667
- <key>ProgramArguments</key>
96668
- <array>
96669
- ${programArguments}
96670
- </array>
96671
- ${environmentBlock} <key>RunAtLoad</key>
96672
- <true/>
96673
- <key>KeepAlive</key>
96674
- <dict>
96675
- <key>SuccessfulExit</key>
96676
- <false/>
96677
- </dict>
96678
- <key>ThrottleInterval</key>
96679
- <integer>5</integer>
96680
- <key>StandardOutPath</key>
96681
- <string>${xml((0, import_node_path29.join)(logDir, "daemon.log"))}</string>
96682
- <key>StandardErrorPath</key>
96683
- <string>${xml((0, import_node_path29.join)(logDir, "daemon-error.log"))}</string>
96684
- </dict>
96685
- </plist>
96686
- `;
96687
- return {
96688
- platform: "darwin",
96689
- manifestPath,
96690
- manifest,
96691
- loadDefinitionCommands: [
96692
- {
96693
- command: "launchctl",
96694
- args: ["bootstrap", domain2, manifestPath],
96695
- tolerateFailure: true
96696
- }
96697
- ],
96698
- enableCommands: [
96699
- {
96700
- command: "launchctl",
96701
- args: ["enable", serviceTarget],
96702
- tolerateFailure: true
96703
- }
96704
- ],
96705
- startCommands: [
96706
- {
96707
- command: "launchctl",
96708
- args: ["kickstart", serviceTarget],
96709
- tolerateFailure: false
96710
- }
96711
- ],
96712
- stopCommands: [
96713
- {
96714
- command: "launchctl",
96715
- args: ["kill", "SIGTERM", serviceTarget],
96716
- tolerateFailure: true
96717
- }
96718
- ],
96719
- replaceCommands: [
96720
- {
96721
- command: "launchctl",
96722
- args: ["bootout", domain2, manifestPath],
96723
- tolerateFailure: true
96724
- },
96725
- {
96726
- command: "launchctl",
96727
- args: ["bootstrap", domain2, manifestPath],
96728
- tolerateFailure: false
96729
- },
96730
- {
96731
- command: "launchctl",
96732
- args: ["kickstart", "-k", serviceTarget],
96733
- tolerateFailure: false
96734
- }
96735
- ],
96736
- uninstallCommands: [
96737
- {
96738
- command: "launchctl",
96739
- args: ["bootout", domain2, manifestPath],
96740
- tolerateFailure: true
96741
- }
96742
- ],
96743
- statusCommand: {
96744
- command: "launchctl",
96745
- args: ["print", serviceTarget],
96746
- tolerateFailure: true
96747
- },
96748
- isActiveCommand: {
96749
- command: "launchctl",
96750
- args: ["print", serviceTarget],
96751
- tolerateFailure: true
96752
- },
96753
- lingerStatusCommand: null
96754
- };
96755
- }
96756
- if (input2.platform === "linux") {
96757
- const manifestPath = (0, import_node_path29.join)(input2.homeDir, ".config", "systemd", "user", SYSTEMD_UNIT);
96758
- const environmentLines = Object.entries(input2.environment ?? {}).map(([key, value2]) => `Environment=${systemdArg(`${key}=${value2}`)}`).join("\n");
96759
- const manifest = `[Unit]
96760
- Description=Alan local agent daemon
96761
- After=network-online.target
96762
- Wants=network-online.target
96763
- StartLimitIntervalSec=300
96764
- StartLimitBurst=3
96765
-
96766
- [Service]
96767
- Type=simple
96768
- ${environmentLines ? `${environmentLines}
96769
- ` : ""}ExecStart=${daemonArgs.map(systemdArg).join(" ")}
96770
- Restart=on-failure
96771
- RestartSec=5
96772
-
96773
- [Install]
96774
- WantedBy=default.target
96775
- `;
96776
- return {
96777
- platform: "linux",
96778
- manifestPath,
96779
- manifest,
96780
- loadDefinitionCommands: [
96781
- {
96782
- command: "systemctl",
96783
- args: ["--user", "daemon-reload"],
96784
- tolerateFailure: false
96785
- }
96786
- ],
96787
- enableCommands: [
96788
- {
96789
- command: "systemctl",
96790
- args: ["--user", "enable", SYSTEMD_UNIT],
96791
- tolerateFailure: false
96792
- }
96793
- ],
96794
- startCommands: [
96795
- {
96796
- command: "systemctl",
96797
- args: ["--user", "start", SYSTEMD_UNIT],
96798
- tolerateFailure: false
96799
- }
96800
- ],
96801
- stopCommands: [
96802
- {
96803
- command: "systemctl",
96804
- args: ["--user", "stop", SYSTEMD_UNIT],
96805
- tolerateFailure: true
96806
- }
96807
- ],
96808
- replaceCommands: [
96809
- {
96810
- command: "systemctl",
96811
- args: ["--user", "daemon-reload"],
96812
- tolerateFailure: false
96813
- },
96814
- {
96815
- command: "systemctl",
96816
- args: ["--user", "restart", SYSTEMD_UNIT],
96817
- tolerateFailure: false
96818
- }
96819
- ],
96820
- uninstallCommands: [
96821
- {
96822
- command: "systemctl",
96823
- args: ["--user", "disable", "--now", SYSTEMD_UNIT],
96824
- tolerateFailure: true
96825
- },
96826
- {
96827
- command: "systemctl",
96828
- args: ["--user", "daemon-reload"],
96829
- tolerateFailure: false
96830
- }
96831
- ],
96832
- statusCommand: {
96833
- command: "systemctl",
96834
- args: ["--user", "status", SYSTEMD_UNIT, "--no-pager"],
96835
- tolerateFailure: true
96836
- },
96837
- isActiveCommand: {
96838
- command: "systemctl",
96839
- args: ["--user", "is-active", SYSTEMD_UNIT],
96840
- tolerateFailure: true
96841
- },
96842
- lingerStatusCommand: {
96843
- command: "loginctl",
96844
- args: ["show-user", "$(id -un)", "-p", "Linger"],
96845
- tolerateFailure: true
96846
- }
96847
- };
96848
- }
96849
- const environmentPrefix = Object.entries(input2.environment ?? {}).map(([key, value2]) => `$env:${key} = ${powershellLiteral(value2)}`).join("; ");
96850
- const directArgument = [input2.cliEntry, "daemon", "--profile", input2.profile].map((part) => part.includes(" ") ? `"${part}"` : part).join(" ");
96851
- const executable = powershellLiteral(environmentPrefix ? "powershell.exe" : input2.nodeExecutable);
96852
- const argument = powershellLiteral(
96853
- environmentPrefix ? `-NoProfile -NonInteractive -WindowStyle Hidden -Command "${environmentPrefix}; & ${powershellLiteral(input2.nodeExecutable)} ${powershellLiteral(input2.cliEntry)} daemon --profile ${input2.profile}"` : directArgument
96854
- );
96855
- const registerScript = [
96856
- "$currentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name",
96857
- `$action = New-ScheduledTaskAction -Execute ${executable} -Argument ${argument}`,
96858
- "$trigger = New-ScheduledTaskTrigger -AtLogOn -User $currentUser",
96859
- "$principal = New-ScheduledTaskPrincipal -UserId $currentUser -LogonType Interactive -RunLevel Limited",
96860
- "$settings = New-ScheduledTaskSettingsSet -RestartCount 3 -RestartInterval (New-TimeSpan -Minutes 1) -ExecutionTimeLimit ([TimeSpan]::Zero)",
96861
- `Register-ScheduledTask -TaskName ${powershellLiteral(WINDOWS_TASK)} -Action $action -Trigger $trigger -Principal $principal -Settings $settings -Force | Out-Null`
96862
- ].join("; ");
96863
- return {
96864
- platform: "win32",
96865
- manifestPath: null,
96866
- manifest: null,
96867
- loadDefinitionCommands: [
96868
- {
96869
- command: "powershell.exe",
96870
- args: ["-NoProfile", "-NonInteractive", "-Command", registerScript],
96871
- tolerateFailure: false
96872
- }
96873
- ],
96874
- enableCommands: [],
96875
- startCommands: [
96876
- {
96877
- command: "powershell.exe",
96878
- args: [
96879
- "-NoProfile",
96880
- "-NonInteractive",
96881
- "-Command",
96882
- `Start-ScheduledTask -TaskName ${powershellLiteral(WINDOWS_TASK)}`
96883
- ],
96884
- tolerateFailure: false
96885
- }
96886
- ],
96887
- stopCommands: [
96888
- {
96889
- command: "powershell.exe",
96890
- args: [
96891
- "-NoProfile",
96892
- "-NonInteractive",
96893
- "-Command",
96894
- `Stop-ScheduledTask -TaskName ${powershellLiteral(WINDOWS_TASK)} -ErrorAction SilentlyContinue`
96895
- ],
96896
- tolerateFailure: true
96897
- }
96898
- ],
96899
- replaceCommands: [
96900
- {
96901
- command: "powershell.exe",
96902
- args: [
96903
- "-NoProfile",
96904
- "-NonInteractive",
96905
- "-Command",
96906
- `${registerScript}; Start-ScheduledTask -TaskName ${powershellLiteral(WINDOWS_TASK)}`
96907
- ],
96908
- tolerateFailure: false
96909
- }
96910
- ],
96911
- uninstallCommands: [
96912
- {
96913
- command: "powershell.exe",
96914
- args: [
96915
- "-NoProfile",
96916
- "-NonInteractive",
96917
- "-Command",
96918
- `Unregister-ScheduledTask -TaskName ${powershellLiteral(WINDOWS_TASK)} -Confirm:$false -ErrorAction SilentlyContinue`
96919
- ],
96920
- tolerateFailure: true
96921
- }
96922
- ],
96923
- statusCommand: {
96924
- command: "powershell.exe",
96925
- args: [
96926
- "-NoProfile",
96927
- "-NonInteractive",
96928
- "-Command",
96929
- `Get-ScheduledTask -TaskName ${powershellLiteral(WINDOWS_TASK)} | Format-List TaskName,State`
96930
- ],
96931
- tolerateFailure: true
96932
- },
96933
- isActiveCommand: {
96934
- command: "powershell.exe",
96935
- args: [
96936
- "-NoProfile",
96937
- "-NonInteractive",
96938
- "-Command",
96939
- `(Get-ScheduledTask -TaskName ${powershellLiteral(WINDOWS_TASK)} -ErrorAction SilentlyContinue).State`
96940
- ],
96941
- tolerateFailure: true
96942
- },
96943
- lingerStatusCommand: null
96944
- };
96945
- }
96946
- function resolveCurrentPlatform() {
96947
- const currentPlatform = (0, import_node_os18.platform)();
96948
- if (currentPlatform !== "darwin" && currentPlatform !== "linux" && currentPlatform !== "win32") {
96949
- throw new Error(`Daemon service installation is not supported on ${currentPlatform}`);
96950
- }
96951
- return currentPlatform;
96952
- }
96953
- function currentServicePlan(args, runtime) {
96954
- const currentPlatform = resolveCurrentPlatform();
96955
- const profile = resolveEndpointProfileFromArgs(args);
96956
- const cliEntry = runtime?.cliEntry ?? process.argv[1];
96957
- if (!cliEntry) throw new Error("Cannot determine the alan-agent executable path");
96958
- return buildDaemonServicePlan({
96959
- platform: currentPlatform,
96960
- homeDir: (0, import_node_os18.homedir)(),
96961
- nodeExecutable: runtime?.executable ?? process.execPath,
96962
- cliEntry: (0, import_node_path29.resolve)(cliEntry),
96963
- profile,
96964
- environment: runtime?.environment
96965
- });
96966
- }
96967
- function writeManifestAtomic(path2, contents) {
96968
- (0, import_node_fs28.mkdirSync)((0, import_node_path29.dirname)(path2), { recursive: true, mode: 448 });
96969
- const pendingPath = `${path2}.pending-${process.pid}`;
96970
- try {
96971
- (0, import_node_fs28.writeFileSync)(pendingPath, contents, { mode: 384 });
96972
- (0, import_node_fs28.chmodSync)(pendingPath, 384);
96973
- (0, import_node_fs28.renameSync)(pendingPath, path2);
96974
- } finally {
96975
- (0, import_node_fs28.rmSync)(pendingPath, { force: true });
96976
- }
96977
- }
96978
- function defaultReadManifest(path2) {
96979
- if (!(0, import_node_fs28.existsSync)(path2)) return null;
96980
- return (0, import_node_fs28.readFileSync)(path2, "utf8");
96981
- }
96982
- function runServiceCommand(command) {
96983
- const result = (0, import_node_child_process9.spawnSync)(command.command, command.args, { encoding: "utf8", shell: false });
96984
- const status = result.status ?? 1;
96985
- const output2 = `${result.stdout ?? ""}${result.stderr ?? ""}`.trim();
96986
- if (status !== 0 && !command.tolerateFailure) {
96987
- throw new Error(
96988
- `Service command failed (${command.command} ${command.args.join(" ")}): ${output2 || `exit ${status}`}`
96989
- );
96990
- }
96991
- return { status, output: output2 };
96992
- }
96993
- function defaultSleep(ms) {
96994
- return new Promise((resolveSleep) => {
96995
- setTimeout(resolveSleep, ms);
96996
- });
96997
- }
96998
- function parseServiceHostState(servicePlatform, result) {
96999
- const output2 = result.output;
97000
- if (servicePlatform === "linux") {
97001
- const trimmed = output2.trim().toLowerCase();
97002
- if (trimmed === "inactive" || trimmed === "failed" || trimmed === "dead" || /\binactive\b/i.test(output2) || /\bfailed\b/i.test(output2)) {
97003
- return "stopped";
97004
- }
97005
- }
97006
- if (result.status !== 0) return "unknown";
97007
- if (servicePlatform === "darwin") {
97008
- if (/\bstate\s*=\s*running\b/i.test(output2)) return "running";
97009
- if (/\bstate\s*=\s*(not running|waiting|stopped)\b/i.test(output2)) return "stopped";
97010
- if (/\bpid\s*=\s*[1-9]\d*\b/i.test(output2)) return "running";
97011
- if (/could not find service/i.test(output2)) return "stopped";
97012
- return "unknown";
97013
- }
97014
- if (servicePlatform === "linux") {
97015
- const trimmed = output2.trim().toLowerCase();
97016
- if (trimmed === "active" || /\bactive\s*\(running\)/i.test(output2)) return "running";
97017
- if (trimmed === "activating" || trimmed === "reloading") return "starting";
97018
- return "unknown";
97019
- }
97020
- const stateMatch = output2.match(/\b(?:State|state)\s*[:=]\s*(\w+)/);
97021
- const state = (stateMatch?.[1] ?? output2.trim()).toLowerCase();
97022
- if (state === "running") return "running";
97023
- if (state === "ready" || state === "disabled" || state === "queued") return "stopped";
97024
- return "unknown";
97025
- }
97026
- function resolveEnsureDefinitionOutcome(input2) {
97027
- if (!input2.definitionChanged) {
97028
- return { changed: false, updatePending: false };
97029
- }
97030
- if (input2.hostState === "running" || input2.hostState === "starting") {
97031
- return { changed: true, updatePending: true };
97032
- }
97033
- return { changed: true, updatePending: false };
97034
- }
97035
- function shouldStartOnInstall(hostState) {
97036
- return hostState === "stopped";
97037
- }
97038
- function resolveUsername(options) {
97039
- if (options?.username) return options.username;
97040
- try {
97041
- return (0, import_node_os18.userInfo)().username;
97042
- } catch {
97043
- return process.env.USER || process.env.USERNAME || "unknown";
97044
- }
97045
- }
97046
- function buildLingerStatusCommand(username) {
97047
- return {
97048
- command: "loginctl",
97049
- args: ["show-user", username, "-p", "Linger"],
97050
- tolerateFailure: true
97051
- };
97052
- }
97053
- function assertSystemdUserLingerEnabled(options = {}) {
97054
- const username = resolveUsername(options);
97055
- const run = options.runCommand ?? runServiceCommand;
97056
- const result = run(buildLingerStatusCommand(username));
97057
- if (result.status !== 0) {
97058
- throw new Error(
97059
- `Cannot verify systemd user linger for ${username} (loginctl failed). For durable headless VM boot run: sudo loginctl enable-linger ${username}`
97060
- );
97061
- }
97062
- if (!/Linger=yes/i.test(result.output)) {
97063
- throw new Error(
97064
- `systemd user linger is disabled for ${username}. For durable headless VM boot run: sudo loginctl enable-linger ${username}`
97065
- );
97066
- }
97067
- }
97068
- function createHostContext(options = {}) {
97069
- const args = options.args ?? [];
97070
- const plan = currentServicePlan(args, options.runtime);
97071
- const run = options.runCommand ?? runServiceCommand;
97072
- const sleep4 = options.sleep ?? defaultSleep;
97073
- const nowMs = options.nowMs ?? Date.now;
97074
- const readManifest = options.readManifest ?? defaultReadManifest;
97075
- const writeManifest = options.writeManifest ?? writeManifestAtomic;
97076
- const removeManifest = options.removeManifest ?? ((path2) => (0, import_node_fs28.rmSync)(path2, { force: true }));
97077
- const ensureLogDir = options.ensureLogDir ?? (() => {
97078
- if (plan.platform === "darwin") {
97079
- (0, import_node_fs28.mkdirSync)((0, import_node_path29.join)((0, import_node_os18.homedir)(), ".alan", "agent", "logs"), { recursive: true, mode: 448 });
97080
- }
97081
- });
97082
- return {
97083
- args,
97084
- plan,
97085
- run,
97086
- sleep: sleep4,
97087
- nowMs,
97088
- readManifest,
97089
- writeManifest,
97090
- removeManifest,
97091
- ensureLogDir,
97092
- profile: resolveEndpointProfileFromArgs(args)
97093
- };
97094
- }
97095
- function inspectDaemonService(options = {}) {
97096
- const { plan, run, nowMs } = createHostContext(options);
97097
- const result = run(plan.isActiveCommand);
97098
- const state = parseServiceHostState(plan.platform, result);
97099
- return {
97100
- state,
97101
- platform: plan.platform,
97102
- detail: result.output || void 0,
97103
- observedAtMs: nowMs()
97104
- };
97105
- }
97106
- function ensureDaemonServiceDefinition(options = {}) {
97107
- const ctx = createHostContext(options);
97108
- const { plan, run, readManifest, writeManifest, ensureLogDir } = ctx;
97109
- let definitionChanged = false;
97110
- if (plan.manifestPath && plan.manifest) {
97111
- ensureLogDir();
97112
- const existing = readManifest(plan.manifestPath);
97113
- definitionChanged = existing !== plan.manifest;
97114
- if (definitionChanged) {
97115
- writeManifest(plan.manifestPath, plan.manifest);
97116
- }
97117
- } else if (plan.platform === "win32") {
97118
- definitionChanged = true;
97119
- }
97120
- const inspection = inspectDaemonService(options);
97121
- const outcome = resolveEnsureDefinitionOutcome({
97122
- definitionChanged,
97123
- hostState: inspection.state
97124
- });
97125
- if (outcome.updatePending) {
97126
- return outcome;
97127
- }
97128
- for (const command of plan.loadDefinitionCommands) run(command);
97129
- return outcome;
97130
- }
97131
- function enableDaemonService(options = {}) {
97132
- const { plan, run } = createHostContext(options);
97133
- for (const command of plan.enableCommands) run(command);
97134
- }
97135
- function startDaemonService(options = {}) {
97136
- const { plan, run } = createHostContext(options);
97137
- for (const command of plan.startCommands) run(command);
97138
- }
97139
- function uninstallDaemonService(args = [], options = {}) {
97140
- const ctx = createHostContext({ ...options, args: options.args ?? args });
97141
- for (const command of ctx.plan.uninstallCommands) ctx.run(command);
97142
- if (ctx.plan.manifestPath) ctx.removeManifest(ctx.plan.manifestPath);
97143
- console.info("[alan-agent] Per-user daemon service removed");
97144
- }
97145
- function installDaemonService(args = [], runtime, options = {}) {
97146
- const profile = resolveEndpointProfileFromArgs(args);
97147
- const configPath = resolveAgentConfigPath({ profile });
97148
- if (!configExistsAtPath(configPath)) {
97149
- throw new Error(`No ${profile} runtime is configured. Run alan-agent setup or login first.`);
97150
- }
97151
- const headless = options.headless ?? args.includes("--headless");
97152
- const merged = { ...options, args, runtime, headless };
97153
- const ctx = createHostContext(merged);
97154
- if (headless) {
97155
- if (ctx.plan.platform !== "linux") {
97156
- throw new Error("--headless is only supported on Linux systemd user services");
97157
- }
97158
- assertSystemdUserLingerEnabled(merged);
97159
- }
97160
- const ensured = ensureDaemonServiceDefinition(merged);
97161
- enableDaemonService(merged);
97162
- const inspection = inspectDaemonService(merged);
97163
- if (ensured.updatePending) {
97164
- console.info("[alan-agent] Daemon service definition update pending; leaving running service", {
97165
- profile,
97166
- state: inspection.state
97167
- });
97168
- return;
97169
- }
97170
- if (!shouldStartOnInstall(inspection.state)) {
97171
- console.info("[alan-agent] Per-user daemon service already present", {
97172
- profile,
97173
- state: inspection.state
97174
- });
97175
- return;
97176
- }
97177
- startDaemonService(merged);
97178
- console.info("[alan-agent] Per-user daemon service installed", { profile });
97179
- }
97180
- function printDaemonServiceStatus(args = []) {
97181
- const plan = currentServicePlan(args);
97182
- const result = runServiceCommand({ ...plan.statusCommand, tolerateFailure: true });
97183
- if (result.status !== 0) {
97184
- process.stdout.write(`unknown
97185
- ${result.output}
97186
- `);
97187
- return;
97188
- }
97189
- process.stdout.write(`${result.output}
97190
- `);
97191
- }
97192
-
97193
97357
  // src/skills/skill-cli.ts
97194
97358
  var import_promises6 = require("fs/promises");
97195
97359
  var import_node_os19 = require("os");
@@ -97388,14 +97552,7 @@ async function main() {
97388
97552
  return;
97389
97553
  }
97390
97554
  if (command === "install") {
97391
- bindConfigPath(commandArgs);
97392
- const configured = readConfig();
97393
- if (!configured.runtimeId || !configured.runtimeToken) {
97394
- if (commandArgs.includes("--setup-token")) await setupDaemon(commandArgs);
97395
- else await loginWithDeviceCode(commandArgs);
97396
- }
97397
- installDaemonService(commandArgs);
97398
- runMcpIntegrationCommand(["reconcile", ...commandArgs]);
97555
+ await runInstallCommand(commandArgs);
97399
97556
  return;
97400
97557
  }
97401
97558
  if (command === "login") {