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 +0,0 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../../src.legacy/chat/daemon/cli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,wBAAsB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAkD1F;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,KAAK,CAAC,CAE1D"}
@@ -1,71 +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
- import { runDaemonWorker } from "./worker.js";
13
- import { startDaemon, status, stopDaemon } from "./lifecycle.js";
14
- export async function runChatDaemonCli(subcommand, argv) {
15
- switch (subcommand) {
16
- case "start": {
17
- const res = await startDaemon();
18
- if (res.already_running) {
19
- process.stdout.write(`[chat-daemon] already running (pid ${res.pid})\n`);
20
- }
21
- else {
22
- process.stdout.write(`[chat-daemon] started (pid ${res.pid})\n`);
23
- }
24
- return 0;
25
- }
26
- case "stop": {
27
- const res = await stopDaemon();
28
- if (res.stopped) {
29
- process.stdout.write(`[chat-daemon] stopped (pid ${res.pid})\n`);
30
- }
31
- else {
32
- process.stdout.write(`[chat-daemon] not running\n`);
33
- }
34
- return 0;
35
- }
36
- case "status": {
37
- const s = await status();
38
- if (s.running) {
39
- const upMin = s.uptime_ms !== null ? (s.uptime_ms / 60000).toFixed(1) : "?";
40
- process.stdout.write(`[chat-daemon] running (pid ${s.pid}, up ${upMin}m)\n`);
41
- return 0;
42
- }
43
- if (s.stale_pid !== undefined) {
44
- process.stdout.write(`[chat-daemon] not running (stale pidfile points at ${s.stale_pid})\n`);
45
- return 1;
46
- }
47
- process.stdout.write(`[chat-daemon] not running\n`);
48
- return 1;
49
- }
50
- case "restart": {
51
- const wasRunning = await status();
52
- if (wasRunning.running)
53
- await stopDaemon();
54
- const res = await startDaemon();
55
- process.stdout.write(`[chat-daemon] restarted (pid ${res.pid})\n`);
56
- return 0;
57
- }
58
- default:
59
- process.stderr.write(`[chat-daemon] usage: opensquid chat-daemon {start|stop|status|restart}\n` +
60
- ` argv received: ${JSON.stringify([subcommand, ...argv])}\n`);
61
- return 1;
62
- }
63
- }
64
- /**
65
- * Internal worker entrypoint — not for direct user invocation.
66
- * Called by the detached child spawned by lifecycle.startDaemon().
67
- */
68
- export async function runChatDaemonWorker() {
69
- return runDaemonWorker();
70
- }
71
- //# sourceMappingURL=cli.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../../src.legacy/chat/daemon/cli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjE,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,UAAkB,EAAE,IAAc;IACvE,QAAQ,UAAU,EAAE,CAAC;QACnB,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,MAAM,GAAG,GAAG,MAAM,WAAW,EAAE,CAAC;YAChC,IAAI,GAAG,CAAC,eAAe,EAAE,CAAC;gBACxB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,sCAAsC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;YAC3E,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,8BAA8B,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;YACnE,CAAC;YACD,OAAO,CAAC,CAAC;QACX,CAAC;QACD,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,MAAM,GAAG,GAAG,MAAM,UAAU,EAAE,CAAC;YAC/B,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;gBAChB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,8BAA8B,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;YACnE,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;YACtD,CAAC;YACD,OAAO,CAAC,CAAC;QACX,CAAC;QACD,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,CAAC,GAAG,MAAM,MAAM,EAAE,CAAC;YACzB,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;gBACd,MAAM,KAAK,GAAG,CAAC,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;gBAC5E,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC,GAAG,QAAQ,KAAK,MAAM,CAAC,CAAC;gBAC7E,OAAO,CAAC,CAAC;YACX,CAAC;YACD,IAAI,CAAC,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;gBAC9B,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,sDAAsD,CAAC,CAAC,SAAS,KAAK,CACvE,CAAC;gBACF,OAAO,CAAC,CAAC;YACX,CAAC;YACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;YACpD,OAAO,CAAC,CAAC;QACX,CAAC;QACD,KAAK,SAAS,CAAC,CAAC,CAAC;YACf,MAAM,UAAU,GAAG,MAAM,MAAM,EAAE,CAAC;YAClC,IAAI,UAAU,CAAC,OAAO;gBAAE,MAAM,UAAU,EAAE,CAAC;YAC3C,MAAM,GAAG,GAAG,MAAM,WAAW,EAAE,CAAC;YAChC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gCAAgC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;YACnE,OAAO,CAAC,CAAC;QACX,CAAC;QACD;YACE,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,0EAA0E;gBACxE,oBAAoB,IAAI,CAAC,SAAS,CAAC,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,CAAC,IAAI,CAChE,CAAC;YACF,OAAO,CAAC,CAAC;IACb,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB;IACvC,OAAO,eAAe,EAAE,CAAC;AAC3B,CAAC"}
@@ -1,384 +0,0 @@
1
- /**
2
- * collisions.ts — TPS.5 (v0.5.124).
3
- *
4
- * Surfaces `buildRoutingIndex` collisions through three durable channels
5
- * instead of the one (daemon log) v0.5.x had. Replaces the "warning lost
6
- * in a log nobody tails" failure mode with:
7
- *
8
- * 1. `~/.opensquid/collisions.jsonl` — append-only audit trail.
9
- * 2. Telegram general-topic notification — debounced 60min per key
10
- * so a long-standing collision pings the operator once an hour,
11
- * not every routing reload.
12
- * 3. MCP `chat_poll_inbox` — prepends warning lines to the poll
13
- * response when an unresolved collision affects the active
14
- * workspace (read path lives in `src/mcp/chat-bridge-server.ts`).
15
- *
16
- * Source of truth is the JSONL file: write-once-on-every-collision +
17
- * read-tail-on-every-poll. Debounce state is derived from the records
18
- * themselves (last `notified_via_telegram=true` timestamp for the same
19
- * channel_key) so daemon restarts don't reset the cooldown.
20
- *
21
- * Concurrency: single writer (the chat-daemon worker), many readers
22
- * (per-project MCP bridge subprocesses). POSIX O_APPEND keeps
23
- * sub-PIPE_BUF writes atomic. Malformed lines are skipped on read.
24
- *
25
- * Failure isolation: NEVER block the routing rebuild. Disk full →
26
- * stderr log + continue. Telegram send failure → log + the JSONL line
27
- * (which already wrote) still surfaces the collision on next MCP poll.
28
- *
29
- * Rebuild path: same ad-hoc tsc invocation as the other src.legacy/
30
- * modules — see `src.legacy/chat/adapters/telegram.ts` header.
31
- */
32
- import { promises as fs } from "node:fs";
33
- import * as path from "node:path";
34
- import { loadAllProjectChatRouting } from "./routing.js";
35
- export const DEBOUNCE_WINDOW_MS = 60 * 60 * 1000;
36
- // ---------------------------------------------------------------------
37
- // Paths
38
- // ---------------------------------------------------------------------
39
- export function collisionsPath(dataRoot) {
40
- const root = dataRoot ?? process.env.OPENSQUID_HOME;
41
- if (!root || root.length === 0) {
42
- throw new Error("collisionsPath: dataRoot not provided and OPENSQUID_HOME unset");
43
- }
44
- return path.join(root, "collisions.jsonl");
45
- }
46
- // ---------------------------------------------------------------------
47
- // Read / debounce
48
- // ---------------------------------------------------------------------
49
- /**
50
- * Read the full discriminated union from `collisions.jsonl`, dropping
51
- * malformed lines and unknown-shape records. Returns [] on missing
52
- * file. TPS.7 (v0.5.130) — supersedes pre-TPS.7 single-type readers.
53
- *
54
- * Records without an explicit `kind` are treated as `CollisionEntry`
55
- * (back-compat with TPS.5 writes).
56
- */
57
- export async function loadAllCollisionsLines(dataRoot) {
58
- const p = collisionsPath(dataRoot);
59
- let raw;
60
- try {
61
- raw = await fs.readFile(p, "utf8");
62
- }
63
- catch (err) {
64
- if (err.code === "ENOENT")
65
- return [];
66
- throw err;
67
- }
68
- const out = [];
69
- for (const line of raw.split("\n")) {
70
- if (line.length === 0)
71
- continue;
72
- try {
73
- const parsed = JSON.parse(line);
74
- if (parsed.v !== 1 || typeof parsed.channel_key !== "string")
75
- continue;
76
- const kind = parsed.kind;
77
- if (kind === "topic_gone") {
78
- const ev = parsed;
79
- if (typeof ev.workspace_uuid === "string" &&
80
- typeof ev.chat_id === "string" &&
81
- typeof ev.topic_id === "number") {
82
- out.push(ev);
83
- }
84
- }
85
- else {
86
- // kind missing OR explicitly "collision" — treat as CollisionEntry.
87
- const ent = parsed;
88
- if (Array.isArray(ent.claimants) && typeof ent.winner_uuid === "string") {
89
- out.push(ent);
90
- }
91
- }
92
- }
93
- catch {
94
- /* skip malformed line */
95
- }
96
- }
97
- return out;
98
- }
99
- /**
100
- * TPS.5 back-compat reader — filters `loadAllCollisionsLines` to just
101
- * `CollisionEntry` records (drops TPS.7 `TopicGoneEvent` lines). Used
102
- * by the debounce scan in `recordCollision` so a recent topic-gone
103
- * event doesn't suppress a fresh collision notification.
104
- */
105
- export async function loadAllCollisions(dataRoot) {
106
- const all = await loadAllCollisionsLines(dataRoot);
107
- return all.filter((line) => {
108
- const kind = line.kind;
109
- return kind === undefined || kind === "collision";
110
- });
111
- }
112
- /**
113
- * TPS.7 (v0.5.130) — read `TopicGoneEvent` records only. Used by the
114
- * debounce scan in `recordTopicGoneEvent` and by MCP `chat_poll_inbox`
115
- * for stale-topic warnings.
116
- */
117
- export async function loadAllTopicGoneEvents(dataRoot) {
118
- const all = await loadAllCollisionsLines(dataRoot);
119
- return all.filter((line) => {
120
- return line.kind === "topic_gone";
121
- });
122
- }
123
- /**
124
- * MCP-side helper: return collisions whose `occurred_at` is within
125
- * `maxAgeMinutes`. Used by `chat_poll_inbox` to prepend warnings
126
- * about ACTIVE (still-recent) collisions to its response.
127
- *
128
- * Default window is 24 hours — long enough that the user sees the
129
- * warning across a typical work session without surfacing ancient
130
- * collisions that the user already fixed.
131
- */
132
- export async function getRecentCollisions(maxAgeMinutes = 24 * 60, dataRoot) {
133
- const cutoff = Date.now() - maxAgeMinutes * 60 * 1000;
134
- const all = await loadAllCollisions(dataRoot);
135
- return all.filter((e) => {
136
- const t = Date.parse(e.occurred_at);
137
- return Number.isFinite(t) && t >= cutoff;
138
- });
139
- }
140
- /**
141
- * TPS.7 (v0.5.130) — same default window as `getRecentCollisions` but
142
- * for `TopicGoneEvent` records. Surfaced through MCP `chat_poll_inbox`
143
- * so the agent learns "your topic was deleted; daemon cleared the
144
- * binding; next session will rebind automatically" within the same
145
- * 24h window.
146
- */
147
- export async function getRecentTopicGoneEvents(maxAgeMinutes = 24 * 60, dataRoot) {
148
- const cutoff = Date.now() - maxAgeMinutes * 60 * 1000;
149
- const all = await loadAllTopicGoneEvents(dataRoot);
150
- return all.filter((e) => {
151
- const t = Date.parse(e.occurred_at);
152
- return Number.isFinite(t) && t >= cutoff;
153
- });
154
- }
155
- /**
156
- * Find the most recent record (if any) that fired a Telegram
157
- * notification for the same channel_key. Used to decide whether a
158
- * new collision is within the debounce window.
159
- */
160
- function lastNotifiedAt(entries, channelKey) {
161
- let best = null;
162
- for (const e of entries) {
163
- if (e.channel_key !== channelKey)
164
- continue;
165
- if (!e.notified_via_telegram)
166
- continue;
167
- const t = Date.parse(e.occurred_at);
168
- if (!Number.isFinite(t))
169
- continue;
170
- if (best === null || t > best)
171
- best = t;
172
- }
173
- return best;
174
- }
175
- /**
176
- * Record a collision: append a structured JSONL entry, and (if outside
177
- * the debounce window + a Telegram report_channel exists) fire a
178
- * one-shot notification to the supergroup's general topic. Returns
179
- * the entry that was appended.
180
- *
181
- * NEVER throws past the caller: persist failures log to stderr; send
182
- * failures log + flip the `notified_via_telegram` flag back to false
183
- * for the persisted record. The routing rebuild that triggered this
184
- * call must always complete.
185
- */
186
- export async function recordCollision(args) {
187
- const now = (args.nowMs ?? Date.now)();
188
- const existing = await loadAllCollisions(args.dataRoot).catch(() => []);
189
- const lastNotified = lastNotifiedAt(existing, args.info.channel_key);
190
- const withinDebounce = lastNotified !== null && now - lastNotified < DEBOUNCE_WINDOW_MS;
191
- // Decide whether we WILL notify this time. The final
192
- // `notified_via_telegram` value reflects the send result (see below).
193
- const shouldNotify = !withinDebounce && args.gateway !== undefined;
194
- // Try Telegram notification BEFORE appending so the persisted flag
195
- // reflects reality. If gateway send fails (rate limit, bot kicked),
196
- // we still record the collision with notified=false so the next
197
- // routing reload may retry past the debounce window.
198
- let didNotify = false;
199
- if (shouldNotify && args.gateway) {
200
- try {
201
- didNotify = await notifyCollisionViaTelegram({
202
- gateway: args.gateway,
203
- info: args.info,
204
- dataRoot: args.dataRoot,
205
- });
206
- }
207
- catch (err) {
208
- process.stderr.write(`[collisions] telegram notify failed for ${args.info.channel_key}: ${err instanceof Error ? err.message : String(err)}\n`);
209
- didNotify = false;
210
- }
211
- }
212
- const entry = {
213
- v: 1,
214
- occurred_at: new Date(now).toISOString(),
215
- channel_key: args.info.channel_key,
216
- claimants: [args.info.existing_uuid, args.info.newcomer_uuid],
217
- winner_uuid: args.info.newcomer_uuid,
218
- notified_via_telegram: didNotify,
219
- };
220
- try {
221
- await appendCollisionsLine(entry, args.dataRoot);
222
- }
223
- catch (err) {
224
- process.stderr.write(`[collisions] persist failed for ${args.info.channel_key}: ${err instanceof Error ? err.message : String(err)}\n`);
225
- }
226
- return entry;
227
- }
228
- /**
229
- * Find ANY project with a Telegram `report_channel` configured and
230
- * send the collision notification to its general topic. Picks the
231
- * first match deterministically (Map insertion order, which is
232
- * filename-sorted in `loadAllProjectChatRouting`) so notifications
233
- * are stable across daemon restarts.
234
- *
235
- * Returns true iff the send succeeded. Catches everything — caller
236
- * folds the failure into the JSONL record via `notified_via_telegram`.
237
- */
238
- async function notifyCollisionViaTelegram(args) {
239
- const configs = await loadAllProjectChatRouting(args.dataRoot);
240
- const target = pickNotificationTarget(configs);
241
- if (target === null)
242
- return false;
243
- const text = formatCollisionMessage(args.info, target.workspaceLabel);
244
- try {
245
- // Force the general topic — collisions are admin-tier notifications,
246
- // not workspace-scoped chatter. Telegram represents the general
247
- // topic as the chat itself with NO threadId, so we intentionally
248
- // omit it (don't pass report_topic_id even if set).
249
- await args.gateway.send({ channel: target.channel, text });
250
- return true;
251
- }
252
- catch {
253
- return false;
254
- }
255
- }
256
- function pickNotificationTarget(configs) {
257
- for (const [uuid, cfg] of configs) {
258
- const ch = cfg.telegram?.report_channel;
259
- if (ch && ch.length > 0) {
260
- return { channel: ch, workspaceLabel: uuid };
261
- }
262
- }
263
- return null;
264
- }
265
- function formatCollisionMessage(info, sourceLabel) {
266
- return [
267
- "⚠️ opensquid routing collision detected",
268
- "",
269
- ` channel: ${info.channel_key}`,
270
- ` existing: ${info.existing_uuid}`,
271
- ` newcomer: ${info.newcomer_uuid} (will win)`,
272
- "",
273
- `Two workspaces claim the same inbound channel. Inbound messages route to`,
274
- `the newer claimant; the older one will see nothing. Edit one of the`,
275
- `chat-routing.json files under ~/.opensquid/projects/ to resolve.`,
276
- "",
277
- `(notified by ${sourceLabel})`,
278
- ].join("\n");
279
- }
280
- /**
281
- * Record a topic-gone event: append a structured JSONL entry to
282
- * collisions.jsonl, and (if outside the debounce window + a Telegram
283
- * report_channel exists) fire a one-shot notification to the
284
- * supergroup's general topic. Returns the entry that was appended.
285
- *
286
- * Mirrors `recordCollision` semantics — NEVER throws past the caller.
287
- * Persist failures log to stderr; send failures flip the
288
- * `notified_via_telegram` flag to false. The async caller in
289
- * `rpc-server.ts:handleTopicGone` doesn't await any user-visible work.
290
- *
291
- * Debounce key: the same `channel_key` shape used by collisions
292
- * (`telegram:<chat_id>:<topic_id>`). Within `DEBOUNCE_WINDOW_MS`,
293
- * additional topic-gone events for the same channel record to JSONL
294
- * but skip the Telegram ping — the user already got the alert.
295
- */
296
- export async function recordTopicGoneEvent(args) {
297
- const now = (args.nowMs ?? Date.now)();
298
- const channelKey = `telegram:${args.chatId}:${args.topicId}`;
299
- const existing = await loadAllTopicGoneEvents(args.dataRoot).catch(() => []);
300
- const lastNotified = lastTopicGoneNotifiedAt(existing, channelKey);
301
- const withinDebounce = lastNotified !== null && now - lastNotified < DEBOUNCE_WINDOW_MS;
302
- const shouldNotify = !withinDebounce && args.gateway !== undefined;
303
- let didNotify = false;
304
- if (shouldNotify && args.gateway) {
305
- try {
306
- didNotify = await notifyTopicGoneViaTelegram({
307
- gateway: args.gateway,
308
- workspaceUuid: args.workspaceUuid,
309
- chatId: args.chatId,
310
- topicId: args.topicId,
311
- dataRoot: args.dataRoot,
312
- });
313
- }
314
- catch (err) {
315
- process.stderr.write(`[collisions] topic-gone telegram notify failed for ${channelKey}: ${err instanceof Error ? err.message : String(err)}\n`);
316
- didNotify = false;
317
- }
318
- }
319
- const entry = {
320
- v: 1,
321
- kind: "topic_gone",
322
- occurred_at: new Date(now).toISOString(),
323
- channel_key: channelKey,
324
- workspace_uuid: args.workspaceUuid,
325
- chat_id: args.chatId,
326
- topic_id: args.topicId,
327
- underlying_description: args.underlyingDescription,
328
- notified_via_telegram: didNotify,
329
- };
330
- try {
331
- await appendCollisionsLine(entry, args.dataRoot);
332
- }
333
- catch (err) {
334
- process.stderr.write(`[collisions] topic-gone persist failed for ${channelKey}: ${err instanceof Error ? err.message : String(err)}\n`);
335
- }
336
- return entry;
337
- }
338
- function lastTopicGoneNotifiedAt(events, channelKey) {
339
- let best = null;
340
- for (const e of events) {
341
- if (e.channel_key !== channelKey)
342
- continue;
343
- if (!e.notified_via_telegram)
344
- continue;
345
- const t = Date.parse(e.occurred_at);
346
- if (!Number.isFinite(t))
347
- continue;
348
- if (best === null || t > best)
349
- best = t;
350
- }
351
- return best;
352
- }
353
- async function appendCollisionsLine(line, dataRoot) {
354
- const p = collisionsPath(dataRoot);
355
- await fs.mkdir(path.dirname(p), { recursive: true });
356
- await fs.appendFile(p, JSON.stringify(line) + "\n", "utf8");
357
- }
358
- async function notifyTopicGoneViaTelegram(args) {
359
- const configs = await loadAllProjectChatRouting(args.dataRoot);
360
- const target = pickNotificationTarget(configs);
361
- if (target === null)
362
- return false;
363
- const text = formatTopicGoneMessage(args);
364
- try {
365
- await args.gateway.send({ channel: target.channel, text });
366
- return true;
367
- }
368
- catch {
369
- return false;
370
- }
371
- }
372
- function formatTopicGoneMessage(args) {
373
- return [
374
- "🧹 opensquid topic binding cleared (topic was deleted)",
375
- "",
376
- ` workspace: ${args.workspaceUuid}`,
377
- ` chat_id: ${args.chatId}`,
378
- ` topic_id: ${args.topicId} (no longer exists)`,
379
- "",
380
- `The bound forum topic was deleted from the supergroup. The daemon`,
381
- `cleared the stale binding; the next MCP-bridge subscribe for this`,
382
- `workspace will auto-rebind to a fresh topic (TPS.6 auto-boot).`,
383
- ].join("\n");
384
- }
@@ -1,69 +0,0 @@
1
- /**
2
- * Startup health checks for chat-daemon's configured inbound channels
3
- * (v0.5.89 / TG.2).
4
- *
5
- * Why this exists: the daemon's inbound path silently accepts whatever
6
- * Telegram delivers via long-poll. If the bot has been kicked from a
7
- * supergroup, or the supergroup_id in chat-routing.json is stale, or
8
- * the bot doesn't have read permission, the symptom is identical:
9
- * "no inbound messages from that chat ever arrive". The daemon log
10
- * looks healthy. The user assumes their routing is broken.
11
- *
12
- * This module adds one round-trip per unique inbound chat_id at
13
- * daemon startup, calling Telegram's `getChat` HTTPS endpoint, and
14
- * logs a clear reachability verdict per chat_id. Catches:
15
- *
16
- * - 403 Forbidden ("bot was kicked from the supergroup chat") — the
17
- * load-bearing case this module was written to catch.
18
- * - 400 Bad Request (chat_id doesn't exist or bot can't see it) —
19
- * surfaces typo'd or stale chat_ids.
20
- * - Network failures — distinguishes config error from connectivity
21
- * issues.
22
- *
23
- * Scope discipline:
24
- * - Telegram-only. Discord + Slack health checks deferred (their
25
- * SDKs require different shapes; one-platform-at-a-time).
26
- * - Best-effort. Health-check failures DO NOT block daemon startup;
27
- * they log warnings and let the daemon continue. A bot that's
28
- * kicked from one chat may still be fine for outbound to others.
29
- * - No grammy dependency. Uses native fetch so this module can run
30
- * even if grammy isn't loaded yet (it's a dynamic import elsewhere).
31
- *
32
- * Imports from: nothing (fetch is global in Node 20+).
33
- * Imported by: src.legacy/chat/daemon/worker.ts (post-gateway-start).
34
- */
35
- export interface ChatReachability {
36
- /** The chat_id we tested, in raw string form (e.g. `-1001234567890` for a supergroup). */
37
- chatId: string;
38
- /** True iff Telegram returned `ok: true` on getChat. */
39
- ok: boolean;
40
- /** Chat title when known (supergroups + channels carry it). */
41
- title?: string;
42
- /** Chat type when known (`supergroup`, `group`, `channel`, `private`). */
43
- chatType?: string;
44
- /** Telegram error_code when not ok (typically 403 or 400). */
45
- errorCode?: number;
46
- /** Telegram description string when not ok. */
47
- errorDescription?: string;
48
- /** Set when the round-trip itself failed (DNS, TLS, timeout). */
49
- networkError?: string;
50
- }
51
- /**
52
- * Call Telegram getChat for each chat_id and return per-chat
53
- * reachability. Sequential because the call count is small (typically
54
- * 1–3 chats per project, 1–10 projects per host) and Telegram's bot
55
- * API rate limits favor sequential calls over bursts. Per-call
56
- * timeout is 5s — enough for legitimate latency, short enough that
57
- * a hung API doesn't block daemon startup forever.
58
- *
59
- * `botToken` is the loaded Telegram bot token. If absent or empty,
60
- * returns an empty array (no point health-checking without a token).
61
- */
62
- export declare function verifyTelegramChats(botToken: string | undefined, chatIds: readonly string[]): Promise<ChatReachability[]>;
63
- /**
64
- * Render a single reachability verdict as a one-line log message.
65
- * Stays formatting-stable so operators can grep daemon logs for
66
- * `[chat-daemon] chat-reachability` to find all verdicts in one pass.
67
- */
68
- export declare function formatReachabilityLine(r: ChatReachability): string;
69
- //# sourceMappingURL=health-check.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"health-check.d.ts","sourceRoot":"","sources":["../../../src.legacy/chat/daemon/health-check.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,0FAA0F;IAC1F,MAAM,EAAE,MAAM,CAAC;IACf,wDAAwD;IACxD,EAAE,EAAE,OAAO,CAAC;IACZ,+DAA+D;IAC/D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+CAA+C;IAC/C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,iEAAiE;IACjE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAaD;;;;;;;;;;GAUG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,OAAO,EAAE,SAAS,MAAM,EAAE,GACzB,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAU7B;AAiCD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAclE"}
@@ -1,112 +0,0 @@
1
- /**
2
- * Startup health checks for chat-daemon's configured inbound channels
3
- * (v0.5.89 / TG.2).
4
- *
5
- * Why this exists: the daemon's inbound path silently accepts whatever
6
- * Telegram delivers via long-poll. If the bot has been kicked from a
7
- * supergroup, or the supergroup_id in chat-routing.json is stale, or
8
- * the bot doesn't have read permission, the symptom is identical:
9
- * "no inbound messages from that chat ever arrive". The daemon log
10
- * looks healthy. The user assumes their routing is broken.
11
- *
12
- * This module adds one round-trip per unique inbound chat_id at
13
- * daemon startup, calling Telegram's `getChat` HTTPS endpoint, and
14
- * logs a clear reachability verdict per chat_id. Catches:
15
- *
16
- * - 403 Forbidden ("bot was kicked from the supergroup chat") — the
17
- * load-bearing case this module was written to catch.
18
- * - 400 Bad Request (chat_id doesn't exist or bot can't see it) —
19
- * surfaces typo'd or stale chat_ids.
20
- * - Network failures — distinguishes config error from connectivity
21
- * issues.
22
- *
23
- * Scope discipline:
24
- * - Telegram-only. Discord + Slack health checks deferred (their
25
- * SDKs require different shapes; one-platform-at-a-time).
26
- * - Best-effort. Health-check failures DO NOT block daemon startup;
27
- * they log warnings and let the daemon continue. A bot that's
28
- * kicked from one chat may still be fine for outbound to others.
29
- * - No grammy dependency. Uses native fetch so this module can run
30
- * even if grammy isn't loaded yet (it's a dynamic import elsewhere).
31
- *
32
- * Imports from: nothing (fetch is global in Node 20+).
33
- * Imported by: src.legacy/chat/daemon/worker.ts (post-gateway-start).
34
- */
35
- /**
36
- * Call Telegram getChat for each chat_id and return per-chat
37
- * reachability. Sequential because the call count is small (typically
38
- * 1–3 chats per project, 1–10 projects per host) and Telegram's bot
39
- * API rate limits favor sequential calls over bursts. Per-call
40
- * timeout is 5s — enough for legitimate latency, short enough that
41
- * a hung API doesn't block daemon startup forever.
42
- *
43
- * `botToken` is the loaded Telegram bot token. If absent or empty,
44
- * returns an empty array (no point health-checking without a token).
45
- */
46
- export async function verifyTelegramChats(botToken, chatIds) {
47
- if (!botToken || botToken.trim().length === 0)
48
- return [];
49
- if (chatIds.length === 0)
50
- return [];
51
- const unique = Array.from(new Set(chatIds));
52
- const results = [];
53
- for (const chatId of unique) {
54
- results.push(await checkOne(botToken, chatId));
55
- }
56
- return results;
57
- }
58
- async function checkOne(token, chatId) {
59
- // 5s timeout via AbortController — keeps a hung Telegram API from
60
- // wedging daemon startup indefinitely. The daemon doesn't actually
61
- // need health-check results to be useful; if all calls time out, we
62
- // just log "skipped due to timeouts" and continue.
63
- const controller = new AbortController();
64
- const timer = setTimeout(() => controller.abort(), 5_000);
65
- try {
66
- const url = `https://api.telegram.org/bot${token}/getChat?chat_id=${encodeURIComponent(chatId)}`;
67
- const res = await fetch(url, { method: "GET", signal: controller.signal });
68
- const body = (await res.json());
69
- if (body.ok && body.result) {
70
- const r = { chatId, ok: true, chatType: body.result.type };
71
- if (body.result.title)
72
- r.title = body.result.title;
73
- return r;
74
- }
75
- const r = { chatId, ok: false };
76
- if (body.error_code !== undefined)
77
- r.errorCode = body.error_code;
78
- if (body.description)
79
- r.errorDescription = body.description;
80
- return r;
81
- }
82
- catch (err) {
83
- return {
84
- chatId,
85
- ok: false,
86
- networkError: err instanceof Error ? err.message : String(err),
87
- };
88
- }
89
- finally {
90
- clearTimeout(timer);
91
- }
92
- }
93
- /**
94
- * Render a single reachability verdict as a one-line log message.
95
- * Stays formatting-stable so operators can grep daemon logs for
96
- * `[chat-daemon] chat-reachability` to find all verdicts in one pass.
97
- */
98
- export function formatReachabilityLine(r) {
99
- if (r.ok) {
100
- const title = r.title ? ` "${r.title}"` : "";
101
- const type = r.chatType ? ` (${r.chatType})` : "";
102
- return `[chat-daemon] chat-reachability ${r.chatId}${title}${type}: OK`;
103
- }
104
- if (r.networkError) {
105
- return `[chat-daemon] chat-reachability ${r.chatId}: NETWORK_ERROR ${r.networkError}`;
106
- }
107
- // Common 403 = "Forbidden: bot was kicked from the supergroup chat"
108
- // Common 400 = "Bad Request: chat not found" (typo'd or stale id)
109
- const code = r.errorCode !== undefined ? `${r.errorCode}` : "?";
110
- const desc = r.errorDescription ?? "(no description)";
111
- return `[chat-daemon] chat-reachability ${r.chatId}: ERROR ${code} ${desc}`;
112
- }
@@ -1 +0,0 @@
1
- {"version":3,"file":"health-check.js","sourceRoot":"","sources":["../../../src.legacy/chat/daemon/health-check.ts"],"names":[],"mappings":"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"}