@rryando/arcs 4.2.0 → 4.2.1

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 (185) hide show
  1. package/README.md +2 -2
  2. package/dist/cli/arcs-flash.d.ts +1 -1
  3. package/dist/cli/arcs-flash.d.ts.map +1 -1
  4. package/dist/cli/arcs-flash.js +3 -5
  5. package/dist/cli/arcs-flash.js.map +1 -1
  6. package/dist/cli/arcs-orchestrate.d.ts +1 -1
  7. package/dist/cli/arcs-orchestrate.d.ts.map +1 -1
  8. package/dist/cli/commands/index.d.ts +0 -1
  9. package/dist/cli/commands/index.d.ts.map +1 -1
  10. package/dist/cli/commands/index.js +0 -1
  11. package/dist/cli/commands/index.js.map +1 -1
  12. package/dist/cli/commands/project.js +1 -30
  13. package/dist/cli/commands/project.js.map +1 -1
  14. package/dist/cli/commands/proposal-doc.d.ts +2 -0
  15. package/dist/cli/commands/proposal-doc.d.ts.map +1 -0
  16. package/dist/cli/commands/proposal-doc.js +381 -0
  17. package/dist/cli/commands/proposal-doc.js.map +1 -0
  18. package/dist/cli/commands/web.js +4 -10
  19. package/dist/cli/commands/web.js.map +1 -1
  20. package/dist/cli/orchestrator-shared-blocks.d.ts +11 -10
  21. package/dist/cli/orchestrator-shared-blocks.d.ts.map +1 -1
  22. package/dist/cli/orchestrator-shared-blocks.js +21 -16
  23. package/dist/cli/orchestrator-shared-blocks.js.map +1 -1
  24. package/dist/utils/graphify-knowledge.d.ts +22 -0
  25. package/dist/utils/graphify-knowledge.d.ts.map +1 -0
  26. package/dist/utils/graphify-knowledge.js +47 -0
  27. package/dist/utils/graphify-knowledge.js.map +1 -0
  28. package/dist/utils/graphify.d.ts +104 -0
  29. package/dist/utils/graphify.d.ts.map +1 -0
  30. package/dist/utils/graphify.js +439 -0
  31. package/dist/utils/graphify.js.map +1 -0
  32. package/dist/utils/session-store.d.ts +24 -2
  33. package/dist/utils/session-store.d.ts.map +1 -1
  34. package/dist/utils/session-store.js +16 -7
  35. package/dist/utils/session-store.js.map +1 -1
  36. package/dist/utils/storage-utils.d.ts +1 -1
  37. package/dist/utils/storage-utils.d.ts.map +1 -1
  38. package/dist/utils/storage-utils.js +1 -1
  39. package/dist/utils/storage-utils.js.map +1 -1
  40. package/dist/web-client/assets/{GraphCanvas-BPDgvsyT.js → GraphCanvas-Dw6EcoDb.js} +1 -1
  41. package/dist/web-client/assets/{MarkdownEditor-D7TLp78z.js → MarkdownEditor-Cz5_44Ej.js} +1 -1
  42. package/dist/web-client/assets/{abnfDiagram-VRR7QNED-CyuP2N9t.js → abnfDiagram-VRR7QNED-CFJzLuew.js} +1 -1
  43. package/dist/web-client/assets/architecture-TIHT7OUA-CoHvhex9.js +1 -0
  44. package/dist/web-client/assets/{architectureDiagram-ZJ3FMSHR-DZ0ul9QX.js → architectureDiagram-ZJ3FMSHR-FRlSgnnW.js} +1 -1
  45. package/dist/web-client/assets/{blockDiagram-677ZJIJ3-LLGzlc9l.js → blockDiagram-677ZJIJ3-WUkkunPZ.js} +1 -1
  46. package/dist/web-client/assets/{c4Diagram-LMCZKHZV-CViu3CTc.js → c4Diagram-LMCZKHZV-BKeAsL6F.js} +1 -1
  47. package/dist/web-client/assets/channel-D8xMXC5_.js +1 -0
  48. package/dist/web-client/assets/{chunk-32BRIVSS-Bw_IuJCM.js → chunk-32BRIVSS-B0b9kUcF.js} +1 -1
  49. package/dist/web-client/assets/{chunk-52WLFC77-C29h440W.js → chunk-52WLFC77-i6Y-vfL3.js} +1 -1
  50. package/dist/web-client/assets/{chunk-C7G6YPKG-hhOrvw5w.js → chunk-C7G6YPKG-atYWm6iP.js} +1 -1
  51. package/dist/web-client/assets/{chunk-EX3LRPZG-COMzol-M.js → chunk-EX3LRPZG-CZD6y0UU.js} +1 -1
  52. package/dist/web-client/assets/{chunk-FWX5IMBZ-6vdX9EUn.js → chunk-FWX5IMBZ-CVErR-UZ.js} +2 -2
  53. package/dist/web-client/assets/{chunk-HOUHSVGY-DWDW6sxp.js → chunk-HOUHSVGY-BlHO2iQ3.js} +1 -1
  54. package/dist/web-client/assets/{chunk-ICXQ74PX-BdMYglo2.js → chunk-ICXQ74PX-Ar8kfXfa.js} +1 -1
  55. package/dist/web-client/assets/{chunk-MOJQB5TN-C0LAX_dC.js → chunk-MOJQB5TN-DKrK867P.js} +1 -1
  56. package/dist/web-client/assets/{chunk-OGEWGWER-CBx8MB7f.js → chunk-OGEWGWER-BmGykUeg.js} +1 -1
  57. package/dist/web-client/assets/{chunk-PUDLZKDR-DKssR1nf.js → chunk-PUDLZKDR-Bq23pnso.js} +1 -1
  58. package/dist/web-client/assets/{chunk-Q4XR5HBZ-B3kcxFE-.js → chunk-Q4XR5HBZ-g15qvFAN.js} +1 -1
  59. package/dist/web-client/assets/{chunk-V7JOEXUC-CAlymndy.js → chunk-V7JOEXUC-uyXA7S9r.js} +1 -1
  60. package/dist/web-client/assets/{chunk-VAUOI2AC-BowfsmTW.js → chunk-VAUOI2AC-WofZ-2M0.js} +1 -1
  61. package/dist/web-client/assets/{chunk-VR4S4FIN-BBOydgvt.js → chunk-VR4S4FIN-DtTkK86v.js} +1 -1
  62. package/dist/web-client/assets/{chunk-WYO6CB5R-DcymFbES.js → chunk-WYO6CB5R-zVyUwJq3.js} +1 -1
  63. package/dist/web-client/assets/{chunk-ZGVPDNZ5--uKFP-Lr.js → chunk-ZGVPDNZ5-CA1Oe3TK.js} +1 -1
  64. package/dist/web-client/assets/classDiagram-OUVF2IWQ-Doj1_hvZ.js +1 -0
  65. package/dist/web-client/assets/classDiagram-v2-EOCWNBFH-Doj1_hvZ.js +1 -0
  66. package/dist/web-client/assets/{cynefin-VYW2F7L2-CjboUOMA.js → cynefin-VYW2F7L2-ivJY1h_9.js} +1 -1
  67. package/dist/web-client/assets/{cynefinDiagram-TSTJHNR4-BcxygBP7.js → cynefinDiagram-TSTJHNR4-D2DstShq.js} +1 -1
  68. package/dist/web-client/assets/{dagre-VKFMJZFB-D-tiERQE.js → dagre-VKFMJZFB-CwnMRy0K.js} +1 -1
  69. package/dist/web-client/assets/{diagram-FQU43EPY-ChPXczaS.js → diagram-FQU43EPY-BKJv6Cvw.js} +1 -1
  70. package/dist/web-client/assets/{diagram-G47NLZAW-CVL3Y91h.js → diagram-G47NLZAW-CwCXcgU5.js} +1 -1
  71. package/dist/web-client/assets/{diagram-NH7WQ7WH-DsaNA9Lh.js → diagram-NH7WQ7WH-CkghU1-6.js} +1 -1
  72. package/dist/web-client/assets/{diagram-OA4YK3LP-CXhrhdhU.js → diagram-OA4YK3LP-D3siQIGu.js} +1 -1
  73. package/dist/web-client/assets/{diagram-WEI45ONY-BTVPnk4E.js → diagram-WEI45ONY-CSs9xTBn.js} +1 -1
  74. package/dist/web-client/assets/{ebnfDiagram-CCIWWBDH-BAyrRBtM.js → ebnfDiagram-CCIWWBDH--i52vMiv.js} +1 -1
  75. package/dist/web-client/assets/{erDiagram-Q63AITRT-Qm24Wepm.js → erDiagram-Q63AITRT-q2hgOBY1.js} +1 -1
  76. package/dist/web-client/assets/eventmodeling-45OFAUF4-ESVuFkJJ.js +1 -0
  77. package/dist/web-client/assets/flowDiagram-23GEKE2U-DN9SdR9f.js +1 -0
  78. package/dist/web-client/assets/{ganttDiagram-NO4QXBWP-D8h7l3XJ.js → ganttDiagram-NO4QXBWP-BZ2rBbTe.js} +1 -1
  79. package/dist/web-client/assets/{gitGraph-TEB2WS4Q-DIBml1SB.js → gitGraph-TEB2WS4Q-OnJ8tHgt.js} +1 -1
  80. package/dist/web-client/assets/{gitGraphDiagram-IHSO6WYX-CtkYoXjn.js → gitGraphDiagram-IHSO6WYX-CPNExFAr.js} +1 -1
  81. package/dist/web-client/assets/{index-DOSH4Q9H.js → index-DCBn-YrR.js} +38 -38
  82. package/dist/web-client/assets/{info-DKCQHKI2-DLEUtV5Q.js → info-DKCQHKI2-DGuJbmdY.js} +1 -1
  83. package/dist/web-client/assets/{infoDiagram-FWYZ7A6U-BJQ7aQux.js → infoDiagram-FWYZ7A6U-ADIAn-P5.js} +1 -1
  84. package/dist/web-client/assets/{ishikawaDiagram-FXEZZL3T-BPM11FvG.js → ishikawaDiagram-FXEZZL3T-CUx-RGfg.js} +1 -1
  85. package/dist/web-client/assets/{journeyDiagram-5HDEW3XC-C0aX2z3c.js → journeyDiagram-5HDEW3XC-BH7-tBBy.js} +1 -1
  86. package/dist/web-client/assets/{kanban-definition-HUTT4EX6-C56F29Ib.js → kanban-definition-HUTT4EX6-BGEXBnI2.js} +1 -1
  87. package/dist/web-client/assets/{line-BLFHLF2N.js → line-CC-5ezU8.js} +1 -1
  88. package/dist/web-client/assets/{mermaid-parser.core-BLC8FhgU.js → mermaid-parser.core-Dw18Fjbq.js} +3 -3
  89. package/dist/web-client/assets/{mermaid.core-BBqkKuXt.js → mermaid.core-CMQBgE43.js} +3 -3
  90. package/dist/web-client/assets/{mindmap-definition-LN4V7U3C-aVZbsoPc.js → mindmap-definition-LN4V7U3C-CGtjw8tB.js} +1 -1
  91. package/dist/web-client/assets/{packet-7NZHBO7P-D4aqSQfB.js → packet-7NZHBO7P-w71Y4Hzd.js} +1 -1
  92. package/dist/web-client/assets/{pegDiagram-2B236MQR-DjfyNI0U.js → pegDiagram-2B236MQR-DWtfEm4T.js} +1 -1
  93. package/dist/web-client/assets/{pie-RZYD4A2V-ChCwYsYj.js → pie-RZYD4A2V-S9ztgnWs.js} +1 -1
  94. package/dist/web-client/assets/{pieDiagram-ENE6RG2P-BeHLKkXC.js → pieDiagram-ENE6RG2P-BWZQPN4m.js} +1 -1
  95. package/dist/web-client/assets/{quadrantDiagram-ABIIQ3AL-stga3gvq.js → quadrantDiagram-ABIIQ3AL-DINDwblH.js} +1 -1
  96. package/dist/web-client/assets/{radar-I7S5WNFK-DOGheiwT.js → radar-I7S5WNFK-BOGl9krB.js} +1 -1
  97. package/dist/web-client/assets/{railroad-3IZDKUUU-_JnU7M6L.js → railroad-3IZDKUUU-CR9kuYSZ.js} +1 -1
  98. package/dist/web-client/assets/railroad-abnf-AHOZXSZD-BvbCHrlR.js +1 -0
  99. package/dist/web-client/assets/railroad-ebnf-EBAXGLYW-D869lbCL.js +1 -0
  100. package/dist/web-client/assets/railroad-peg-LSFZ7HO6-r4TXaJPI.js +1 -0
  101. package/dist/web-client/assets/{railroadDiagram-RFXS5EU6-C0CkMsOd.js → railroadDiagram-RFXS5EU6-byLCs9hp.js} +1 -1
  102. package/dist/web-client/assets/{requirementDiagram-TGXJPOKE-DuImwoRD.js → requirementDiagram-TGXJPOKE-Dn_FtbqW.js} +1 -1
  103. package/dist/web-client/assets/{sankeyDiagram-HTMAVEWB-kprq0XF9.js → sankeyDiagram-HTMAVEWB-DUjRrCeC.js} +1 -1
  104. package/dist/web-client/assets/{sequenceDiagram-DBY2YBRQ-DiXKJMF6.js → sequenceDiagram-DBY2YBRQ-BmBz8Wpq.js} +1 -1
  105. package/dist/web-client/assets/{stateDiagram-2N3HPSRC-D5qbVStE.js → stateDiagram-2N3HPSRC-BAYHjmqB.js} +1 -1
  106. package/dist/web-client/assets/stateDiagram-v2-6OUMAXLB-Bl-1K1zV.js +1 -0
  107. package/dist/web-client/assets/{swimlanes-5IMT3BWC-DCbw389c.js → swimlanes-5IMT3BWC-Bm942AR-.js} +1 -1
  108. package/dist/web-client/assets/swimlanesDiagram-G3AALYLV-DHU7bsfA.js +8 -0
  109. package/dist/web-client/assets/{timeline-definition-FHXFAJF6-CQeaYN_9.js → timeline-definition-FHXFAJF6-CHAZHhQk.js} +1 -1
  110. package/dist/web-client/assets/{treeView-QDETBFTQ-Cf7Sq3qo.js → treeView-QDETBFTQ-DHHkLsSy.js} +1 -1
  111. package/dist/web-client/assets/{treemap-6X3UGDF4-BovzvoTU.js → treemap-6X3UGDF4-BUxZ8fhY.js} +1 -1
  112. package/dist/web-client/assets/{vennDiagram-L72KCM5P-CZsJy139.js → vennDiagram-L72KCM5P-BL9TRcUU.js} +1 -1
  113. package/dist/web-client/assets/{wardley-OPB4EBWU-DJ7MS6XZ.js → wardley-OPB4EBWU-CfJ5mO-y.js} +1 -1
  114. package/dist/web-client/assets/{wardleyDiagram-EHGQE667-rqhcmsbM.js → wardleyDiagram-EHGQE667-BlH1TSjy.js} +1 -1
  115. package/dist/web-client/assets/{xychartDiagram-FW5EYKEG-HuK4Seps.js → xychartDiagram-FW5EYKEG-BJN6wtrV.js} +1 -1
  116. package/dist/web-client/index.html +1 -1
  117. package/dist/web-server/app.d.ts.map +1 -1
  118. package/dist/web-server/app.js +1 -7
  119. package/dist/web-server/app.js.map +1 -1
  120. package/dist/web-server/claude-runner.d.ts +11 -4
  121. package/dist/web-server/claude-runner.d.ts.map +1 -1
  122. package/dist/web-server/claude-runner.js +10 -14
  123. package/dist/web-server/claude-runner.js.map +1 -1
  124. package/dist/web-server/index.d.ts.map +1 -1
  125. package/dist/web-server/index.js +4 -1
  126. package/dist/web-server/index.js.map +1 -1
  127. package/dist/web-server/opencode-client.d.ts +123 -0
  128. package/dist/web-server/opencode-client.d.ts.map +1 -0
  129. package/dist/web-server/opencode-client.js +514 -0
  130. package/dist/web-server/opencode-client.js.map +1 -0
  131. package/dist/web-server/prompt-assembly.d.ts.map +1 -1
  132. package/dist/web-server/prompt-assembly.js +1 -2
  133. package/dist/web-server/prompt-assembly.js.map +1 -1
  134. package/dist/web-server/routes/sessions.d.ts +9 -6
  135. package/dist/web-server/routes/sessions.d.ts.map +1 -1
  136. package/dist/web-server/routes/sessions.js +272 -205
  137. package/dist/web-server/routes/sessions.js.map +1 -1
  138. package/dist/web-server/run-driver.d.ts +113 -0
  139. package/dist/web-server/run-driver.d.ts.map +1 -0
  140. package/dist/web-server/run-driver.js +214 -0
  141. package/dist/web-server/run-driver.js.map +1 -0
  142. package/dist/web-server/run-event-log.d.ts +23 -1
  143. package/dist/web-server/run-event-log.d.ts.map +1 -1
  144. package/dist/web-server/run-event-log.js +29 -5
  145. package/dist/web-server/run-event-log.js.map +1 -1
  146. package/dist/web-server/web-auth.d.ts +3 -5
  147. package/dist/web-server/web-auth.d.ts.map +1 -1
  148. package/dist/web-server/web-auth.js +6 -11
  149. package/dist/web-server/web-auth.js.map +1 -1
  150. package/dist/web-server/web-token.d.ts +1 -2
  151. package/dist/web-server/web-token.d.ts.map +1 -1
  152. package/dist/web-server/web-token.js +1 -2
  153. package/dist/web-server/web-token.js.map +1 -1
  154. package/opencode/arcs/bundle-runtime.json +0 -3
  155. package/opencode/arcs/prompts/arcs-docs.txt +4 -4
  156. package/opencode/arcs/prompts/arcs-flash.txt +15 -21
  157. package/opencode/arcs/prompts/arcs-orchestrate-caveman.txt +17 -15
  158. package/opencode/arcs/prompts/arcs-orchestrate.txt +17 -15
  159. package/opencode/arcs/prompts/code-reviewer.txt +4 -4
  160. package/opencode/arcs/prompts/graph-explorer.txt +4 -4
  161. package/opencode/arcs/prompts/software-engineer.txt +2 -2
  162. package/opencode/arcs/prompts/tech-architect.txt +4 -4
  163. package/opencode/arcs/skills/brainstorming/SKILL.md +4 -4
  164. package/opencode/arcs/skills/enriching-codegraph-proposals/SKILL.md +1 -1
  165. package/opencode/arcs/skills/implementation/SKILL.md +6 -6
  166. package/opencode/arcs/skills/init-project/SKILL.md +4 -4
  167. package/opencode/arcs/skills/systematic-debugging/SKILL.md +2 -2
  168. package/opencode/arcs/skills/test-driven-development/SKILL.md +3 -3
  169. package/opencode/arcs/skills/to-diagram/SKILL.md +2 -2
  170. package/opencode/arcs/skills/writing-knowledge/SKILL.md +2 -2
  171. package/opencode/arcs/skills/writing-plans/SKILL.md +2 -2
  172. package/package.json +1 -1
  173. package/dist/web-client/assets/architecture-TIHT7OUA-Bdo2Yvm9.js +0 -1
  174. package/dist/web-client/assets/channel-DBNmizpo.js +0 -1
  175. package/dist/web-client/assets/classDiagram-OUVF2IWQ-CB3HiA1_.js +0 -1
  176. package/dist/web-client/assets/classDiagram-v2-EOCWNBFH-CB3HiA1_.js +0 -1
  177. package/dist/web-client/assets/eventmodeling-45OFAUF4-DoTBIvl5.js +0 -1
  178. package/dist/web-client/assets/flowDiagram-23GEKE2U-BEH23L1A.js +0 -1
  179. package/dist/web-client/assets/railroad-abnf-AHOZXSZD-nhNub7LE.js +0 -1
  180. package/dist/web-client/assets/railroad-ebnf-EBAXGLYW-BlQYe7Yf.js +0 -1
  181. package/dist/web-client/assets/railroad-peg-LSFZ7HO6-B3E8pRVN.js +0 -1
  182. package/dist/web-client/assets/stateDiagram-v2-6OUMAXLB-DWwTAG1r.js +0 -1
  183. package/dist/web-client/assets/swimlanesDiagram-G3AALYLV-DabrCsjZ.js +0 -8
  184. package/opencode/arcs/skills/install-claude-code-hook/SKILL.md +0 -23
  185. package/scripts/claude-code-session-hook.mjs +0 -146
@@ -0,0 +1,123 @@
1
+ /**
2
+ * opencode session discovery bridge (Phase 1 — observability only).
3
+ *
4
+ * ARCS never spawns or manages an opencode server; it attaches to an already
5
+ * running `opencode serve` instance as a thin client, subscribes to the
6
+ * cross-instance `/global/event` SSE stream, and mirrors what it sees into the
7
+ * per-project session store. Everything here is best-effort: if opencode is
8
+ * not configured, not running, or speaks a different dialect, the ARCS web
9
+ * server keeps working and the sessions list is simply empty or stale.
10
+ *
11
+ * Verified against opencode 0.0.0-main-202607110203:
12
+ * - `opencode serve` defaults to port 0 (ephemeral), so a port/URL must be
13
+ * supplied explicitly via env — there is no safe default to guess.
14
+ * - `OPENCODE_SERVER_PASSWORD` is enforced as HTTP Basic auth with the literal
15
+ * username "opencode"; any other username is rejected with 401.
16
+ * - `/event` is scoped to one instance (`?directory=`); `/global/event` is the
17
+ * cross-directory stream and wraps each event as `{ directory, project,
18
+ * payload }`. Frames carry no `event:` field, only `data:`.
19
+ */
20
+ import { type SessionStatus } from "../utils/session-store.js";
21
+ export interface OpencodeConfig {
22
+ baseUrl: string;
23
+ password?: string;
24
+ }
25
+ /**
26
+ * Reads bridge configuration from the environment. Returns null (discovery
27
+ * disabled) when no opencode endpoint is configured.
28
+ */
29
+ export declare function readOpencodeConfig(env?: NodeJS.ProcessEnv): OpencodeConfig | null;
30
+ export interface OpencodeMessageTarget {
31
+ /** opencode-native session id ("ses_…") — never the ARCS normalized id. */
32
+ runtimeSessionId: string;
33
+ /** Worktree the session belongs to, when known — scopes opencode's lookup. */
34
+ directory?: string;
35
+ }
36
+ /**
37
+ * Injects a user message into a live opencode session.
38
+ *
39
+ * Unlike the rest of this module (best-effort observability) this is a user
40
+ * mutation, so failures throw a typed DagError the web routes can surface.
41
+ *
42
+ * Verified against opencode 1.0.0 (`GET /doc`) plus a live server:
43
+ * - `POST /session/:sessionID/prompt_async` acks with 204 and runs the turn in
44
+ * the background. `POST /session/:sessionID/message` takes the same body but
45
+ * only responds once the assistant has finished its whole turn — minutes, for
46
+ * a browser request — so async delivery is the one that fits a web form.
47
+ * - the body requires `parts`; a text part is `{ type: "text", text }`.
48
+ * - `?directory=` is optional (an unscoped send still lands) but is passed when
49
+ * known so the lookup is unambiguous across worktrees.
50
+ */
51
+ export declare function sendOpencodeMessage(config: OpencodeConfig, target: OpencodeMessageTarget, text: string): Promise<void>;
52
+ export interface CreateOpencodeSessionInput {
53
+ /** Worktree the session runs in — required, see the directory note below. */
54
+ directory: string;
55
+ title?: string;
56
+ }
57
+ /** Only what ARCS needs to mirror the session; the SSE stream fills in the rest. */
58
+ export interface CreatedOpencodeSession {
59
+ runtimeSessionId: string;
60
+ title?: string;
61
+ }
62
+ /**
63
+ * Creates a live opencode session bound to a worktree.
64
+ *
65
+ * Verified against opencode 0.0.0-main-202607110203 (`GET /doc`, operationId
66
+ * `session.create`) plus a live server:
67
+ * - the route is `POST /session` — NOT `/api/session`. opencode serves its own
68
+ * web UI from the same port and answers every unknown path with a 200
69
+ * text/html SPA shell, so a wrong path looks like a success until the body is
70
+ * read. That is why the id is checked below rather than trusting `res.ok`.
71
+ * - `directory` is a *query* parameter and never a body field. Omitting it does
72
+ * not fail; opencode silently creates the session in its own working
73
+ * directory, so the caller must always pass the worktree explicitly.
74
+ * - `title` is the only body field ARCS sets; the response is a full session
75
+ * object (`{ id, slug, directory, title, time }`).
76
+ * - `DELETE /session/:sessionID` exists, so nothing created here is permanent.
77
+ */
78
+ export declare function createOpencodeSession(config: OpencodeConfig, input: CreateOpencodeSessionInput): Promise<CreatedOpencodeSession>;
79
+ interface OpencodeSessionInfo {
80
+ id?: string;
81
+ slug?: string;
82
+ title?: string;
83
+ directory?: string;
84
+ projectID?: string;
85
+ time?: {
86
+ created?: number;
87
+ updated?: number;
88
+ };
89
+ project?: {
90
+ worktree?: string;
91
+ };
92
+ }
93
+ interface OpencodeEvent {
94
+ type?: string;
95
+ properties?: {
96
+ sessionID?: string;
97
+ info?: OpencodeSessionInfo;
98
+ status?: {
99
+ type?: string;
100
+ };
101
+ };
102
+ }
103
+ /**
104
+ * Maps an opencode event type to the ARCS session status it implies.
105
+ * Returns null for events that carry no status transition (the record is
106
+ * refreshed but its status is left alone).
107
+ */
108
+ export declare function statusForOpencodeEvent(event: OpencodeEvent): SessionStatus | null;
109
+ export interface OpencodeDiscoveryState {
110
+ enabled: boolean;
111
+ connected: boolean;
112
+ baseUrl: string | null;
113
+ }
114
+ export declare function opencodeDiscoveryState(): OpencodeDiscoveryState;
115
+ /**
116
+ * Starts the discovery loop if an opencode endpoint is configured. Idempotent;
117
+ * returns false when discovery is disabled (no configuration present).
118
+ */
119
+ export declare function startOpencodeDiscovery(config?: OpencodeConfig | null): boolean;
120
+ /** Stops the discovery loop (test cleanup / server shutdown). */
121
+ export declare function stopOpencodeDiscovery(): Promise<void>;
122
+ export {};
123
+ //# sourceMappingURL=opencode-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode-client.d.ts","sourceRoot":"","sources":["../../src/web-server/opencode-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAOH,OAAO,EAEL,KAAK,aAAa,EAGnB,MAAM,2BAA2B,CAAC;AAanC,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,cAAc,GAAG,IAAI,CAc9F;AAYD,MAAM,WAAW,qBAAqB;IACpC,2EAA2E;IAC3E,gBAAgB,EAAE,MAAM,CAAC;IACzB,8EAA8E;IAC9E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,qBAAqB,EAC7B,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAiCf;AAMD,MAAM,WAAW,0BAA0B;IACzC,6EAA6E;IAC7E,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,oFAAoF;AACpF,MAAM,WAAW,sBAAsB;IACrC,gBAAgB,EAAE,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,cAAc,EACtB,KAAK,EAAE,0BAA0B,GAChC,OAAO,CAAC,sBAAsB,CAAC,CAyCjC;AAeD,UAAU,mBAAmB;IAC3B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9C,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACjC;AAED,UAAU,aAAa;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE;QACX,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,IAAI,CAAC,EAAE,mBAAmB,CAAC;QAC3B,MAAM,CAAC,EAAE;YAAE,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;KAC5B,CAAC;CACH;AAQD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,aAAa,GAAG,aAAa,GAAG,IAAI,CAuBjF;AA2DD,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,wBAAgB,sBAAsB,IAAI,sBAAsB,CAE/D;AAoQD;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,wBAAuB,GAAG,OAAO,CAW7E;AAED,iEAAiE;AACjE,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC,CAa3D"}
@@ -0,0 +1,514 @@
1
+ /**
2
+ * opencode session discovery bridge (Phase 1 — observability only).
3
+ *
4
+ * ARCS never spawns or manages an opencode server; it attaches to an already
5
+ * running `opencode serve` instance as a thin client, subscribes to the
6
+ * cross-instance `/global/event` SSE stream, and mirrors what it sees into the
7
+ * per-project session store. Everything here is best-effort: if opencode is
8
+ * not configured, not running, or speaks a different dialect, the ARCS web
9
+ * server keeps working and the sessions list is simply empty or stale.
10
+ *
11
+ * Verified against opencode 0.0.0-main-202607110203:
12
+ * - `opencode serve` defaults to port 0 (ephemeral), so a port/URL must be
13
+ * supplied explicitly via env — there is no safe default to guess.
14
+ * - `OPENCODE_SERVER_PASSWORD` is enforced as HTTP Basic auth with the literal
15
+ * username "opencode"; any other username is rejected with 401.
16
+ * - `/event` is scoped to one instance (`?directory=`); `/global/event` is the
17
+ * cross-directory stream and wraps each event as `{ directory, project,
18
+ * payload }`. Frames carry no `event:` field, only `data:`.
19
+ */
20
+ import { resolve } from "node:path";
21
+ import { readRootMeta } from "../utils/dag.js";
22
+ import { DagError } from "../utils/errors.js";
23
+ import { readJsonSafe } from "../utils/json.js";
24
+ import { getDataDir, getProjectDir } from "../utils/paths.js";
25
+ import { listSessions, updateSession, upsertSession, } from "../utils/session-store.js";
26
+ import { findBestMatch } from "../utils/workspace-match.js";
27
+ const DEFAULT_HOSTNAME = "127.0.0.1";
28
+ const BASIC_AUTH_USER = "opencode";
29
+ const RECONNECT_MIN_MS = 1_000;
30
+ const RECONNECT_MAX_MS = 30_000;
31
+ const SEND_TIMEOUT_MS = 10_000;
32
+ /**
33
+ * Reads bridge configuration from the environment. Returns null (discovery
34
+ * disabled) when no opencode endpoint is configured.
35
+ */
36
+ export function readOpencodeConfig(env = process.env) {
37
+ const password = env.OPENCODE_SERVER_PASSWORD?.trim() || undefined;
38
+ const explicitUrl = env.ARCS_OPENCODE_URL?.trim() || env.OPENCODE_URL?.trim();
39
+ if (explicitUrl) {
40
+ return { baseUrl: explicitUrl.replace(/\/+$/, ""), ...(password && { password }) };
41
+ }
42
+ const rawPort = env.OPENCODE_PORT?.trim();
43
+ if (!rawPort)
44
+ return null;
45
+ const port = Number.parseInt(rawPort, 10);
46
+ if (!Number.isInteger(port) || port <= 0 || port > 65535)
47
+ return null;
48
+ const hostname = env.OPENCODE_HOSTNAME?.trim() || DEFAULT_HOSTNAME;
49
+ return { baseUrl: `http://${hostname}:${port}`, ...(password && { password }) };
50
+ }
51
+ function requestHeaders(config) {
52
+ if (!config.password)
53
+ return {};
54
+ const token = Buffer.from(`${BASIC_AUTH_USER}:${config.password}`).toString("base64");
55
+ return { authorization: `Basic ${token}` };
56
+ }
57
+ /**
58
+ * Injects a user message into a live opencode session.
59
+ *
60
+ * Unlike the rest of this module (best-effort observability) this is a user
61
+ * mutation, so failures throw a typed DagError the web routes can surface.
62
+ *
63
+ * Verified against opencode 1.0.0 (`GET /doc`) plus a live server:
64
+ * - `POST /session/:sessionID/prompt_async` acks with 204 and runs the turn in
65
+ * the background. `POST /session/:sessionID/message` takes the same body but
66
+ * only responds once the assistant has finished its whole turn — minutes, for
67
+ * a browser request — so async delivery is the one that fits a web form.
68
+ * - the body requires `parts`; a text part is `{ type: "text", text }`.
69
+ * - `?directory=` is optional (an unscoped send still lands) but is passed when
70
+ * known so the lookup is unambiguous across worktrees.
71
+ */
72
+ export async function sendOpencodeMessage(config, target, text) {
73
+ // SHORTCUT: prompt_async only — upgrade to a `/session/:id/message` fallback
74
+ // when an opencode build that predates prompt_async has to be supported.
75
+ const query = target.directory ? `?directory=${encodeURIComponent(target.directory)}` : "";
76
+ const url = `${config.baseUrl}/session/${encodeURIComponent(target.runtimeSessionId)}/prompt_async${query}`;
77
+ let res;
78
+ try {
79
+ res = await fetch(url, {
80
+ method: "POST",
81
+ headers: { "content-type": "application/json", ...requestHeaders(config) },
82
+ body: JSON.stringify({ parts: [{ type: "text", text }] }),
83
+ signal: AbortSignal.timeout(SEND_TIMEOUT_MS),
84
+ });
85
+ }
86
+ catch (err) {
87
+ throw new DagError("OPENCODE_UNREACHABLE", `Could not reach opencode at ${config.baseUrl}: ${String(err)}`);
88
+ }
89
+ if (res.status === 404) {
90
+ throw new DagError("OPENCODE_SESSION_NOT_FOUND", `opencode does not know session "${target.runtimeSessionId}" — it may have ended.`);
91
+ }
92
+ if (!res.ok) {
93
+ throw new DagError("OPENCODE_REQUEST_FAILED", `opencode rejected the message (${res.status})${await errorDetail(res)}`);
94
+ }
95
+ }
96
+ /**
97
+ * Creates a live opencode session bound to a worktree.
98
+ *
99
+ * Verified against opencode 0.0.0-main-202607110203 (`GET /doc`, operationId
100
+ * `session.create`) plus a live server:
101
+ * - the route is `POST /session` — NOT `/api/session`. opencode serves its own
102
+ * web UI from the same port and answers every unknown path with a 200
103
+ * text/html SPA shell, so a wrong path looks like a success until the body is
104
+ * read. That is why the id is checked below rather than trusting `res.ok`.
105
+ * - `directory` is a *query* parameter and never a body field. Omitting it does
106
+ * not fail; opencode silently creates the session in its own working
107
+ * directory, so the caller must always pass the worktree explicitly.
108
+ * - `title` is the only body field ARCS sets; the response is a full session
109
+ * object (`{ id, slug, directory, title, time }`).
110
+ * - `DELETE /session/:sessionID` exists, so nothing created here is permanent.
111
+ */
112
+ export async function createOpencodeSession(config, input) {
113
+ const url = `${config.baseUrl}/session?directory=${encodeURIComponent(input.directory)}`;
114
+ let res;
115
+ try {
116
+ res = await fetch(url, {
117
+ method: "POST",
118
+ headers: { "content-type": "application/json", ...requestHeaders(config) },
119
+ body: JSON.stringify(input.title ? { title: input.title } : {}),
120
+ signal: AbortSignal.timeout(SEND_TIMEOUT_MS),
121
+ });
122
+ }
123
+ catch (err) {
124
+ throw new DagError("OPENCODE_UNREACHABLE", `Could not reach opencode at ${config.baseUrl}: ${String(err)}`);
125
+ }
126
+ if (!res.ok) {
127
+ throw new DagError("OPENCODE_REQUEST_FAILED", `opencode refused to create a session (${res.status})${await errorDetail(res)}`);
128
+ }
129
+ let body;
130
+ try {
131
+ body = await res.json();
132
+ }
133
+ catch {
134
+ body = null;
135
+ }
136
+ const info = body;
137
+ if (!info?.id) {
138
+ throw new DagError("OPENCODE_REQUEST_FAILED", `opencode answered ${config.baseUrl}/session with something other than a session — ` +
139
+ "the create-session endpoint may have moved in this opencode build.");
140
+ }
141
+ return { runtimeSessionId: info.id, ...(info.title && { title: info.title }) };
142
+ }
143
+ async function errorDetail(res) {
144
+ try {
145
+ const body = (await res.text()).trim();
146
+ return body ? `: ${body.slice(0, 200)}` : "";
147
+ }
148
+ catch {
149
+ return "";
150
+ }
151
+ }
152
+ /**
153
+ * Maps an opencode event type to the ARCS session status it implies.
154
+ * Returns null for events that carry no status transition (the record is
155
+ * refreshed but its status is left alone).
156
+ */
157
+ export function statusForOpencodeEvent(event) {
158
+ switch (event.type) {
159
+ case "session.created":
160
+ return "active";
161
+ case "session.idle":
162
+ return "idle";
163
+ case "session.error":
164
+ return "failed";
165
+ case "session.deleted":
166
+ return "disconnected";
167
+ case "session.status":
168
+ switch (event.properties?.status?.type) {
169
+ case "idle":
170
+ return "idle";
171
+ case "busy":
172
+ case "retry":
173
+ return "active";
174
+ default:
175
+ return null;
176
+ }
177
+ default:
178
+ return null;
179
+ }
180
+ }
181
+ function isoFromEpochMs(value) {
182
+ if (typeof value !== "number" || !Number.isFinite(value) || value <= 0)
183
+ return undefined;
184
+ return new Date(value).toISOString();
185
+ }
186
+ // ---------------------------------------------------------------------------
187
+ // Project resolution
188
+ // ---------------------------------------------------------------------------
189
+ async function loadWorkspaceProjects() {
190
+ const dataDir = getDataDir();
191
+ const projects = [];
192
+ try {
193
+ const rootMeta = await readRootMeta(dataDir);
194
+ for (const node of rootMeta.projects) {
195
+ const meta = await readJsonSafe(resolve(dataDir, "projects", node.id, "meta.json"));
196
+ const paths = Array.isArray(meta?.workspacePaths) ? meta.workspacePaths : [];
197
+ if (paths.length > 0)
198
+ projects.push({ slug: node.id, workspacePaths: paths });
199
+ }
200
+ }
201
+ catch {
202
+ // Unreadable DAG root — treat as "no projects" and retry on the next event.
203
+ }
204
+ return projects;
205
+ }
206
+ // SHORTCUT: directory→slug resolution re-reads the DAG on every cache miss and
207
+ // caches positive hits for the lifetime of the connection; upgrade to a
208
+ // watcher-invalidated cache when workspace paths start changing mid-session.
209
+ const directorySlugCache = new Map();
210
+ async function resolveSlugForDirectory(directory) {
211
+ if (!directory)
212
+ return null;
213
+ const cached = directorySlugCache.get(directory);
214
+ if (cached !== undefined)
215
+ return cached;
216
+ const match = findBestMatch(directory, await loadWorkspaceProjects());
217
+ const slug = match.kind === "match" ? match.slug : null;
218
+ directorySlugCache.set(directory, slug);
219
+ return slug;
220
+ }
221
+ // ---------------------------------------------------------------------------
222
+ // Bridge state
223
+ // ---------------------------------------------------------------------------
224
+ /** sessionID -> project slug, so id-only events (idle, error) can be routed. */
225
+ const sessionSlugs = new Map();
226
+ let running = false;
227
+ let connected = false;
228
+ let controller = null;
229
+ let activeConfig = null;
230
+ let loop = null;
231
+ let warnedUnreachable = false;
232
+ export function opencodeDiscoveryState() {
233
+ return { enabled: running, connected, baseUrl: activeConfig?.baseUrl ?? null };
234
+ }
235
+ // ---------------------------------------------------------------------------
236
+ // Session mirroring
237
+ // ---------------------------------------------------------------------------
238
+ async function recordSession(slug, info, status) {
239
+ const runtimeSessionId = info.id;
240
+ if (!runtimeSessionId)
241
+ return;
242
+ const metadata = {};
243
+ if (info.title)
244
+ metadata.title = info.title;
245
+ if (info.slug)
246
+ metadata.sessionSlug = info.slug;
247
+ if (info.directory)
248
+ metadata.directory = info.directory;
249
+ if (info.projectID)
250
+ metadata.opencodeProjectId = info.projectID;
251
+ await upsertSession(getProjectDir(slug), {
252
+ runtimeType: "opencode",
253
+ runtimeSessionId,
254
+ ...(status && { status }),
255
+ ...(isoFromEpochMs(info.time?.created) && {
256
+ startedAt: isoFromEpochMs(info.time?.created),
257
+ }),
258
+ ...(isoFromEpochMs(info.time?.updated) && {
259
+ lastMessageAt: isoFromEpochMs(info.time?.updated),
260
+ }),
261
+ ...(Object.keys(metadata).length > 0 && { metadata }),
262
+ });
263
+ sessionSlugs.set(runtimeSessionId, slug);
264
+ }
265
+ async function applyStatus(sessionId, status) {
266
+ const slug = sessionSlugs.get(sessionId);
267
+ if (!slug)
268
+ return;
269
+ await updateSession(getProjectDir(slug), { id: sessionId, status });
270
+ }
271
+ async function handleEnvelope(envelope) {
272
+ const event = envelope.payload;
273
+ if (!event?.type)
274
+ return;
275
+ if (event.type === "server.instance.disposed" || event.type === "global.disposed") {
276
+ await markAllDisconnected();
277
+ return;
278
+ }
279
+ if (!event.type.startsWith("session."))
280
+ return;
281
+ const info = event.properties?.info;
282
+ const status = statusForOpencodeEvent(event);
283
+ if (info?.id) {
284
+ const directory = info.directory ?? info.project?.worktree ?? envelope.directory;
285
+ const slug = await resolveSlugForDirectory(directory);
286
+ if (!slug)
287
+ return;
288
+ await recordSession(slug, info, status);
289
+ return;
290
+ }
291
+ const sessionId = event.properties?.sessionID;
292
+ if (sessionId && status)
293
+ await applyStatus(sessionId, status);
294
+ }
295
+ /** Marks every opencode session ARCS currently tracks as disconnected. */
296
+ async function markAllDisconnected() {
297
+ const entries = [...sessionSlugs.entries()];
298
+ sessionSlugs.clear();
299
+ for (const [sessionId, slug] of entries) {
300
+ try {
301
+ await updateSession(getProjectDir(slug), { id: sessionId, status: "disconnected" });
302
+ }
303
+ catch {
304
+ // Record already gone — nothing to reconcile.
305
+ }
306
+ }
307
+ }
308
+ // ---------------------------------------------------------------------------
309
+ // Backfill + reconcile
310
+ // ---------------------------------------------------------------------------
311
+ /**
312
+ * On every (re)connect, take a full snapshot of opencode's sessions and make
313
+ * the ARCS index match it: known sessions are upserted as "idle" (live, no
314
+ * activity observed yet) and sessions opencode no longer knows about are
315
+ * marked "disconnected". Live events correct the status within seconds.
316
+ */
317
+ async function backfill(config) {
318
+ let sessions = [];
319
+ try {
320
+ const res = await fetch(`${config.baseUrl}/experimental/session`, {
321
+ headers: requestHeaders(config),
322
+ signal: controller?.signal,
323
+ });
324
+ if (!res.ok)
325
+ return;
326
+ const body = await res.json();
327
+ if (!Array.isArray(body))
328
+ return;
329
+ sessions = body;
330
+ }
331
+ catch {
332
+ // Endpoint missing or unreachable — live events alone still populate.
333
+ return;
334
+ }
335
+ const seen = new Set();
336
+ for (const info of sessions) {
337
+ const slug = await resolveSlugForDirectory(info.directory ?? info.project?.worktree);
338
+ if (!slug || !info.id)
339
+ continue;
340
+ try {
341
+ await recordSession(slug, info, "idle");
342
+ seen.add(info.id);
343
+ }
344
+ catch {
345
+ // A single malformed session must not abort the whole snapshot.
346
+ }
347
+ }
348
+ await reconcileMissing(seen);
349
+ }
350
+ async function reconcileMissing(seen) {
351
+ const dataDir = getDataDir();
352
+ let slugs = [];
353
+ try {
354
+ slugs = (await readRootMeta(dataDir)).projects.map((p) => p.id);
355
+ }
356
+ catch {
357
+ return;
358
+ }
359
+ for (const slug of slugs) {
360
+ const projectDir = getProjectDir(slug);
361
+ let stale = [];
362
+ try {
363
+ stale = (await listSessions(projectDir, { runtimeType: "opencode" }))
364
+ .filter((s) => s.status !== "disconnected" && !seen.has(s.runtimeSessionId))
365
+ .map((s) => s.normalizedId);
366
+ }
367
+ catch {
368
+ continue;
369
+ }
370
+ for (const id of stale) {
371
+ try {
372
+ await updateSession(projectDir, { id, status: "disconnected" });
373
+ }
374
+ catch {
375
+ // Concurrently removed — nothing to do.
376
+ }
377
+ }
378
+ }
379
+ }
380
+ // ---------------------------------------------------------------------------
381
+ // SSE stream
382
+ // ---------------------------------------------------------------------------
383
+ /** Consumes one `/global/event` stream until it ends or is aborted. */
384
+ async function consumeStream(config) {
385
+ const res = await fetch(`${config.baseUrl}/global/event`, {
386
+ headers: { accept: "text/event-stream", ...requestHeaders(config) },
387
+ signal: controller?.signal,
388
+ });
389
+ if (!res.ok || !res.body) {
390
+ throw new Error(`opencode /global/event responded ${res.status}`);
391
+ }
392
+ connected = true;
393
+ warnedUnreachable = false;
394
+ await backfill(config);
395
+ const reader = res.body.getReader();
396
+ const decoder = new TextDecoder();
397
+ let buffer = "";
398
+ let streaming = true;
399
+ while (streaming) {
400
+ const { done, value } = await reader.read();
401
+ if (done) {
402
+ streaming = false;
403
+ break;
404
+ }
405
+ buffer += decoder.decode(value, { stream: true });
406
+ let boundary = buffer.indexOf("\n\n");
407
+ while (boundary !== -1) {
408
+ const frame = buffer.slice(0, boundary);
409
+ buffer = buffer.slice(boundary + 2);
410
+ await handleFrame(frame);
411
+ boundary = buffer.indexOf("\n\n");
412
+ }
413
+ }
414
+ }
415
+ async function handleFrame(frame) {
416
+ const data = frame
417
+ .split("\n")
418
+ .filter((line) => line.startsWith("data:"))
419
+ .map((line) => line.slice(5).trimStart())
420
+ .join("\n");
421
+ if (!data)
422
+ return;
423
+ let envelope;
424
+ try {
425
+ envelope = JSON.parse(data);
426
+ }
427
+ catch {
428
+ return;
429
+ }
430
+ try {
431
+ await handleEnvelope(envelope);
432
+ }
433
+ catch (err) {
434
+ console.warn("[arcs-web] opencode session sync failed", err);
435
+ }
436
+ }
437
+ function sleep(ms, signal) {
438
+ return new Promise((resolvePromise) => {
439
+ const onAbort = () => {
440
+ clearTimeout(timer);
441
+ resolvePromise();
442
+ };
443
+ const timer = setTimeout(() => {
444
+ signal.removeEventListener("abort", onAbort);
445
+ resolvePromise();
446
+ }, ms);
447
+ signal.addEventListener("abort", onAbort, { once: true });
448
+ });
449
+ }
450
+ async function runDiscovery(config) {
451
+ let delay = RECONNECT_MIN_MS;
452
+ while (running) {
453
+ try {
454
+ await consumeStream(config);
455
+ delay = RECONNECT_MIN_MS;
456
+ }
457
+ catch (err) {
458
+ if (!running || (err instanceof Error && err.name === "AbortError"))
459
+ break;
460
+ if (!warnedUnreachable) {
461
+ warnedUnreachable = true;
462
+ console.warn(`[arcs-web] opencode session discovery could not reach ${config.baseUrl} — ` +
463
+ `sessions will not update until it is available (${String(err)})`);
464
+ }
465
+ delay = Math.min(RECONNECT_MAX_MS, delay * 2);
466
+ }
467
+ connected = false;
468
+ directorySlugCache.clear();
469
+ if (!running)
470
+ break;
471
+ await markAllDisconnected();
472
+ if (!running || !controller)
473
+ break;
474
+ await sleep(delay, controller.signal);
475
+ }
476
+ connected = false;
477
+ }
478
+ // ---------------------------------------------------------------------------
479
+ // Lifecycle
480
+ // ---------------------------------------------------------------------------
481
+ /**
482
+ * Starts the discovery loop if an opencode endpoint is configured. Idempotent;
483
+ * returns false when discovery is disabled (no configuration present).
484
+ */
485
+ export function startOpencodeDiscovery(config = readOpencodeConfig()) {
486
+ if (running)
487
+ return true;
488
+ if (!config)
489
+ return false;
490
+ running = true;
491
+ activeConfig = config;
492
+ controller = new AbortController();
493
+ loop = runDiscovery(config).catch((err) => {
494
+ console.warn("[arcs-web] opencode session discovery stopped unexpectedly", err);
495
+ });
496
+ return true;
497
+ }
498
+ /** Stops the discovery loop (test cleanup / server shutdown). */
499
+ export async function stopOpencodeDiscovery() {
500
+ if (!running)
501
+ return;
502
+ running = false;
503
+ controller?.abort();
504
+ const pending = loop;
505
+ controller = null;
506
+ activeConfig = null;
507
+ loop = null;
508
+ connected = false;
509
+ warnedUnreachable = false;
510
+ sessionSlugs.clear();
511
+ directorySlugCache.clear();
512
+ await pending?.catch(() => { });
513
+ }
514
+ //# sourceMappingURL=opencode-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode-client.js","sourceRoot":"","sources":["../../src/web-server/opencode-client.ts"],"names":[],"mappings":"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"}