opensquid 0.5.441 → 0.5.447

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 (380) hide show
  1. package/README.md +1 -0
  2. package/dist/functions/arm_scope.d.ts +27 -0
  3. package/dist/functions/arm_scope.d.ts.map +1 -0
  4. package/dist/functions/arm_scope.js +52 -0
  5. package/dist/functions/arm_scope.js.map +1 -0
  6. package/dist/functions/index.d.ts +1 -0
  7. package/dist/functions/index.d.ts.map +1 -1
  8. package/dist/functions/index.js +1 -0
  9. package/dist/functions/index.js.map +1 -1
  10. package/dist/runtime/bootstrap.d.ts.map +1 -1
  11. package/dist/runtime/bootstrap.js +2 -0
  12. package/dist/runtime/bootstrap.js.map +1 -1
  13. package/dist/runtime/handoff/render.d.ts +5 -4
  14. package/dist/runtime/handoff/render.d.ts.map +1 -1
  15. package/dist/runtime/handoff/render.js +7 -7
  16. package/dist/runtime/handoff/render.js.map +1 -1
  17. package/dist/runtime/hooks/active_task_mirror.js +0 -0
  18. package/dist/runtime/hooks/apply_patch.js +0 -0
  19. package/dist/runtime/hooks/dispatch.js +0 -0
  20. package/dist/runtime/hooks/hook_output.js +0 -0
  21. package/dist/runtime/hooks/memory_reconcile.js +0 -0
  22. package/dist/runtime/hooks/new_project_detect.js +0 -0
  23. package/dist/runtime/hooks/profession_resolver.js +0 -0
  24. package/dist/runtime/hooks/scope_intent.js +0 -0
  25. package/dist/runtime/hooks/session_id.js +0 -0
  26. package/dist/runtime/hooks/session_liveness.js +0 -0
  27. package/dist/runtime/hooks/stop_drive.js +0 -0
  28. package/dist/runtime/hooks/stop_stream.js +0 -0
  29. package/dist/runtime/hooks/subagent_guard.js +0 -0
  30. package/dist/runtime/hooks/transcript.js +0 -0
  31. package/dist/runtime/hooks/transcript_tasks.js +0 -0
  32. package/dist/runtime/ralph/orchestrator.d.ts.map +1 -1
  33. package/dist/runtime/ralph/orchestrator.js +2 -1
  34. package/dist/runtime/ralph/orchestrator.js.map +1 -1
  35. package/dist/setup/cli/limits_state.d.ts.map +1 -1
  36. package/dist/setup/cli/limits_state.js +6 -40
  37. package/dist/setup/cli/limits_state.js.map +1 -1
  38. package/dist/setup/cli/pack_walk.d.ts +32 -0
  39. package/dist/setup/cli/pack_walk.d.ts.map +1 -0
  40. package/dist/setup/cli/pack_walk.js +76 -0
  41. package/dist/setup/cli/pack_walk.js.map +1 -0
  42. package/dist/setup/cli/permissions_state.d.ts.map +1 -1
  43. package/dist/setup/cli/permissions_state.js +6 -37
  44. package/dist/setup/cli/permissions_state.js.map +1 -1
  45. package/dist/setup/cli/triggers_state.d.ts.map +1 -1
  46. package/dist/setup/cli/triggers_state.js +3 -29
  47. package/dist/setup/cli/triggers_state.js.map +1 -1
  48. package/dist/workgraph/events.d.ts.map +1 -1
  49. package/dist/workgraph/events.js +10 -0
  50. package/dist/workgraph/events.js.map +1 -1
  51. package/dist/workgraph/store.d.ts.map +1 -1
  52. package/dist/workgraph/store.js +5 -0
  53. package/dist/workgraph/store.js.map +1 -1
  54. package/dist/workgraph/types.d.ts +2 -1
  55. package/dist/workgraph/types.d.ts.map +1 -1
  56. package/docs/ARCHITECTURE.md +268 -0
  57. package/package.json +5 -3
  58. package/packs/builtin/coding-flow/skills/entry-and-handoffs/skill.yaml +13 -17
  59. package/dist/anti-drift/evaluator.d.ts +0 -88
  60. package/dist/anti-drift/evaluator.d.ts.map +0 -1
  61. package/dist/anti-drift/evaluator.js +0 -417
  62. package/dist/anti-drift/evaluator.js.map +0 -1
  63. package/dist/anti-drift/evaluator.test.js +0 -78
  64. package/dist/anti-drift/rules.d.ts +0 -80
  65. package/dist/anti-drift/rules.d.ts.map +0 -1
  66. package/dist/anti-drift/rules.js +0 -368
  67. package/dist/anti-drift/rules.js.map +0 -1
  68. package/dist/anti-drift/rules.test.js +0 -213
  69. package/dist/anti-drift/state.d.ts +0 -107
  70. package/dist/anti-drift/state.d.ts.map +0 -1
  71. package/dist/anti-drift/state.js +0 -177
  72. package/dist/anti-drift/state.js.map +0 -1
  73. package/dist/anti-drift/state.test.js +0 -120
  74. package/dist/chat/adapters/discord.d.ts +0 -41
  75. package/dist/chat/adapters/discord.d.ts.map +0 -1
  76. package/dist/chat/adapters/discord.js +0 -176
  77. package/dist/chat/adapters/discord.js.map +0 -1
  78. package/dist/chat/adapters/discord.test.js +0 -25
  79. package/dist/chat/adapters/slack.d.ts +0 -43
  80. package/dist/chat/adapters/slack.d.ts.map +0 -1
  81. package/dist/chat/adapters/slack.js +0 -172
  82. package/dist/chat/adapters/slack.js.map +0 -1
  83. package/dist/chat/adapters/slack.test.js +0 -30
  84. package/dist/chat/adapters/telegram.d.ts +0 -148
  85. package/dist/chat/adapters/telegram.d.ts.map +0 -1
  86. package/dist/chat/adapters/telegram.js +0 -498
  87. package/dist/chat/adapters/telegram.js.map +0 -1
  88. package/dist/chat/adapters/telegram.test.js +0 -94
  89. package/dist/chat/config.d.ts +0 -98
  90. package/dist/chat/config.d.ts.map +0 -1
  91. package/dist/chat/config.js +0 -185
  92. package/dist/chat/config.js.map +0 -1
  93. package/dist/chat/daemon/active-project.d.ts +0 -17
  94. package/dist/chat/daemon/active-project.d.ts.map +0 -1
  95. package/dist/chat/daemon/active-project.js +0 -23
  96. package/dist/chat/daemon/active-project.js.map +0 -1
  97. package/dist/chat/daemon/autospawn.d.ts +0 -40
  98. package/dist/chat/daemon/autospawn.d.ts.map +0 -1
  99. package/dist/chat/daemon/autospawn.js +0 -129
  100. package/dist/chat/daemon/autospawn.js.map +0 -1
  101. package/dist/chat/daemon/autospawn.test.js +0 -112
  102. package/dist/chat/daemon/cli.d.ts +0 -18
  103. package/dist/chat/daemon/cli.d.ts.map +0 -1
  104. package/dist/chat/daemon/cli.js +0 -71
  105. package/dist/chat/daemon/cli.js.map +0 -1
  106. package/dist/chat/daemon/collisions.js +0 -384
  107. package/dist/chat/daemon/health-check.d.ts +0 -69
  108. package/dist/chat/daemon/health-check.d.ts.map +0 -1
  109. package/dist/chat/daemon/health-check.js +0 -112
  110. package/dist/chat/daemon/health-check.js.map +0 -1
  111. package/dist/chat/daemon/inbox-read.d.ts +0 -35
  112. package/dist/chat/daemon/inbox-read.d.ts.map +0 -1
  113. package/dist/chat/daemon/inbox-read.js +0 -75
  114. package/dist/chat/daemon/inbox-read.js.map +0 -1
  115. package/dist/chat/daemon/inbox-read.test.js +0 -97
  116. package/dist/chat/daemon/inbox.d.ts +0 -63
  117. package/dist/chat/daemon/inbox.d.ts.map +0 -1
  118. package/dist/chat/daemon/inbox.js +0 -56
  119. package/dist/chat/daemon/inbox.js.map +0 -1
  120. package/dist/chat/daemon/inbox.test.js +0 -110
  121. package/dist/chat/daemon/lifecycle.d.ts +0 -71
  122. package/dist/chat/daemon/lifecycle.d.ts.map +0 -1
  123. package/dist/chat/daemon/lifecycle.js +0 -221
  124. package/dist/chat/daemon/lifecycle.js.map +0 -1
  125. package/dist/chat/daemon/lifecycle.test.js +0 -163
  126. package/dist/chat/daemon/protocol.d.ts +0 -107
  127. package/dist/chat/daemon/protocol.d.ts.map +0 -1
  128. package/dist/chat/daemon/protocol.js +0 -54
  129. package/dist/chat/daemon/protocol.js.map +0 -1
  130. package/dist/chat/daemon/routing.d.ts +0 -140
  131. package/dist/chat/daemon/routing.d.ts.map +0 -1
  132. package/dist/chat/daemon/routing.js +0 -198
  133. package/dist/chat/daemon/routing.js.map +0 -1
  134. package/dist/chat/daemon/routing.test.js +0 -259
  135. package/dist/chat/daemon/rpc-client.d.ts +0 -45
  136. package/dist/chat/daemon/rpc-client.d.ts.map +0 -1
  137. package/dist/chat/daemon/rpc-client.js +0 -133
  138. package/dist/chat/daemon/rpc-client.js.map +0 -1
  139. package/dist/chat/daemon/rpc-server.d.ts +0 -39
  140. package/dist/chat/daemon/rpc-server.d.ts.map +0 -1
  141. package/dist/chat/daemon/rpc-server.js +0 -385
  142. package/dist/chat/daemon/rpc-server.js.map +0 -1
  143. package/dist/chat/daemon/rpc.test.js +0 -177
  144. package/dist/chat/daemon/subscribers.js +0 -257
  145. package/dist/chat/daemon/worker.d.ts +0 -27
  146. package/dist/chat/daemon/worker.d.ts.map +0 -1
  147. package/dist/chat/daemon/worker.js +0 -313
  148. package/dist/chat/daemon/worker.js.map +0 -1
  149. package/dist/chat/daemon/workspace-topic.js +0 -324
  150. package/dist/chat/env-token.d.ts +0 -60
  151. package/dist/chat/env-token.d.ts.map +0 -1
  152. package/dist/chat/env-token.js +0 -137
  153. package/dist/chat/env-token.js.map +0 -1
  154. package/dist/chat/env-token.test.js +0 -160
  155. package/dist/chat/factory.d.ts +0 -30
  156. package/dist/chat/factory.d.ts.map +0 -1
  157. package/dist/chat/factory.js +0 -50
  158. package/dist/chat/factory.js.map +0 -1
  159. package/dist/chat/factory.test.js +0 -55
  160. package/dist/chat/gateway.d.ts +0 -176
  161. package/dist/chat/gateway.d.ts.map +0 -1
  162. package/dist/chat/gateway.js +0 -146
  163. package/dist/chat/gateway.js.map +0 -1
  164. package/dist/chat/gateway.test.js +0 -192
  165. package/dist/claude-md.d.ts +0 -39
  166. package/dist/claude-md.d.ts.map +0 -1
  167. package/dist/claude-md.js +0 -113
  168. package/dist/claude-md.js.map +0 -1
  169. package/dist/claude-md.test.js +0 -91
  170. package/dist/codex/activate.d.ts +0 -66
  171. package/dist/codex/activate.d.ts.map +0 -1
  172. package/dist/codex/activate.js +0 -329
  173. package/dist/codex/activate.js.map +0 -1
  174. package/dist/codex/activate.test.js +0 -229
  175. package/dist/codex/bundled-default/bundled-default.test.js +0 -161
  176. package/dist/codex/cli-publish.test.js +0 -133
  177. package/dist/codex/cli.d.ts +0 -35
  178. package/dist/codex/cli.d.ts.map +0 -1
  179. package/dist/codex/cli.js +0 -554
  180. package/dist/codex/cli.js.map +0 -1
  181. package/dist/codex/cli.test.js +0 -277
  182. package/dist/codex/import-skill-md.d.ts +0 -53
  183. package/dist/codex/import-skill-md.d.ts.map +0 -1
  184. package/dist/codex/import-skill-md.js +0 -236
  185. package/dist/codex/import-skill-md.js.map +0 -1
  186. package/dist/codex/import-skill-md.test.js +0 -225
  187. package/dist/codex/loader.d.ts +0 -27
  188. package/dist/codex/loader.d.ts.map +0 -1
  189. package/dist/codex/loader.js +0 -86
  190. package/dist/codex/loader.js.map +0 -1
  191. package/dist/codex/loader.test.js +0 -75
  192. package/dist/codex/parse.d.ts +0 -28
  193. package/dist/codex/parse.d.ts.map +0 -1
  194. package/dist/codex/parse.js +0 -309
  195. package/dist/codex/parse.js.map +0 -1
  196. package/dist/codex/parse.test.js +0 -241
  197. package/dist/codex/store.d.ts +0 -87
  198. package/dist/codex/store.d.ts.map +0 -1
  199. package/dist/codex/store.js +0 -205
  200. package/dist/codex/store.js.map +0 -1
  201. package/dist/codex/store.test.js +0 -242
  202. package/dist/codex/types.d.ts +0 -398
  203. package/dist/codex/types.d.ts.map +0 -1
  204. package/dist/codex/types.js +0 -21
  205. package/dist/codex/types.js.map +0 -1
  206. package/dist/config.d.ts +0 -53
  207. package/dist/config.d.ts.map +0 -1
  208. package/dist/config.js +0 -202
  209. package/dist/config.js.map +0 -1
  210. package/dist/config.test.js +0 -117
  211. package/dist/engine/cli.d.ts +0 -14
  212. package/dist/engine/cli.d.ts.map +0 -1
  213. package/dist/engine/cli.js +0 -171
  214. package/dist/engine/cli.js.map +0 -1
  215. package/dist/engine/client.d.ts +0 -219
  216. package/dist/engine/client.d.ts.map +0 -1
  217. package/dist/engine/client.js +0 -312
  218. package/dist/engine/client.js.map +0 -1
  219. package/dist/engine/config.d.ts +0 -62
  220. package/dist/engine/config.d.ts.map +0 -1
  221. package/dist/engine/config.js +0 -223
  222. package/dist/engine/config.js.map +0 -1
  223. package/dist/engine/index.d.ts +0 -17
  224. package/dist/engine/index.d.ts.map +0 -1
  225. package/dist/engine/index.js +0 -16
  226. package/dist/engine/index.js.map +0 -1
  227. package/dist/engine/resolver.d.ts +0 -62
  228. package/dist/engine/resolver.d.ts.map +0 -1
  229. package/dist/engine/resolver.js +0 -103
  230. package/dist/engine/resolver.js.map +0 -1
  231. package/dist/engine/singleton.d.ts +0 -95
  232. package/dist/engine/singleton.d.ts.map +0 -1
  233. package/dist/engine/singleton.js +0 -325
  234. package/dist/engine/singleton.js.map +0 -1
  235. package/dist/engine/types.d.ts +0 -402
  236. package/dist/engine/types.d.ts.map +0 -1
  237. package/dist/engine/types.js +0 -22
  238. package/dist/engine/types.js.map +0 -1
  239. package/dist/engine-binary-resolver.js +0 -110
  240. package/dist/engine-binary-resolver.test.js +0 -61
  241. package/dist/engine-cli.js +0 -60
  242. package/dist/engine-client.js +0 -301
  243. package/dist/engine-client.test.js +0 -118
  244. package/dist/functions/chain_state.d.ts +0 -51
  245. package/dist/functions/chain_state.d.ts.map +0 -1
  246. package/dist/functions/chain_state.js +0 -59
  247. package/dist/functions/chain_state.js.map +0 -1
  248. package/dist/hooks/drift-catalog.d.ts +0 -68
  249. package/dist/hooks/drift-catalog.d.ts.map +0 -1
  250. package/dist/hooks/drift-catalog.js +0 -184
  251. package/dist/hooks/drift-catalog.js.map +0 -1
  252. package/dist/hooks/drift-catalog.test.js +0 -154
  253. package/dist/hooks/drift-patterns.d.ts +0 -110
  254. package/dist/hooks/drift-patterns.d.ts.map +0 -1
  255. package/dist/hooks/drift-patterns.js +0 -289
  256. package/dist/hooks/drift-patterns.js.map +0 -1
  257. package/dist/hooks/drift-patterns.test.js +0 -325
  258. package/dist/hooks/engine-vocab-gate.d.ts +0 -108
  259. package/dist/hooks/engine-vocab-gate.d.ts.map +0 -1
  260. package/dist/hooks/engine-vocab-gate.js +0 -225
  261. package/dist/hooks/engine-vocab-gate.js.map +0 -1
  262. package/dist/hooks/engine-vocab-gate.test.js +0 -170
  263. package/dist/hooks/heartbeat.d.ts +0 -107
  264. package/dist/hooks/heartbeat.d.ts.map +0 -1
  265. package/dist/hooks/heartbeat.js +0 -316
  266. package/dist/hooks/heartbeat.js.map +0 -1
  267. package/dist/hooks/heartbeat.test.js +0 -393
  268. package/dist/hooks/honesty-ledger-session-scope.test.js +0 -100
  269. package/dist/hooks/honesty-ledger.d.ts +0 -123
  270. package/dist/hooks/honesty-ledger.d.ts.map +0 -1
  271. package/dist/hooks/honesty-ledger.js +0 -226
  272. package/dist/hooks/honesty-ledger.js.map +0 -1
  273. package/dist/hooks/honesty-ledger.test.js +0 -466
  274. package/dist/hooks/inline-report-check.d.ts +0 -63
  275. package/dist/hooks/inline-report-check.d.ts.map +0 -1
  276. package/dist/hooks/inline-report-check.js +0 -88
  277. package/dist/hooks/inline-report-check.js.map +0 -1
  278. package/dist/hooks/inline-report-check.test.js +0 -96
  279. package/dist/hooks/pre-tool-use.d.ts +0 -62
  280. package/dist/hooks/pre-tool-use.d.ts.map +0 -1
  281. package/dist/hooks/pre-tool-use.js +0 -342
  282. package/dist/hooks/pre-tool-use.js.map +0 -1
  283. package/dist/hooks/pre-tool-use.test.js +0 -134
  284. package/dist/hooks/session-end.d.ts +0 -15
  285. package/dist/hooks/session-end.d.ts.map +0 -1
  286. package/dist/hooks/session-end.js +0 -60
  287. package/dist/hooks/session-end.js.map +0 -1
  288. package/dist/hooks/session-end.test.js +0 -52
  289. package/dist/hooks/stop.d.ts +0 -35
  290. package/dist/hooks/stop.d.ts.map +0 -1
  291. package/dist/hooks/stop.js +0 -136
  292. package/dist/hooks/stop.js.map +0 -1
  293. package/dist/hooks/transcript-active-task.test.js +0 -342
  294. package/dist/hooks/transcript.d.ts +0 -26
  295. package/dist/hooks/transcript.d.ts.map +0 -1
  296. package/dist/hooks/transcript.js +0 -266
  297. package/dist/hooks/transcript.js.map +0 -1
  298. package/dist/hooks/transcript.test.js +0 -103
  299. package/dist/hooks/user-prompt-submit.d.ts +0 -74
  300. package/dist/hooks/user-prompt-submit.d.ts.map +0 -1
  301. package/dist/hooks/user-prompt-submit.js +0 -256
  302. package/dist/hooks/user-prompt-submit.js.map +0 -1
  303. package/dist/hooks/user-prompt-submit.test.js +0 -118
  304. package/dist/hooks/versioning-gate.d.ts +0 -101
  305. package/dist/hooks/versioning-gate.d.ts.map +0 -1
  306. package/dist/hooks/versioning-gate.js +0 -245
  307. package/dist/hooks/versioning-gate.js.map +0 -1
  308. package/dist/hooks/versioning-gate.test.js +0 -368
  309. package/dist/hooks/workflow-gate.d.ts +0 -64
  310. package/dist/hooks/workflow-gate.d.ts.map +0 -1
  311. package/dist/hooks/workflow-gate.js +0 -152
  312. package/dist/hooks/workflow-gate.js.map +0 -1
  313. package/dist/hooks/workflow-gate.test.js +0 -197
  314. package/dist/hooks-cli.d.ts +0 -25
  315. package/dist/hooks-cli.d.ts.map +0 -1
  316. package/dist/hooks-cli.js +0 -286
  317. package/dist/hooks-cli.js.map +0 -1
  318. package/dist/hooks-cli.test.js +0 -148
  319. package/dist/origin.d.ts +0 -16
  320. package/dist/origin.d.ts.map +0 -1
  321. package/dist/origin.js +0 -92
  322. package/dist/origin.js.map +0 -1
  323. package/dist/packs/seed_lessons_ingest.d.ts +0 -30
  324. package/dist/packs/seed_lessons_ingest.d.ts.map +0 -1
  325. package/dist/packs/seed_lessons_ingest.js +0 -107
  326. package/dist/packs/seed_lessons_ingest.js.map +0 -1
  327. package/dist/project-cli.d.ts +0 -7
  328. package/dist/project-cli.d.ts.map +0 -1
  329. package/dist/project-cli.js +0 -145
  330. package/dist/project-cli.js.map +0 -1
  331. package/dist/project.d.ts +0 -127
  332. package/dist/project.d.ts.map +0 -1
  333. package/dist/project.js +0 -281
  334. package/dist/project.js.map +0 -1
  335. package/dist/project.test.js +0 -287
  336. package/dist/rag/backends/loop_engine.d.ts +0 -61
  337. package/dist/rag/backends/loop_engine.d.ts.map +0 -1
  338. package/dist/rag/backends/loop_engine.js +0 -160
  339. package/dist/rag/backends/loop_engine.js.map +0 -1
  340. package/dist/recall.d.ts +0 -82
  341. package/dist/recall.d.ts.map +0 -1
  342. package/dist/recall.js +0 -81
  343. package/dist/recall.js.map +0 -1
  344. package/dist/runtime/agent_bridge/autospawn.d.ts +0 -131
  345. package/dist/runtime/agent_bridge/autospawn.d.ts.map +0 -1
  346. package/dist/runtime/agent_bridge/autospawn.js +0 -251
  347. package/dist/runtime/agent_bridge/autospawn.js.map +0 -1
  348. package/dist/runtime/chain_state.d.ts +0 -124
  349. package/dist/runtime/chain_state.d.ts.map +0 -1
  350. package/dist/runtime/chain_state.js +0 -189
  351. package/dist/runtime/chain_state.js.map +0 -1
  352. package/dist/runtime/hooks/permission_decision.d.ts +0 -34
  353. package/dist/runtime/hooks/permission_decision.d.ts.map +0 -1
  354. package/dist/runtime/hooks/permission_decision.js +0 -39
  355. package/dist/runtime/hooks/permission_decision.js.map +0 -1
  356. package/dist/runtime/workflow_fsm.d.ts +0 -21
  357. package/dist/runtime/workflow_fsm.d.ts.map +0 -1
  358. package/dist/runtime/workflow_fsm.js +0 -25
  359. package/dist/runtime/workflow_fsm.js.map +0 -1
  360. package/dist/runtime/workflow_map.d.ts +0 -26
  361. package/dist/runtime/workflow_map.d.ts.map +0 -1
  362. package/dist/runtime/workflow_map.js +0 -38
  363. package/dist/runtime/workflow_map.js.map +0 -1
  364. package/dist/scope.d.ts +0 -48
  365. package/dist/scope.d.ts.map +0 -1
  366. package/dist/scope.js +0 -111
  367. package/dist/scope.js.map +0 -1
  368. package/dist/setup/cli/topic_create_step.d.ts +0 -84
  369. package/dist/setup/cli/topic_create_step.d.ts.map +0 -1
  370. package/dist/setup/cli/topic_create_step.js +0 -213
  371. package/dist/setup/cli/topic_create_step.js.map +0 -1
  372. package/dist/system-export.d.ts +0 -65
  373. package/dist/system-export.d.ts.map +0 -1
  374. package/dist/system-export.js +0 -194
  375. package/dist/system-export.js.map +0 -1
  376. package/dist/utterance/classifier.d.ts +0 -53
  377. package/dist/utterance/classifier.d.ts.map +0 -1
  378. package/dist/utterance/classifier.js +0 -184
  379. package/dist/utterance/classifier.js.map +0 -1
  380. package/dist/utterance/classifier.test.js +0 -147
@@ -1,98 +0,0 @@
1
- /**
2
- * Chat-connection configuration loaded from
3
- * `~/.opensquid/config.json` `chat_connections` block. Per-platform
4
- * blocks are independent — having one configured doesn't require any
5
- * of the others.
6
- *
7
- * Shape:
8
- * ```json
9
- * {
10
- * "version": 1,
11
- * "chat_connections": {
12
- * "telegram": { "bot_token": "...", "allowlist_chat_ids": ["8075471258"] },
13
- * "discord": { "bot_token": "...", "allowlist_user_ids": ["..."] },
14
- * "slack": { "bot_token": "xoxb-...", "app_token": "xapp-...", "allowlist_user_ids": ["..."] }
15
- * }
16
- * }
17
- * ```
18
- *
19
- * Tokens are stored in cleartext in `config.json`; advise users to
20
- * `chmod 600 ~/.opensquid/config.json` (the file lives in a hidden
21
- * dir already, so this is a small additional hardening — not a real
22
- * defense against a compromised user account).
23
- */
24
- import { type EnvSource } from "./env-token.js";
25
- import type { ChatPlatform } from "./gateway.js";
26
- export interface TelegramConfig {
27
- bot_token: string;
28
- /**
29
- * Chat ids the bot will accept messages from. Empty = accept from any
30
- * chat (NOT recommended — the bot is publicly addressable via Telegram).
31
- */
32
- allowlist_chat_ids?: string[];
33
- }
34
- export interface DiscordConfig {
35
- bot_token: string;
36
- /** User ids whose DMs / @-mentions the bot will respond to. Empty = bot owner only. */
37
- allowlist_user_ids?: string[];
38
- }
39
- export interface SlackConfig {
40
- /** Bot User OAuth Token — starts with `xoxb-`. Used for Web API calls. */
41
- bot_token: string;
42
- /**
43
- * App-level Token — starts with `xapp-`. Required for Socket Mode
44
- * (the no-public-ingress connection style we use).
45
- */
46
- app_token: string;
47
- /** User ids the bot will respond to. Empty = bot owner only. */
48
- allowlist_user_ids?: string[];
49
- }
50
- export interface ChatConnectionsConfig {
51
- telegram?: TelegramConfig;
52
- discord?: DiscordConfig;
53
- slack?: SlackConfig;
54
- }
55
- export declare function loadChatConfig(dataRoot?: string): Promise<ChatConnectionsConfig>;
56
- export interface ChatTokenSources {
57
- telegram?: EnvSource;
58
- discord?: EnvSource;
59
- slack_bot?: EnvSource;
60
- slack_app?: EnvSource;
61
- env_file_path?: string;
62
- }
63
- /**
64
- * Like loadChatConfig but also returns which source each token came
65
- * from. The chat-daemon uses this to log "[chat-daemon] telegram
66
- * bot_token source: env-file (~/.loop/.env)" so operators can debug
67
- * "which bot is this daemon actually using" without exposing the
68
- * secret.
69
- */
70
- export declare function loadChatConfigWithSources(dataRoot?: string): Promise<{
71
- config: ChatConnectionsConfig;
72
- sources: ChatTokenSources;
73
- }>;
74
- export declare function saveChatConfig(chat: ChatConnectionsConfig, dataRoot?: string): Promise<void>;
75
- /**
76
- * Set a single platform's config block. Convenience for the future
77
- * `opensquid chat setup <platform>` wizard.
78
- */
79
- export declare function setPlatformConfig<P extends ChatPlatform>(platform: P, config: P extends "telegram" ? TelegramConfig : P extends "discord" ? DiscordConfig : SlackConfig, dataRoot?: string): Promise<void>;
80
- /**
81
- * Forget a single platform's config block. Reverts that platform to
82
- * inactive on the next opensquid restart.
83
- */
84
- export declare function forgetPlatformConfig(platform: ChatPlatform, dataRoot?: string): Promise<void>;
85
- export interface ConfigValidationIssue {
86
- platform: ChatPlatform;
87
- field: string;
88
- problem: string;
89
- }
90
- /**
91
- * Surface obvious config errors without trying to validate the token
92
- * against the live API (that happens on adapter start). Catches
93
- * empty-string / undefined / shape mistakes before opening a connection.
94
- */
95
- export declare function validateChatConfig(config: ChatConnectionsConfig): ConfigValidationIssue[];
96
- /** Which platforms have any non-empty config block? */
97
- export declare function configuredPlatforms(config: ChatConnectionsConfig): ChatPlatform[];
98
- //# sourceMappingURL=config.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src.legacy/chat/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAKH,OAAO,EAAgB,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAMjD,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,uFAAuF;IACvF,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,WAAW;IAC1B,0EAA0E;IAC1E,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB,gEAAgE;IAChE,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB;AAcD,wBAAsB,cAAc,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAQtF;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;GAMG;AACH,wBAAsB,yBAAyB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1E,MAAM,EAAE,qBAAqB,CAAC;IAC9B,OAAO,EAAE,gBAAgB,CAAC;CAC3B,CAAC,CAGD;AA+CD,wBAAsB,cAAc,CAClC,IAAI,EAAE,qBAAqB,EAC3B,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAIf;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,CAAC,SAAS,YAAY,EAC5D,QAAQ,EAAE,CAAC,EACX,MAAM,EAAE,CAAC,SAAS,UAAU,GAAG,cAAc,GAAG,CAAC,SAAS,SAAS,GAAG,aAAa,GAAG,WAAW,EACjG,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAKf;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,YAAY,EACtB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAIf;AAMD,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,YAAY,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,qBAAqB,GAAG,qBAAqB,EAAE,CAyDzF;AAED,uDAAuD;AACvD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,qBAAqB,GAAG,YAAY,EAAE,CAMjF"}
@@ -1,185 +0,0 @@
1
- /**
2
- * Chat-connection configuration loaded from
3
- * `~/.opensquid/config.json` `chat_connections` block. Per-platform
4
- * blocks are independent — having one configured doesn't require any
5
- * of the others.
6
- *
7
- * Shape:
8
- * ```json
9
- * {
10
- * "version": 1,
11
- * "chat_connections": {
12
- * "telegram": { "bot_token": "...", "allowlist_chat_ids": ["8075471258"] },
13
- * "discord": { "bot_token": "...", "allowlist_user_ids": ["..."] },
14
- * "slack": { "bot_token": "xoxb-...", "app_token": "xapp-...", "allowlist_user_ids": ["..."] }
15
- * }
16
- * }
17
- * ```
18
- *
19
- * Tokens are stored in cleartext in `config.json`; advise users to
20
- * `chmod 600 ~/.opensquid/config.json` (the file lives in a hidden
21
- * dir already, so this is a small additional hardening — not a real
22
- * defense against a compromised user account).
23
- */
24
- import { loadConfig, saveConfig } from "../config.js";
25
- import { resolveToken } from "./env-token.js";
26
- export async function loadChatConfig(dataRoot) {
27
- const raw = (await loadConfig(dataRoot));
28
- // 0.7.5 (#148): overlay env-var + .env tokens atop config.json. Lets
29
- // the user park a Telegram bot token in ~/.loop/.env so opensquid
30
- // uses a DIFFERENT bot than Claude Code's plugin:telegram (no 409
31
- // collision possible — they're different bots). Priority is
32
- // env > .env > config.json (per resolveToken).
33
- return overlayEnvTokens(raw.chat_connections ?? {});
34
- }
35
- /**
36
- * Like loadChatConfig but also returns which source each token came
37
- * from. The chat-daemon uses this to log "[chat-daemon] telegram
38
- * bot_token source: env-file (~/.loop/.env)" so operators can debug
39
- * "which bot is this daemon actually using" without exposing the
40
- * secret.
41
- */
42
- export async function loadChatConfigWithSources(dataRoot) {
43
- const raw = (await loadConfig(dataRoot));
44
- return overlayEnvTokensWithSources(raw.chat_connections ?? {});
45
- }
46
- async function overlayEnvTokens(base) {
47
- const { config } = await overlayEnvTokensWithSources(base);
48
- return config;
49
- }
50
- async function overlayEnvTokensWithSources(base) {
51
- const out = { ...base };
52
- const sources = {};
53
- // Telegram
54
- const tg = await resolveToken("OPENSQUID_TELEGRAM_BOT_TOKEN", base.telegram?.bot_token);
55
- if (tg.value) {
56
- out.telegram = { ...(base.telegram ?? {}), bot_token: tg.value };
57
- sources.telegram = tg.source;
58
- if (tg.env_file_path)
59
- sources.env_file_path = tg.env_file_path;
60
- }
61
- // Discord
62
- const dc = await resolveToken("OPENSQUID_DISCORD_BOT_TOKEN", base.discord?.bot_token);
63
- if (dc.value) {
64
- out.discord = { ...(base.discord ?? {}), bot_token: dc.value };
65
- sources.discord = dc.source;
66
- if (dc.env_file_path && !sources.env_file_path)
67
- sources.env_file_path = dc.env_file_path;
68
- }
69
- // Slack: needs both bot_token + app_token
70
- const sb = await resolveToken("OPENSQUID_SLACK_BOT_TOKEN", base.slack?.bot_token);
71
- const sa = await resolveToken("OPENSQUID_SLACK_APP_TOKEN", base.slack?.app_token);
72
- if (sb.value || sa.value || base.slack) {
73
- out.slack = {
74
- ...(base.slack ?? { bot_token: "", app_token: "" }),
75
- bot_token: sb.value ?? base.slack?.bot_token ?? "",
76
- app_token: sa.value ?? base.slack?.app_token ?? "",
77
- };
78
- sources.slack_bot = sb.source;
79
- sources.slack_app = sa.source;
80
- if (sb.env_file_path && !sources.env_file_path)
81
- sources.env_file_path = sb.env_file_path;
82
- if (sa.env_file_path && !sources.env_file_path)
83
- sources.env_file_path = sa.env_file_path;
84
- }
85
- return { config: out, sources };
86
- }
87
- export async function saveChatConfig(chat, dataRoot) {
88
- const raw = (await loadConfig(dataRoot));
89
- raw.chat_connections = chat;
90
- await saveConfig(raw, dataRoot);
91
- }
92
- /**
93
- * Set a single platform's config block. Convenience for the future
94
- * `opensquid chat setup <platform>` wizard.
95
- */
96
- export async function setPlatformConfig(platform, config, dataRoot) {
97
- const chat = await loadChatConfig(dataRoot);
98
- // Cast narrows correctly per the conditional type above.
99
- chat[platform] = config;
100
- await saveChatConfig(chat, dataRoot);
101
- }
102
- /**
103
- * Forget a single platform's config block. Reverts that platform to
104
- * inactive on the next opensquid restart.
105
- */
106
- export async function forgetPlatformConfig(platform, dataRoot) {
107
- const chat = await loadChatConfig(dataRoot);
108
- delete chat[platform];
109
- await saveChatConfig(chat, dataRoot);
110
- }
111
- /**
112
- * Surface obvious config errors without trying to validate the token
113
- * against the live API (that happens on adapter start). Catches
114
- * empty-string / undefined / shape mistakes before opening a connection.
115
- */
116
- export function validateChatConfig(config) {
117
- const issues = [];
118
- if (config.telegram) {
119
- if (!config.telegram.bot_token?.trim()) {
120
- issues.push({
121
- platform: "telegram",
122
- field: "bot_token",
123
- problem: "empty — get one from @BotFather and run `opensquid chat setup telegram`",
124
- });
125
- }
126
- else if (!/^\d+:[A-Za-z0-9_-]+$/.test(config.telegram.bot_token)) {
127
- issues.push({
128
- platform: "telegram",
129
- field: "bot_token",
130
- problem: "wrong format — should look like '123456:ABC-DEF...'",
131
- });
132
- }
133
- }
134
- if (config.discord) {
135
- if (!config.discord.bot_token?.trim()) {
136
- issues.push({
137
- platform: "discord",
138
- field: "bot_token",
139
- problem: "empty — Discord Developer Portal → Application → Bot → Reset Token",
140
- });
141
- }
142
- }
143
- if (config.slack) {
144
- if (!config.slack.bot_token?.trim()) {
145
- issues.push({
146
- platform: "slack",
147
- field: "bot_token",
148
- problem: "empty — api.slack.com/apps → OAuth & Permissions → Bot User OAuth Token (xoxb-...)",
149
- });
150
- }
151
- else if (!config.slack.bot_token.startsWith("xoxb-")) {
152
- issues.push({
153
- platform: "slack",
154
- field: "bot_token",
155
- problem: "should start with 'xoxb-' (Bot User OAuth Token, not Workspace token)",
156
- });
157
- }
158
- if (!config.slack.app_token?.trim()) {
159
- issues.push({
160
- platform: "slack",
161
- field: "app_token",
162
- problem: "empty — required for Socket Mode; api.slack.com/apps → Basic Information → App-Level Tokens (xapp-...)",
163
- });
164
- }
165
- else if (!config.slack.app_token.startsWith("xapp-")) {
166
- issues.push({
167
- platform: "slack",
168
- field: "app_token",
169
- problem: "should start with 'xapp-' (App-Level Token, NOT Bot User OAuth Token)",
170
- });
171
- }
172
- }
173
- return issues;
174
- }
175
- /** Which platforms have any non-empty config block? */
176
- export function configuredPlatforms(config) {
177
- const out = [];
178
- if (config.telegram)
179
- out.push("telegram");
180
- if (config.discord)
181
- out.push("discord");
182
- if (config.slack)
183
- out.push("slack");
184
- return out;
185
- }
@@ -1 +0,0 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src.legacy/chat/config.ts"],"names":[],"mappings":"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"}
@@ -1,17 +0,0 @@
1
- /**
2
- * Resolve the active project's UUID for chat-routing operations
3
- * (v0.7.1 Phase E).
4
- *
5
- * Strategy:
6
- * 1. If `OPENSQUID_PROJECT_UUID` env var is set, use it verbatim.
7
- * 2. Walk up from `cwd` looking for `.opensquid/project.json` and
8
- * return its uuid.
9
- * 3. Return null — the caller decides whether to error or fall back
10
- * to the orphan path.
11
- *
12
- * Per-tool fallback: tools that need a project uuid surface a clear
13
- * error message instead of silently routing to orphan; the user can
14
- * run `opensquid project init` to create a card if missing.
15
- */
16
- export declare function resolveActiveProjectUuid(cwd?: string): Promise<string | null>;
17
- //# sourceMappingURL=active-project.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"active-project.d.ts","sourceRoot":"","sources":["../../../src.legacy/chat/daemon/active-project.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,wBAAsB,wBAAwB,CAC5C,GAAG,GAAE,MAAsB,GAC1B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAIxB"}
@@ -1,23 +0,0 @@
1
- /**
2
- * Resolve the active project's UUID for chat-routing operations
3
- * (v0.7.1 Phase E).
4
- *
5
- * Strategy:
6
- * 1. If `OPENSQUID_PROJECT_UUID` env var is set, use it verbatim.
7
- * 2. Walk up from `cwd` looking for `.opensquid/project.json` and
8
- * return its uuid.
9
- * 3. Return null — the caller decides whether to error or fall back
10
- * to the orphan path.
11
- *
12
- * Per-tool fallback: tools that need a project uuid surface a clear
13
- * error message instead of silently routing to orphan; the user can
14
- * run `opensquid project init` to create a card if missing.
15
- */
16
- import { findProjectCard } from "../../project.js";
17
- export async function resolveActiveProjectUuid(cwd = process.cwd()) {
18
- if (process.env.OPENSQUID_PROJECT_UUID)
19
- return process.env.OPENSQUID_PROJECT_UUID;
20
- const found = await findProjectCard(cwd);
21
- return found?.card.uuid ?? null;
22
- }
23
- //# sourceMappingURL=active-project.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"active-project.js","sourceRoot":"","sources":["../../../src.legacy/chat/daemon/active-project.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEnD,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,MAAc,OAAO,CAAC,GAAG,EAAE;IAE3B,IAAI,OAAO,CAAC,GAAG,CAAC,sBAAsB;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC;IAClF,MAAM,KAAK,GAAG,MAAM,eAAe,CAAC,GAAG,CAAC,CAAC;IACzC,OAAO,KAAK,EAAE,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC;AAClC,CAAC"}
@@ -1,40 +0,0 @@
1
- /**
2
- * Daemon auto-spawn from MCP server (v0.7.1 Phase D).
3
- *
4
- * On MCP server boot, we want to opportunistically ensure the chat-
5
- * daemon is running so chat_send routes through the daemon (Phase B)
6
- * and inbound messages land in per-project inboxes (Phase C). Without
7
- * auto-spawn the user has to remember `opensquid chat-daemon start`
8
- * once per machine after every reboot, which defeats the
9
- * "unconscious tool" goal.
10
- *
11
- * Behavior:
12
- * - No-op if no chat_connections configured (no point in a daemon
13
- * with zero adapters).
14
- * - No-op if daemon already running.
15
- * - Otherwise try to acquire an atomic spawn lock (fs.open(lock,
16
- * 'wx') — EEXIST = another MCP server is spawning). If acquired,
17
- * spawn and release. If not, wait briefly for the other process's
18
- * pidfile to appear.
19
- * - Always async fire-and-forget — never blocks MCP server boot.
20
- *
21
- * Stale lock handling: a lockfile older than ~15s is assumed stale
22
- * (longer than the plausible spawn time) and is unlinked before
23
- * retry. Prevents permanent jam if a previous spawner crashed.
24
- */
25
- export interface AutoSpawnResult {
26
- status: "spawned" | "already_running" | "waited_for_peer" | "no_config" | "skipped" | "error";
27
- pid?: number;
28
- error?: string;
29
- }
30
- /**
31
- * Best-effort: ensure a chat-daemon is running. Returns immediately
32
- * on the no-op paths (no config, already running, peer-spawning).
33
- * Never throws — callers can fire-and-forget without try/catch.
34
- */
35
- export declare function ensureDaemonRunning(opts?: {
36
- dataRoot?: string;
37
- /** For tests: override the entrypoint passed to startDaemon. */
38
- entrypoint?: string;
39
- }): Promise<AutoSpawnResult>;
40
- //# sourceMappingURL=autospawn.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"autospawn.d.ts","sourceRoot":"","sources":["../../../src.legacy/chat/daemon/autospawn.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAaH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,SAAS,GAAG,iBAAiB,GAAG,iBAAiB,GAAG,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC;IAC9F,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,GAAE;IACJ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gEAAgE;IAChE,UAAU,CAAC,EAAE,MAAM,CAAC;CAChB,GACL,OAAO,CAAC,eAAe,CAAC,CAyC1B"}
@@ -1,129 +0,0 @@
1
- /**
2
- * Daemon auto-spawn from MCP server (v0.7.1 Phase D).
3
- *
4
- * On MCP server boot, we want to opportunistically ensure the chat-
5
- * daemon is running so chat_send routes through the daemon (Phase B)
6
- * and inbound messages land in per-project inboxes (Phase C). Without
7
- * auto-spawn the user has to remember `opensquid chat-daemon start`
8
- * once per machine after every reboot, which defeats the
9
- * "unconscious tool" goal.
10
- *
11
- * Behavior:
12
- * - No-op if no chat_connections configured (no point in a daemon
13
- * with zero adapters).
14
- * - No-op if daemon already running.
15
- * - Otherwise try to acquire an atomic spawn lock (fs.open(lock,
16
- * 'wx') — EEXIST = another MCP server is spawning). If acquired,
17
- * spawn and release. If not, wait briefly for the other process's
18
- * pidfile to appear.
19
- * - Always async fire-and-forget — never blocks MCP server boot.
20
- *
21
- * Stale lock handling: a lockfile older than ~15s is assumed stale
22
- * (longer than the plausible spawn time) and is unlinked before
23
- * retry. Prevents permanent jam if a previous spawner crashed.
24
- */
25
- import { promises as fs } from "node:fs";
26
- import * as path from "node:path";
27
- import { resolveDataRoot } from "../../codex/store.js";
28
- import { loadChatConfig } from "../config.js";
29
- import { startDaemon, status } from "./lifecycle.js";
30
- const STALE_LOCK_AGE_MS = 15_000;
31
- const PIDFILE_WAIT_MS = 8_000;
32
- const PIDFILE_POLL_INTERVAL_MS = 100;
33
- /**
34
- * Best-effort: ensure a chat-daemon is running. Returns immediately
35
- * on the no-op paths (no config, already running, peer-spawning).
36
- * Never throws — callers can fire-and-forget without try/catch.
37
- */
38
- export async function ensureDaemonRunning(opts = {}) {
39
- try {
40
- const config = await loadChatConfig(opts.dataRoot);
41
- if (!config.telegram && !config.discord && !config.slack) {
42
- return { status: "no_config" };
43
- }
44
- const s = await status(opts.dataRoot);
45
- if (s.running)
46
- return { status: "already_running", pid: s.pid };
47
- const lockPath = spawnLockPath(opts.dataRoot);
48
- const acquired = await tryAcquireLock(lockPath);
49
- if (acquired) {
50
- try {
51
- // Re-check after acquiring the lock; a peer might have
52
- // finished spawning between our first status() and lock
53
- // acquisition.
54
- const s2 = await status(opts.dataRoot);
55
- if (s2.running)
56
- return { status: "already_running", pid: s2.pid };
57
- const res = await startDaemon({
58
- dataRoot: opts.dataRoot,
59
- entrypoint: opts.entrypoint,
60
- });
61
- return res.already_running
62
- ? { status: "already_running", pid: res.pid }
63
- : { status: "spawned", pid: res.pid };
64
- }
65
- finally {
66
- await releaseLock(lockPath);
67
- }
68
- }
69
- // Another MCP server has the lock — wait for the pidfile to
70
- // appear, then trust that daemon.
71
- const pid = await waitForPeerSpawn(opts.dataRoot);
72
- if (pid !== null)
73
- return { status: "waited_for_peer", pid };
74
- return { status: "error", error: "peer spawn timed out" };
75
- }
76
- catch (err) {
77
- return {
78
- status: "error",
79
- error: err instanceof Error ? err.message : String(err),
80
- };
81
- }
82
- }
83
- function spawnLockPath(dataRoot) {
84
- return path.join(resolveDataRoot(dataRoot), "chat-daemon.spawn.lock");
85
- }
86
- async function tryAcquireLock(lockPath) {
87
- await fs.mkdir(path.dirname(lockPath), { recursive: true });
88
- try {
89
- const fd = await fs.open(lockPath, "wx");
90
- await fd.write(`${process.pid}\n`);
91
- await fd.close();
92
- return true;
93
- }
94
- catch (err) {
95
- if (err.code !== "EEXIST")
96
- throw err;
97
- // Lock exists. Check age — if stale, unlink and retry once.
98
- try {
99
- const stat = await fs.stat(lockPath);
100
- if (Date.now() - stat.mtimeMs > STALE_LOCK_AGE_MS) {
101
- await fs.unlink(lockPath).catch(() => {
102
- /* race */
103
- });
104
- return tryAcquireLock(lockPath);
105
- }
106
- }
107
- catch {
108
- /* lock vanished between EEXIST and stat — retry */
109
- return tryAcquireLock(lockPath);
110
- }
111
- return false;
112
- }
113
- }
114
- async function releaseLock(lockPath) {
115
- await fs.unlink(lockPath).catch(() => {
116
- /* race-tolerant */
117
- });
118
- }
119
- async function waitForPeerSpawn(dataRoot) {
120
- const deadline = Date.now() + PIDFILE_WAIT_MS;
121
- while (Date.now() < deadline) {
122
- const s = await status(dataRoot);
123
- if (s.running)
124
- return s.pid;
125
- await new Promise((r) => setTimeout(r, PIDFILE_POLL_INTERVAL_MS));
126
- }
127
- return null;
128
- }
129
- //# sourceMappingURL=autospawn.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"autospawn.js","sourceRoot":"","sources":["../../../src.legacy/chat/daemon/autospawn.ts"],"names":[],"mappings":"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"}
@@ -1,112 +0,0 @@
1
- /**
2
- * autospawn.test.ts (v0.7.1 Phase D) — exercises ensureDaemonRunning
3
- * decision branches against real tmpdirs. Uses the real lifecycle
4
- * primitives so the spawn behavior is end-to-end realistic.
5
- */
6
- import { promises as fs } from "node:fs";
7
- import * as os from "node:os";
8
- import * as path from "node:path";
9
- import { afterEach, beforeEach, describe, expect, it } from "vitest";
10
- import { ensureDaemonRunning } from "./autospawn.js";
11
- import { saveChatConfig } from "../config.js";
12
- import { stopDaemon } from "./lifecycle.js";
13
- // Resolve to the built dist/index.js so the spawned worker runs the
14
- // real chat-daemon-worker subcommand (vitest's runner doesn't have it).
15
- const REPO_ROOT = path.resolve(__dirname, "../../..");
16
- const ENTRYPOINT = path.join(REPO_ROOT, "dist", "index.js");
17
- let tmpRoot;
18
- let prevHome;
19
- let prevOsHome;
20
- beforeEach(async () => {
21
- tmpRoot = await fs.mkdtemp(path.join(os.tmpdir(), "opensquid-autospawn-test-"));
22
- prevHome = process.env.OPENSQUID_HOME;
23
- prevOsHome = process.env.HOME;
24
- process.env.OPENSQUID_HOME = tmpRoot;
25
- // 0.7.5 (#148): override HOME so the env-token .env candidate paths
26
- // (~/.loop/.env etc) point at the empty tmpdir, not the real home
27
- // where a user-saved .env would synthesize a telegram config and
28
- // turn what should be `no_config` into `spawned`.
29
- process.env.HOME = tmpRoot;
30
- });
31
- afterEach(async () => {
32
- // Best-effort stop any daemon left behind by a failing test.
33
- try {
34
- await stopDaemon({ dataRoot: tmpRoot });
35
- }
36
- catch {
37
- /* ignore */
38
- }
39
- if (prevHome === undefined)
40
- delete process.env.OPENSQUID_HOME;
41
- else
42
- process.env.OPENSQUID_HOME = prevHome;
43
- if (prevOsHome === undefined)
44
- delete process.env.HOME;
45
- else
46
- process.env.HOME = prevOsHome;
47
- await fs.rm(tmpRoot, { recursive: true, force: true });
48
- });
49
- describe("ensureDaemonRunning — decision branches", () => {
50
- it("returns no_config when chat_connections is empty", async () => {
51
- const res = await ensureDaemonRunning({ dataRoot: tmpRoot, entrypoint: ENTRYPOINT });
52
- expect(res.status).toBe("no_config");
53
- });
54
- // The spawn-success path requires a real Telegram bot token (or the
55
- // adapter start fails and the worker exits — autospawn correctly
56
- // reports "error"). The full spawn path is already covered by
57
- // lifecycle.test.ts (empty config → worker parks idle → spawn
58
- // succeeds without network) and by manual end-to-end smoke. Here
59
- // we exercise the autospawn-specific behaviors that DON'T require
60
- // a real token: lock release, stale-lock cleanup, and decision
61
- // logic with no config.
62
- it("releases the spawn lock after the attempt (regardless of spawn outcome)", async () => {
63
- await saveChatConfig({ telegram: { bot_token: "1234:fake-token-for-test-only-no-network" } }, tmpRoot);
64
- await ensureDaemonRunning({ dataRoot: tmpRoot, entrypoint: ENTRYPOINT });
65
- const lockPath = path.join(tmpRoot, "chat-daemon.spawn.lock");
66
- const lockExists = await fs
67
- .access(lockPath)
68
- .then(() => true)
69
- .catch(() => false);
70
- expect(lockExists).toBe(false);
71
- }, 15000);
72
- it("clears a stale spawn lock (older than threshold) and re-attempts", async () => {
73
- await saveChatConfig({ telegram: { bot_token: "1234:fake-token-for-test-only-no-network" } }, tmpRoot);
74
- // Create an aged lockfile by writing it then back-dating its mtime.
75
- const lockPath = path.join(tmpRoot, "chat-daemon.spawn.lock");
76
- await fs.writeFile(lockPath, "stale\n");
77
- const ancient = new Date(Date.now() - 60_000);
78
- await fs.utimes(lockPath, ancient, ancient);
79
- const res = await ensureDaemonRunning({ dataRoot: tmpRoot, entrypoint: ENTRYPOINT });
80
- // Regardless of spawn success (depends on whether the fake token
81
- // is accepted), the stale lock should be gone afterwards.
82
- const stillExists = await fs
83
- .access(lockPath)
84
- .then(() => true)
85
- .catch(() => false);
86
- expect(stillExists).toBe(false);
87
- // Status must be a real decision outcome, not 'no_config'.
88
- expect(res.status).not.toBe("no_config");
89
- }, 15000);
90
- it("returns already_running when called against a manually-started daemon", async () => {
91
- // No chat config → empty-config daemon parks idle without a network call.
92
- // We start the daemon ourselves, then call ensureDaemonRunning
93
- // with config present to force the autospawn check path.
94
- const { startDaemon } = await import("./lifecycle.js");
95
- await startDaemon({ dataRoot: tmpRoot, entrypoint: ENTRYPOINT });
96
- // Configure chat AFTER spawning so the daemon parks without a
97
- // token (the empty config at spawn time means no adapter starts,
98
- // but the post-hoc save lets the autospawn check find a config).
99
- await saveChatConfig({ telegram: { bot_token: "1234:fake-token-for-test-only-no-network" } }, tmpRoot);
100
- const res = await ensureDaemonRunning({ dataRoot: tmpRoot, entrypoint: ENTRYPOINT });
101
- expect(res.status).toBe("already_running");
102
- expect(res.pid).toBeGreaterThan(0);
103
- }, 15000);
104
- it("never throws on a corrupt config — surfaces as status:error", async () => {
105
- // Write a config.json that loadChatConfig will read OK but with no chat
106
- // blocks. That triggers the no_config path, not an error.
107
- await fs.writeFile(path.join(tmpRoot, "config.json"), JSON.stringify({ version: 1 }));
108
- const res = await ensureDaemonRunning({ dataRoot: tmpRoot, entrypoint: ENTRYPOINT });
109
- // No chat → no_config (not an error).
110
- expect(res.status).toBe("no_config");
111
- });
112
- });
@@ -1,18 +0,0 @@
1
- /**
2
- * Chat-daemon CLI dispatch (v0.7.1 Phase A).
3
- *
4
- * Two entry shapes:
5
- * `opensquid chat-daemon {start|stop|status}` — user-facing
6
- * `opensquid chat-daemon-worker` — internal, never type
7
- *
8
- * `start` spawns the worker as a detached child and exits. The worker
9
- * subcommand IS the long-running daemon — never invoke it manually
10
- * unless you want to inspect logs in the foreground.
11
- */
12
- export declare function runChatDaemonCli(subcommand: string, argv: string[]): Promise<number>;
13
- /**
14
- * Internal worker entrypoint — not for direct user invocation.
15
- * Called by the detached child spawned by lifecycle.startDaemon().
16
- */
17
- export declare function runChatDaemonWorker(): Promise<never>;
18
- //# sourceMappingURL=cli.d.ts.map