airaknit 1.1.2-rc.9

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 (440) hide show
  1. package/LICENSE +84 -0
  2. package/README.md +202 -0
  3. package/bin/airaknit +9 -0
  4. package/bin/airaknit-project +14 -0
  5. package/bin/kanna +9 -0
  6. package/dist/client/assets/CompactSummaryMessage-Yw0BDWEJ.js +1 -0
  7. package/dist/client/assets/ExitPlanModeMessage-DIdkQ4uF.js +1 -0
  8. package/dist/client/assets/LocalFilePreviewDialog-DQx2eiCc.js +3 -0
  9. package/dist/client/assets/LocalProjectsSection-C4xlWkgS.js +1 -0
  10. package/dist/client/assets/TextMessage-B5G39DEJ.js +1 -0
  11. package/dist/client/assets/UserMessage-CIkWk-0L.js +1 -0
  12. package/dist/client/assets/_basePickBy-CVrAFfnZ.js +1 -0
  13. package/dist/client/assets/_baseUniq-JL-aaF4P.js +1 -0
  14. package/dist/client/assets/arc-B07zg7ol.js +1 -0
  15. package/dist/client/assets/architecture-YZFGNWBL-PSLVJL3p.js +1 -0
  16. package/dist/client/assets/architectureDiagram-Q4EWVU46-DfWIF1G_.js +36 -0
  17. package/dist/client/assets/array-BGFCBI0e.js +1 -0
  18. package/dist/client/assets/blockDiagram-DXYQGD6D-CzwIeo_B.js +132 -0
  19. package/dist/client/assets/bundle-mjs-BDE2gWbQ.js +1 -0
  20. package/dist/client/assets/button-DO50qOGv.js +1 -0
  21. package/dist/client/assets/c4Diagram-AHTNJAMY-CR8DCQRE.js +10 -0
  22. package/dist/client/assets/channel-Dj-UUfaF.js +1 -0
  23. package/dist/client/assets/chunk-2KRD3SAO-dznP-cn8.js +1 -0
  24. package/dist/client/assets/chunk-336JU56O-Dqss5Vu6.js +2 -0
  25. package/dist/client/assets/chunk-426QAEUC-CEKis_0_.js +1 -0
  26. package/dist/client/assets/chunk-4BX2VUAB-BYOv0Gm1.js +1 -0
  27. package/dist/client/assets/chunk-4TB4RGXK-BxzubH5S.js +206 -0
  28. package/dist/client/assets/chunk-55IACEB6-BSlTj03a.js +1 -0
  29. package/dist/client/assets/chunk-5FUZZQ4R-9Au93Bi1.js +62 -0
  30. package/dist/client/assets/chunk-5PVQY5BW-BhksHFEZ.js +2 -0
  31. package/dist/client/assets/chunk-67CJDMHE-BFwhz-8t.js +1 -0
  32. package/dist/client/assets/chunk-7N4EOEYR-BDUPds87.js +1 -0
  33. package/dist/client/assets/chunk-AA7GKIK3-CEWTdyXO.js +1 -0
  34. package/dist/client/assets/chunk-BO2N2NFS-D0LvxnhU.js +103 -0
  35. package/dist/client/assets/chunk-BSJP7CBP-BNJnK6sq.js +1 -0
  36. package/dist/client/assets/chunk-Bj-mKKzh.js +1 -0
  37. package/dist/client/assets/chunk-CIAEETIT-CYhfoCeN.js +1 -0
  38. package/dist/client/assets/chunk-EDXVE4YY-C5ovJLc0.js +1 -0
  39. package/dist/client/assets/chunk-ENJZ2VHE-HOhYaeGr.js +10 -0
  40. package/dist/client/assets/chunk-FMBD7UC4-BLCiKcAQ.js +15 -0
  41. package/dist/client/assets/chunk-FOC6F5B3-B6GtY2ek.js +1 -0
  42. package/dist/client/assets/chunk-ICPOFSXX-DPoIZoC5.js +122 -0
  43. package/dist/client/assets/chunk-K5T4RW27-BsKN63rv.js +94 -0
  44. package/dist/client/assets/chunk-KGLVRYIC-BUGn9uuY.js +1 -0
  45. package/dist/client/assets/chunk-LIHQZDEY-DhaZyo03.js +1 -0
  46. package/dist/client/assets/chunk-ORNJ4GCN-DlpeeJyi.js +1 -0
  47. package/dist/client/assets/chunk-OYMX7WX6-Dc9q7aYA.js +231 -0
  48. package/dist/client/assets/chunk-QZHKN3VN-BEdrPoSb.js +1 -0
  49. package/dist/client/assets/chunk-U2HBQHQK-CIB3Bjjd.js +70 -0
  50. package/dist/client/assets/chunk-X2U36JSP-CtB-o8Yp.js +1 -0
  51. package/dist/client/assets/chunk-XPW4576I-C6iHhX_8.js +32 -0
  52. package/dist/client/assets/chunk-YZCP3GAM-CTmKr6ZH.js +1 -0
  53. package/dist/client/assets/chunk-ZZ45TVLE-BgU8A2RF.js +1 -0
  54. package/dist/client/assets/classDiagram-6PBFFD2Q-Bqk5e679.js +1 -0
  55. package/dist/client/assets/classDiagram-v2-HSJHXN6E-6pSaZOkC.js +1 -0
  56. package/dist/client/assets/client-BrKWI4CM.js +1 -0
  57. package/dist/client/assets/client-CGgNRU9w.js +1 -0
  58. package/dist/client/assets/client-DMSLRzg9.js +6 -0
  59. package/dist/client/assets/clone-DWcL7whJ.js +1 -0
  60. package/dist/client/assets/cose-bilkent-S5V4N54A-CrV5wsV_.js +1 -0
  61. package/dist/client/assets/cytoscape.esm--aLzKuep.js +321 -0
  62. package/dist/client/assets/dagre-CuRxWcrj.js +1 -0
  63. package/dist/client/assets/dagre-KV5264BT-BIDiVnkA.js +4 -0
  64. package/dist/client/assets/defaultLocale-CRZydyG6.js +1 -0
  65. package/dist/client/assets/diagram-5BDNPKRD-i1kjKRCB.js +10 -0
  66. package/dist/client/assets/diagram-G4DWMVQ6-9ZSLuhbl.js +24 -0
  67. package/dist/client/assets/diagram-MMDJMWI5-B4_CUjgv.js +43 -0
  68. package/dist/client/assets/diagram-TYMM5635-Ct5eTGS8.js +24 -0
  69. package/dist/client/assets/dist-CuB4kiSK.js +1 -0
  70. package/dist/client/assets/erDiagram-SMLLAGMA-Cy38ercc.js +85 -0
  71. package/dist/client/assets/flowDiagram-DWJPFMVM-CZKuYl0V.js +162 -0
  72. package/dist/client/assets/ganttDiagram-T4ZO3ILL-DLPjCh7a.js +292 -0
  73. package/dist/client/assets/gitGraph-7Q5UKJZL-DqbrtEp9.js +1 -0
  74. package/dist/client/assets/gitGraphDiagram-UUTBAWPF-BoRBkDhQ.js +106 -0
  75. package/dist/client/assets/graphlib-BcQ6qlQh.js +1 -0
  76. package/dist/client/assets/highlighted-body-OFNGDK62-BEpBVDTX.js +1 -0
  77. package/dist/client/assets/index-CetCiuqP.js +105 -0
  78. package/dist/client/assets/index-N29Mip7A.css +1 -0
  79. package/dist/client/assets/info-OMHHGYJF-D98DRBJX.js +1 -0
  80. package/dist/client/assets/infoDiagram-42DDH7IO-BAcdTWbt.js +2 -0
  81. package/dist/client/assets/init-B8gtcn7T.js +1 -0
  82. package/dist/client/assets/isArrayLikeObject-D8SJFmkN.js +1 -0
  83. package/dist/client/assets/isEmpty-BF3YX5Jk.js +1 -0
  84. package/dist/client/assets/ishikawaDiagram-UXIWVN3A-Ynu2VKdC.js +70 -0
  85. package/dist/client/assets/journeyDiagram-VCZTEJTY-BjfhQaN3.js +139 -0
  86. package/dist/client/assets/jsx-runtime-CyI9ICYU.js +1 -0
  87. package/dist/client/assets/kanban-definition-6JOO6SKY-JLXH9zUJ.js +89 -0
  88. package/dist/client/assets/katex-B94qP8b6.js +265 -0
  89. package/dist/client/assets/lib--QVjyxmL.js +29 -0
  90. package/dist/client/assets/lib-B6rgJiZ9.js +1 -0
  91. package/dist/client/assets/line-DCrYfLBn.js +1 -0
  92. package/dist/client/assets/linear-_4upLmeo.js +1 -0
  93. package/dist/client/assets/mermaid-GHXKKRXX-rwJHYUmW.js +1 -0
  94. package/dist/client/assets/mermaid-parser.core-KZinfW8o.js +4 -0
  95. package/dist/client/assets/mermaid.core-QqY9gSNe.js +11 -0
  96. package/dist/client/assets/mindmap-definition-QFDTVHPH-TWgHDAzp.js +96 -0
  97. package/dist/client/assets/ordinal-CCj7PWgZ.js +1 -0
  98. package/dist/client/assets/packet-4T2RLAQJ-DEvfkn3F.js +1 -0
  99. package/dist/client/assets/path-DZF-JdEe.js +1 -0
  100. package/dist/client/assets/pie-ZZUOXDRM-72e6WVjb.js +1 -0
  101. package/dist/client/assets/pieDiagram-DEJITSTG-Cl8PCsoj.js +30 -0
  102. package/dist/client/assets/preload-helper-rov5CBGT.js +1 -0
  103. package/dist/client/assets/pty-client-DZ27IS00.js +1 -0
  104. package/dist/client/assets/ptyInstancesStore-D9ag7SYd.js +1 -0
  105. package/dist/client/assets/quadrantDiagram-34T5L4WZ-CHyVGp9E.js +7 -0
  106. package/dist/client/assets/radar-PYXPWWZC-Cp7xd_EY.js +1 -0
  107. package/dist/client/assets/react-CClhXMB2.js +1 -0
  108. package/dist/client/assets/react-Dd6D81m0.js +1 -0
  109. package/dist/client/assets/react-dom--G6_6fQ_.js +1 -0
  110. package/dist/client/assets/requirementDiagram-MS252O5E-DaanG2iM.js +84 -0
  111. package/dist/client/assets/rough.esm-BsmKo2S5.js +1 -0
  112. package/dist/client/assets/sankeyDiagram-XADWPNL6-B_fhLY36.js +10 -0
  113. package/dist/client/assets/sequenceDiagram-FGHM5R23-C5FNrveI.js +157 -0
  114. package/dist/client/assets/src-DeTlMJAU.js +1 -0
  115. package/dist/client/assets/stateDiagram-FHFEXIEX-nTTcdjjQ.js +1 -0
  116. package/dist/client/assets/stateDiagram-v2-QKLJ7IA2-Dw0632j_.js +1 -0
  117. package/dist/client/assets/timeline-definition-GMOUNBTQ-DkQV1yP8.js +120 -0
  118. package/dist/client/assets/treeView-SZITEDCU-ZLIgC7_K.js +1 -0
  119. package/dist/client/assets/treemap-W4RFUUIX-BqaMbB6N.js +1 -0
  120. package/dist/client/assets/uiIdentityOverlay-Ba7GNj7m.js +1 -0
  121. package/dist/client/assets/vennDiagram-DHZGUBPP-DbZ2xgs6.js +34 -0
  122. package/dist/client/assets/wardley-RL74JXVD-DXQS8zf4.js +1 -0
  123. package/dist/client/assets/wardleyDiagram-NUSXRM2D-BzCJ6MAu.js +20 -0
  124. package/dist/client/assets/xychartDiagram-5P7HB3ND-BSlFecop.js +7 -0
  125. package/dist/client/favicon.png +0 -0
  126. package/dist/client/favicon.svg +15 -0
  127. package/dist/client/fonts/body-medium.woff2 +0 -0
  128. package/dist/client/fonts/body-regular-italic.woff2 +0 -0
  129. package/dist/client/fonts/body-regular.woff2 +0 -0
  130. package/dist/client/fonts/body-semibold.woff2 +0 -0
  131. package/dist/client/index.html +31 -0
  132. package/dist/client/manifest.webmanifest +12 -0
  133. package/dist/client/sw.js +32 -0
  134. package/package.json +122 -0
  135. package/src/nats/auth-callout/callout-config.test.ts +93 -0
  136. package/src/nats/auth-callout/callout-config.ts +109 -0
  137. package/src/nats/auth-callout/callout.integration.test.ts +332 -0
  138. package/src/nats/auth-callout/keys.ts +103 -0
  139. package/src/nats/auth-callout/responder.ts +241 -0
  140. package/src/nats/auth-callout/scope-policy.test.ts +159 -0
  141. package/src/nats/auth-callout/scope-policy.ts +210 -0
  142. package/src/nats/auth-callout/token.test.ts +163 -0
  143. package/src/nats/auth-callout/token.ts +157 -0
  144. package/src/nats/nats-daemon-callout.ts +194 -0
  145. package/src/nats/nats-daemon.test.ts +77 -0
  146. package/src/nats/nats-daemon.ts +50 -0
  147. package/src/nats/nats-token.test.ts +61 -0
  148. package/src/nats/nats-token.ts +59 -0
  149. package/src/runner/coordination-mcp-integration.test.ts +134 -0
  150. package/src/runner/nats-coordination-client.test.ts +49 -0
  151. package/src/runner/nats-coordination-client.ts +94 -0
  152. package/src/runner/runner-agent.test.ts +469 -0
  153. package/src/runner/runner-agent.ts +453 -0
  154. package/src/runner/runner-credential.test.ts +93 -0
  155. package/src/runner/runner-credential.ts +82 -0
  156. package/src/runner/runner-nats.test.ts +495 -0
  157. package/src/runner/runner-nats.ts +323 -0
  158. package/src/runner/runner-pair.test.ts +107 -0
  159. package/src/runner/runner-pair.ts +81 -0
  160. package/src/runner/runner.test.ts +135 -0
  161. package/src/runner/runner.ts +212 -0
  162. package/src/runner/turn-factories.test.ts +97 -0
  163. package/src/runner/turn-factories.ts +475 -0
  164. package/src/server/agent-config-journey.test.ts +106 -0
  165. package/src/server/agent.ts +8 -0
  166. package/src/server/auto-continue/auth-error-detector.ts +66 -0
  167. package/src/server/auto-continue/limit-detector.ts +194 -0
  168. package/src/server/bm25.test.ts +92 -0
  169. package/src/server/bm25.ts +101 -0
  170. package/src/server/chat-events-jetstream.test.ts +135 -0
  171. package/src/server/claude-harness.ts +360 -0
  172. package/src/server/claude-pty/agent-normalizers.ts +309 -0
  173. package/src/server/claude-pty/auth.test.ts +38 -0
  174. package/src/server/claude-pty/auth.ts +32 -0
  175. package/src/server/claude-pty/claude-session-registry.adapter.ts +81 -0
  176. package/src/server/claude-pty/claude-session-registry.test.ts +149 -0
  177. package/src/server/claude-pty/driver.test.ts +902 -0
  178. package/src/server/claude-pty/driver.ts +807 -0
  179. package/src/server/claude-pty/jsonl-path.adapter.ts +57 -0
  180. package/src/server/claude-pty/jsonl-path.test.ts +114 -0
  181. package/src/server/claude-pty/jsonl-to-event.test.ts +241 -0
  182. package/src/server/claude-pty/jsonl-to-event.ts +174 -0
  183. package/src/server/claude-pty/output-ring.test.ts +35 -0
  184. package/src/server/claude-pty/output-ring.ts +25 -0
  185. package/src/server/claude-pty/parity-matrix.test.ts +227 -0
  186. package/src/server/claude-pty/pid-registry.adapter.ts +135 -0
  187. package/src/server/claude-pty/pid-registry.test.ts +122 -0
  188. package/src/server/claude-pty/preflight/binary-fingerprint.adapter.ts +20 -0
  189. package/src/server/claude-pty/preflight/binary-fingerprint.test.ts +32 -0
  190. package/src/server/claude-pty/pty-instance-registry.test.ts +177 -0
  191. package/src/server/claude-pty/pty-instance-registry.ts +166 -0
  192. package/src/server/claude-pty/pty-memory-sampler.adapter.test.ts +103 -0
  193. package/src/server/claude-pty/pty-memory-sampler.adapter.ts +85 -0
  194. package/src/server/claude-pty/pty-process.adapter.ts +66 -0
  195. package/src/server/claude-pty/pty-process.test.ts +49 -0
  196. package/src/server/claude-pty/resolve-binary.adapter.ts +106 -0
  197. package/src/server/claude-pty/resolve-binary.test.ts +118 -0
  198. package/src/server/claude-pty/runtime-dir.adapter.ts +19 -0
  199. package/src/server/claude-pty/settings-writer.adapter.ts +27 -0
  200. package/src/server/claude-pty/settings-writer.test.ts +22 -0
  201. package/src/server/claude-pty/smoke-test-io.adapter.ts +28 -0
  202. package/src/server/claude-pty/smoke-test.test.ts +191 -0
  203. package/src/server/claude-pty/smoke-test.ts +185 -0
  204. package/src/server/claude-pty/subagent-orchestrator.ts +887 -0
  205. package/src/server/claude-pty/tool-callback.ts +274 -0
  206. package/src/server/claude-pty/tui-control.test.ts +272 -0
  207. package/src/server/claude-pty/tui-control.ts +182 -0
  208. package/src/server/claude-pty/tui-source.adapter.test.ts +360 -0
  209. package/src/server/claude-pty/tui-source.adapter.ts +343 -0
  210. package/src/server/claude-pty/tunnel-gateway.ts +12 -0
  211. package/src/server/claude-pty-mcp/canonical-args.ts +15 -0
  212. package/src/server/claude-pty-mcp/fs-stat.adapter.ts +8 -0
  213. package/src/server/claude-pty-mcp/history-primer.ts +90 -0
  214. package/src/server/claude-pty-mcp/http-server.adapter.ts +33 -0
  215. package/src/server/claude-pty-mcp/mcp-http.ts +177 -0
  216. package/src/server/claude-pty-mcp/mcp.ts +412 -0
  217. package/src/server/claude-pty-mcp/mention-parser.ts +25 -0
  218. package/src/server/claude-pty-mcp/paths.ts +24 -0
  219. package/src/server/claude-pty-mcp/permission-gate.ts +243 -0
  220. package/src/server/claude-pty-mcp/terminal-pid-registry.adapter.ts +107 -0
  221. package/src/server/claude-pty-mcp/tools/ask-user-question.test.ts +119 -0
  222. package/src/server/claude-pty-mcp/tools/ask-user-question.ts +61 -0
  223. package/src/server/claude-pty-mcp/tools/bash.adapter.ts +76 -0
  224. package/src/server/claude-pty-mcp/tools/bash.test.ts +56 -0
  225. package/src/server/claude-pty-mcp/tools/delegate-subagent.test.ts +155 -0
  226. package/src/server/claude-pty-mcp/tools/delegate-subagent.ts +111 -0
  227. package/src/server/claude-pty-mcp/tools/edit.adapter.ts +95 -0
  228. package/src/server/claude-pty-mcp/tools/edit.test.ts +93 -0
  229. package/src/server/claude-pty-mcp/tools/exit-plan-mode.test.ts +61 -0
  230. package/src/server/claude-pty-mcp/tools/exit-plan-mode.ts +50 -0
  231. package/src/server/claude-pty-mcp/tools/glob.adapter.ts +86 -0
  232. package/src/server/claude-pty-mcp/tools/glob.test.ts +61 -0
  233. package/src/server/claude-pty-mcp/tools/grep.adapter.ts +126 -0
  234. package/src/server/claude-pty-mcp/tools/grep.test.ts +62 -0
  235. package/src/server/claude-pty-mcp/tools/read.adapter.ts +58 -0
  236. package/src/server/claude-pty-mcp/tools/read.test.ts +62 -0
  237. package/src/server/claude-pty-mcp/tools/tool-callback-shim.ts +42 -0
  238. package/src/server/claude-pty-mcp/tools/webfetch.test.ts +81 -0
  239. package/src/server/claude-pty-mcp/tools/webfetch.ts +82 -0
  240. package/src/server/claude-pty-mcp/tools/websearch.test.ts +40 -0
  241. package/src/server/claude-pty-mcp/tools/websearch.ts +42 -0
  242. package/src/server/claude-pty-mcp/tools/write.adapter.ts +60 -0
  243. package/src/server/claude-pty-mcp/tools/write.test.ts +52 -0
  244. package/src/server/claude-pty-mcp/uploads.adapter.ts +98 -0
  245. package/src/server/claude-pty-mcp/uploads.ts +38 -0
  246. package/src/server/claude-turn.test.ts +176 -0
  247. package/src/server/cli-runtime.test.ts +456 -0
  248. package/src/server/cli-runtime.ts +374 -0
  249. package/src/server/cli-supervisor.ts +81 -0
  250. package/src/server/cli.ts +78 -0
  251. package/src/server/client-log-forwarder.test.ts +74 -0
  252. package/src/server/client-log-forwarder.ts +75 -0
  253. package/src/server/codex-app-server-protocol.ts +449 -0
  254. package/src/server/codex-app-server.test.ts +2990 -0
  255. package/src/server/codex-app-server.ts +1713 -0
  256. package/src/server/coordination-integration.test.ts +63 -0
  257. package/src/server/coordination-mcp.test.ts +149 -0
  258. package/src/server/coordination-mcp.ts +197 -0
  259. package/src/server/delegation-coordinator.test.ts +675 -0
  260. package/src/server/delegation-coordinator.ts +454 -0
  261. package/src/server/discovery.test.ts +211 -0
  262. package/src/server/discovery.ts +301 -0
  263. package/src/server/event-store-agent-config.test.ts +124 -0
  264. package/src/server/event-store-coordination.test.ts +149 -0
  265. package/src/server/event-store-profile.test.ts +132 -0
  266. package/src/server/event-store-repo.test.ts +154 -0
  267. package/src/server/event-store-runner-team.test.ts +104 -0
  268. package/src/server/event-store.test.ts +342 -0
  269. package/src/server/event-store.ts +2208 -0
  270. package/src/server/events.ts +379 -0
  271. package/src/server/extension-router.test.ts +183 -0
  272. package/src/server/extension-router.ts +114 -0
  273. package/src/server/extensions/agents/server.test.ts +191 -0
  274. package/src/server/extensions/agents/server.ts +108 -0
  275. package/src/server/extensions/c3/server.test.ts +284 -0
  276. package/src/server/extensions/c3/server.ts +212 -0
  277. package/src/server/extensions/code/server.test.ts +200 -0
  278. package/src/server/extensions/code/server.ts +150 -0
  279. package/src/server/extensions.config.ts +10 -0
  280. package/src/server/external-open.ts +69 -0
  281. package/src/server/generate-fork-context.ts +58 -0
  282. package/src/server/generate-merge-context.test.ts +290 -0
  283. package/src/server/generate-merge-context.ts +141 -0
  284. package/src/server/generate-title.ts +36 -0
  285. package/src/server/git-clone-policy.test.ts +138 -0
  286. package/src/server/git-clone-policy.ts +27 -0
  287. package/src/server/harness-types.ts +1 -0
  288. package/src/server/journey-verification.test.ts +640 -0
  289. package/src/server/journey-verification.ts +195 -0
  290. package/src/server/machine-name.ts +22 -0
  291. package/src/server/nats-auth.test.ts +92 -0
  292. package/src/server/nats-auth.ts +6 -0
  293. package/src/server/nats-bind-guard.test.ts +71 -0
  294. package/src/server/nats-bind-guard.ts +42 -0
  295. package/src/server/nats-bridge.test.ts +141 -0
  296. package/src/server/nats-bridge.ts +111 -0
  297. package/src/server/nats-connector.test.ts +56 -0
  298. package/src/server/nats-connector.ts +71 -0
  299. package/src/server/nats-daemon-manager.test.ts +76 -0
  300. package/src/server/nats-daemon-manager.ts +174 -0
  301. package/src/server/nats-publisher.test.ts +356 -0
  302. package/src/server/nats-publisher.ts +271 -0
  303. package/src/server/nats-responders.test.ts +1018 -0
  304. package/src/server/nats-responders.ts +925 -0
  305. package/src/server/nats-streams.test.ts +112 -0
  306. package/src/server/nats-streams.ts +129 -0
  307. package/src/server/oauth-pool/oauth-responders.ts +185 -0
  308. package/src/server/oauth-pool/oauth-settings-store.ts +173 -0
  309. package/src/server/oauth-pool/oauth-token-pool.ts +303 -0
  310. package/src/server/orchestration.test.ts +1063 -0
  311. package/src/server/orchestration.ts +716 -0
  312. package/src/server/pairing-endpoints.test.ts +171 -0
  313. package/src/server/pairing-store.test.ts +154 -0
  314. package/src/server/pairing-store.ts +124 -0
  315. package/src/server/paths.ts +27 -0
  316. package/src/server/pr3-liveness.test.ts +252 -0
  317. package/src/server/process-utils.ts +10 -0
  318. package/src/server/project-cli.ts +180 -0
  319. package/src/server/provider-catalog.test.ts +177 -0
  320. package/src/server/provider-catalog.ts +146 -0
  321. package/src/server/pty-responders.ts +345 -0
  322. package/src/server/push-notifications.test.ts +234 -0
  323. package/src/server/push-notifications.ts +188 -0
  324. package/src/server/quick-response.test.ts +196 -0
  325. package/src/server/quick-response.ts +154 -0
  326. package/src/server/read-models-agent-config.test.ts +59 -0
  327. package/src/server/read-models-coordination.test.ts +69 -0
  328. package/src/server/read-models.test.ts +332 -0
  329. package/src/server/read-models.ts +258 -0
  330. package/src/server/repo-journey.test.ts +96 -0
  331. package/src/server/repo-manager.test.ts +118 -0
  332. package/src/server/repo-manager.ts +97 -0
  333. package/src/server/repo-status.test.ts +54 -0
  334. package/src/server/repo-status.ts +82 -0
  335. package/src/server/restart.test.ts +27 -0
  336. package/src/server/restart.ts +30 -0
  337. package/src/server/runner-incompatible-gate.test.ts +383 -0
  338. package/src/server/runner-manager.test.ts +72 -0
  339. package/src/server/runner-manager.ts +312 -0
  340. package/src/server/runner-pairing-urls.test.ts +59 -0
  341. package/src/server/runner-pairing-urls.ts +67 -0
  342. package/src/server/runner-proxy.test.ts +456 -0
  343. package/src/server/runner-proxy.ts +494 -0
  344. package/src/server/runner-router.test.ts +429 -0
  345. package/src/server/runner-router.ts +212 -0
  346. package/src/server/runner-routing.test.ts +584 -0
  347. package/src/server/runtime-registry.test.ts +436 -0
  348. package/src/server/runtime-registry.ts +307 -0
  349. package/src/server/sandbox-health.test.ts +127 -0
  350. package/src/server/sandbox-health.ts +94 -0
  351. package/src/server/sandbox-journey.test.ts +232 -0
  352. package/src/server/sandbox-manager.test.ts +146 -0
  353. package/src/server/sandbox-manager.ts +159 -0
  354. package/src/server/server.test.ts +287 -0
  355. package/src/server/server.ts +1108 -0
  356. package/src/server/session-discovery.test.ts +129 -0
  357. package/src/server/session-discovery.ts +475 -0
  358. package/src/server/session-index.test.ts +362 -0
  359. package/src/server/session-index.ts +119 -0
  360. package/src/server/session-seed.ts +288 -0
  361. package/src/server/share.test.ts +108 -0
  362. package/src/server/share.ts +113 -0
  363. package/src/server/skill-discovery.test.ts +201 -0
  364. package/src/server/skill-discovery.ts +77 -0
  365. package/src/server/storage/test-helpers.ts +67 -0
  366. package/src/server/terminal-manager.test.ts +309 -0
  367. package/src/server/terminal-manager.ts +354 -0
  368. package/src/server/transcript-consumer.test.ts +339 -0
  369. package/src/server/transcript-consumer.ts +162 -0
  370. package/src/server/transcript-search.test.ts +193 -0
  371. package/src/server/transcript-search.ts +83 -0
  372. package/src/server/transcript-utils.ts +52 -0
  373. package/src/server/update-manager.test.ts +107 -0
  374. package/src/server/update-manager.ts +230 -0
  375. package/src/server/workflow-engine.test.ts +251 -0
  376. package/src/server/workflow-engine.ts +169 -0
  377. package/src/server/workflow-mcp.ts +49 -0
  378. package/src/server/workflow-store.test.ts +155 -0
  379. package/src/server/workflow-store.ts +139 -0
  380. package/src/server/workspace-agent-integration.test.ts +167 -0
  381. package/src/server/workspace-agent-routes.test.ts +127 -0
  382. package/src/server/workspace-agent-routes.ts +89 -0
  383. package/src/server/workspace-agent.test.ts +103 -0
  384. package/src/server/workspace-agent.ts +102 -0
  385. package/src/server/workspace-cli.test.ts +79 -0
  386. package/src/server/workspace-config-manager.test.ts +109 -0
  387. package/src/server/workspace-config-manager.ts +83 -0
  388. package/src/server/workspace-directory-policy.test.ts +109 -0
  389. package/src/server/workspace-directory-policy.ts +56 -0
  390. package/src/shared/agent-config-types.ts +25 -0
  391. package/src/shared/branding.test.ts +42 -0
  392. package/src/shared/branding.ts +54 -0
  393. package/src/shared/compression.test.ts +85 -0
  394. package/src/shared/compression.ts +42 -0
  395. package/src/shared/coordination-store.test.ts +24 -0
  396. package/src/shared/coordination-store.ts +26 -0
  397. package/src/shared/dev-ports.test.ts +84 -0
  398. package/src/shared/dev-ports.ts +100 -0
  399. package/src/shared/extension-types.ts +45 -0
  400. package/src/shared/fork-presets.ts +54 -0
  401. package/src/shared/harness-types.test.ts +15 -0
  402. package/src/shared/harness-types.ts +21 -0
  403. package/src/shared/log-sink.test.ts +112 -0
  404. package/src/shared/log-sink.ts +185 -0
  405. package/src/shared/mention-pattern.ts +7 -0
  406. package/src/shared/merge-presets.ts +41 -0
  407. package/src/shared/nats-subjects.test.ts +61 -0
  408. package/src/shared/nats-subjects.ts +131 -0
  409. package/src/shared/permission-policy.ts +136 -0
  410. package/src/shared/ports.ts +3 -0
  411. package/src/shared/preset-types.ts +15 -0
  412. package/src/shared/profile-types.ts +49 -0
  413. package/src/shared/projectFileUrl.ts +36 -0
  414. package/src/shared/protocol.ts +153 -0
  415. package/src/shared/pty-instance.ts +43 -0
  416. package/src/shared/puggy/diagnostics/result.ts +18 -0
  417. package/src/shared/puggy/expressions/evaluate.ts +292 -0
  418. package/src/shared/puggy/index.test.ts +101 -0
  419. package/src/shared/puggy/index.ts +69 -0
  420. package/src/shared/puggy/parser/ast.ts +110 -0
  421. package/src/shared/puggy/parser/parser.ts +624 -0
  422. package/src/shared/puggy/renderer/html.ts +447 -0
  423. package/src/shared/runner-protocol.test.ts +277 -0
  424. package/src/shared/runner-protocol.ts +210 -0
  425. package/src/shared/runner-team-types.ts +73 -0
  426. package/src/shared/runtime-types.ts +48 -0
  427. package/src/shared/sandbox-types.ts +53 -0
  428. package/src/shared/tailwind-build.test.ts +12 -0
  429. package/src/shared/tinkaria-system-prompt.ts +101 -0
  430. package/src/shared/tools.test.ts +335 -0
  431. package/src/shared/tools.ts +397 -0
  432. package/src/shared/transcript-entries.ts +27 -0
  433. package/src/shared/transcript-render.test.ts +225 -0
  434. package/src/shared/transcript-render.ts +467 -0
  435. package/src/shared/types.ts +1031 -0
  436. package/src/shared/vite-config.test.ts +47 -0
  437. package/src/shared/web-context.test.ts +110 -0
  438. package/src/shared/web-context.ts +76 -0
  439. package/src/shared/workflow-types.ts +51 -0
  440. package/src/shared/workspace-types.ts +100 -0
@@ -0,0 +1,277 @@
1
+ import { describe, test, expect } from "bun:test"
2
+ import {
3
+ runnerHeartbeatSubject,
4
+ runnerCmdSubject,
5
+ runnerEventsSubject,
6
+ RUNNER_REGISTRY_BUCKET,
7
+ RUNNER_EVENTS_STREAM,
8
+ ALL_RUNNER_EVENTS,
9
+ PROTOCOL_VERSION,
10
+ SUPPORTED_RANGE,
11
+ isProtocolSupported,
12
+ runnerLivenessState,
13
+ LIVENESS_DEGRADED_MS,
14
+ LIVENESS_OFFLINE_MS,
15
+ type RunnerTurnEvent,
16
+ type StartTurnCommand,
17
+ type CancelTurnCommand,
18
+ type RespondToolCommand,
19
+ type ShutdownCommand,
20
+ type RunnerRegistration,
21
+ type RunnerHeartbeat,
22
+ } from "./runner-protocol"
23
+
24
+ describe("runner protocol subjects", () => {
25
+ test("heartbeat subject", () => {
26
+ expect(runnerHeartbeatSubject("r1")).toBe("runtime.runner.heartbeat.r1")
27
+ })
28
+
29
+ test("command subjects", () => {
30
+ expect(runnerCmdSubject("r1", "start_turn")).toBe("runtime.runner.cmd.r1.start_turn")
31
+ expect(runnerCmdSubject("r1", "cancel_turn")).toBe("runtime.runner.cmd.r1.cancel_turn")
32
+ expect(runnerCmdSubject("r1", "respond_tool")).toBe("runtime.runner.cmd.r1.respond_tool")
33
+ expect(runnerCmdSubject("r1", "shutdown")).toBe("runtime.runner.cmd.r1.shutdown")
34
+ })
35
+
36
+ test("events subject", () => {
37
+ expect(runnerEventsSubject("chat-123")).toBe("runtime.runner.evt.chat-123")
38
+ })
39
+
40
+ test("registry bucket constant", () => {
41
+ expect(RUNNER_REGISTRY_BUCKET).toBe("runtime_runner_registry")
42
+ })
43
+
44
+ test("stream constants", () => {
45
+ expect(RUNNER_EVENTS_STREAM).toBe("KANNA_RUNNER_EVENTS")
46
+ expect(ALL_RUNNER_EVENTS).toBe("runtime.runner.evt.>")
47
+ })
48
+ })
49
+
50
+ // ── PR4 Stage 1 audit: StartTurnCommand secret boundary ─────────────
51
+
52
+ describe("StartTurnCommand PR4 shape audit", () => {
53
+ const SECRET_PATTERN = /API_KEY|TOKEN|SECRET|Bearer|sk-/i
54
+
55
+ function hasSecretShapedKey(obj: Record<string, string>): boolean {
56
+ return Object.keys(obj).some((k) => SECRET_PATTERN.test(k))
57
+ }
58
+
59
+ function hasSecretShapedValue(obj: Record<string, string>): boolean {
60
+ return Object.values(obj).some((v) => SECRET_PATTERN.test(v))
61
+ }
62
+
63
+ test("StartTurnCommand type has no binaryPath field", () => {
64
+ // This is a type-level check enforced via the shape of a representative command.
65
+ // If binaryPath were re-introduced, the spread below would surface it.
66
+ const cmd: StartTurnCommand = {
67
+ chatId: "c1",
68
+ provider: "claude",
69
+ content: "hello",
70
+ model: "claude-sonnet-4-6",
71
+ planMode: false,
72
+ appendUserPrompt: true,
73
+ workspaceLocalPath: "/tmp/ws",
74
+ sessionToken: null,
75
+ chatTitle: "New Chat",
76
+ existingMessageCount: 0,
77
+ workspaceId: "p1",
78
+ extraEnv: { NODE_ENV: "production" },
79
+ }
80
+ // Serialise as the server would send it on the wire.
81
+ const wire = JSON.parse(JSON.stringify(cmd)) as Record<string, unknown>
82
+ expect("binaryPath" in wire).toBe(false)
83
+ })
84
+
85
+ test("resolveProfileOverrides returns no binaryPath in its shape (env only)", () => {
86
+ // We represent the server output by constructing the object it would spread.
87
+ // This mirrors the server calling resolveProfileOverrides and spreading into StartTurnCommand.
88
+ const profileOverrides: { extraEnv?: Record<string, string> } = {
89
+ extraEnv: { SOME_TEAM_FLAG: "1" },
90
+ }
91
+ const wire = JSON.parse(JSON.stringify(profileOverrides)) as Record<string, unknown>
92
+ expect("binaryPath" in wire).toBe(false)
93
+ expect("extraEnv" in wire).toBe(true)
94
+ })
95
+
96
+ test("extraEnv with no secret-shaped keys passes the audit guard", () => {
97
+ const safeEnv: Record<string, string> = {
98
+ NODE_ENV: "production",
99
+ SOME_TEAM_FLAG: "1",
100
+ LOG_LEVEL: "info",
101
+ }
102
+ expect(hasSecretShapedKey(safeEnv)).toBe(false)
103
+ expect(hasSecretShapedValue(safeEnv)).toBe(false)
104
+ })
105
+
106
+ test("extraEnv with secret-shaped keys is detected by the audit guard", () => {
107
+ const leakyEnv: Record<string, string> = {
108
+ ANTHROPIC_API_KEY: "sk-ant-abc123",
109
+ NODE_ENV: "production",
110
+ }
111
+ expect(hasSecretShapedKey(leakyEnv)).toBe(true)
112
+ })
113
+
114
+ test("extraEnv with Bearer-prefixed value is detected by the audit guard", () => {
115
+ const leakyEnv: Record<string, string> = {
116
+ AUTH_HEADER: "Bearer eyJhbGci...",
117
+ }
118
+ expect(hasSecretShapedValue(leakyEnv)).toBe(true)
119
+ })
120
+
121
+ test("a representative wire-serialised StartTurnCommand contains no binaryPath and no secret-shaped values", () => {
122
+ const cmd: StartTurnCommand = {
123
+ chatId: "c-audit",
124
+ provider: "codex",
125
+ content: "implement feature X",
126
+ model: "gpt-5.4",
127
+ planMode: false,
128
+ appendUserPrompt: true,
129
+ workspaceLocalPath: "/home/user/project",
130
+ sessionToken: null,
131
+ chatTitle: "Feature chat",
132
+ existingMessageCount: 0,
133
+ workspaceId: "ws-1",
134
+ extraEnv: { TEAM_FLAG: "on", NODE_ENV: "production" },
135
+ }
136
+ const wire = JSON.parse(JSON.stringify(cmd)) as Record<string, unknown>
137
+
138
+ expect("binaryPath" in wire).toBe(false)
139
+
140
+ const env = wire.extraEnv as Record<string, string> | undefined
141
+ if (env) {
142
+ expect(hasSecretShapedKey(env)).toBe(false)
143
+ expect(hasSecretShapedValue(env)).toBe(false)
144
+ }
145
+ })
146
+ })
147
+
148
+ describe("runner protocol types", () => {
149
+ test("RunnerTurnEvent discriminated union covers all event types", () => {
150
+ const events: RunnerTurnEvent[] = [
151
+ { type: "transcript", chatId: "c1", entry: { _id: "e1", kind: "assistant_text", text: "hi", createdAt: 1 } as any },
152
+ { type: "session_token", chatId: "c1", sessionToken: "tok" },
153
+ { type: "status_change", chatId: "c1", status: "running" as any },
154
+ { type: "pending_tool", chatId: "c1", tool: null },
155
+ { type: "turn_finished", chatId: "c1" },
156
+ { type: "turn_failed", chatId: "c1", error: "oops" },
157
+ { type: "turn_cancelled", chatId: "c1" },
158
+ { type: "title_generated", chatId: "c1", title: "My Chat" },
159
+ { type: "plan_mode_set", chatId: "c1", planMode: true },
160
+ { type: "provider_set", chatId: "c1", provider: "claude" },
161
+ { type: "context_cleared", chatId: "c1" },
162
+ ]
163
+ expect(events).toHaveLength(11)
164
+ // Verify each type is unique
165
+ const types = events.map(e => e.type)
166
+ expect(new Set(types).size).toBe(11)
167
+ })
168
+
169
+ test("StartTurnCommand has required fields", () => {
170
+ const cmd: StartTurnCommand = {
171
+ chatId: "c1", provider: "claude", content: "hello",
172
+ delegatedContext: "Forked parent chat context:\nUser: earlier work",
173
+ isSpawned: true,
174
+ model: "claude-sonnet-4-6", planMode: false, appendUserPrompt: true,
175
+ workspaceLocalPath: "/tmp", sessionToken: null, chatTitle: "New Chat",
176
+ existingMessageCount: 0, workspaceId: "p1",
177
+ }
178
+ expect(cmd.chatId).toBe("c1")
179
+ expect(cmd.provider).toBe("claude")
180
+ expect(cmd.delegatedContext).toContain("Forked parent chat context:")
181
+ expect(cmd.isSpawned).toBe(true)
182
+ })
183
+
184
+ test("CancelTurnCommand has required fields", () => {
185
+ const cmd: CancelTurnCommand = { chatId: "c1" }
186
+ expect(cmd.chatId).toBe("c1")
187
+ })
188
+
189
+ test("RespondToolCommand has required fields", () => {
190
+ const cmd: RespondToolCommand = { chatId: "c1", toolUseId: "t1", result: "approved" }
191
+ expect(cmd.chatId).toBe("c1")
192
+ expect(cmd.toolUseId).toBe("t1")
193
+ })
194
+
195
+ test("ShutdownCommand has required fields", () => {
196
+ const cmd: ShutdownCommand = { reason: "user_requested" }
197
+ expect(cmd.reason).toBe("user_requested")
198
+ })
199
+
200
+ test("RunnerRegistration has required fields", () => {
201
+ const reg: RunnerRegistration = {
202
+ runnerId: "r1", pid: 123, startedAt: Date.now(), providers: ["claude", "codex"],
203
+ protocolVersion: 1,
204
+ }
205
+ expect(reg.runnerId).toBe("r1")
206
+ expect(reg.protocolVersion).toBe(1)
207
+ })
208
+
209
+ test("RunnerHeartbeat has required fields", () => {
210
+ const hb: RunnerHeartbeat = {
211
+ runnerId: "r1", activeChatIds: ["c1", "c2"], ts: Date.now(),
212
+ }
213
+ expect(hb.runnerId).toBe("r1")
214
+ expect(hb.activeChatIds).toHaveLength(2)
215
+ })
216
+ })
217
+
218
+ describe("protocol version constants", () => {
219
+ test("PROTOCOL_VERSION is 1", () => {
220
+ expect(PROTOCOL_VERSION).toBe(1)
221
+ })
222
+
223
+ test("SUPPORTED_RANGE min=max=PROTOCOL_VERSION", () => {
224
+ expect(SUPPORTED_RANGE.min).toBe(PROTOCOL_VERSION)
225
+ expect(SUPPORTED_RANGE.max).toBe(PROTOCOL_VERSION)
226
+ })
227
+ })
228
+
229
+ describe("isProtocolSupported", () => {
230
+ test("returns true for v1 (current)", () => {
231
+ expect(isProtocolSupported(1)).toBe(true)
232
+ })
233
+
234
+ test("returns false for v0 (below range)", () => {
235
+ expect(isProtocolSupported(0)).toBe(false)
236
+ })
237
+
238
+ test("returns false for v2 (above range)", () => {
239
+ expect(isProtocolSupported(2)).toBe(false)
240
+ })
241
+
242
+ test("returns false for negative version", () => {
243
+ expect(isProtocolSupported(-1)).toBe(false)
244
+ })
245
+ })
246
+
247
+ describe("runnerLivenessState", () => {
248
+ const NOW = 1_000_000
249
+
250
+ test("null lastHeartbeatAt → offline", () => {
251
+ expect(runnerLivenessState(null, NOW)).toBe("offline")
252
+ })
253
+
254
+ test("age=0 → online", () => {
255
+ expect(runnerLivenessState(NOW, NOW)).toBe("online")
256
+ })
257
+
258
+ test("age=24_999 (just under LIVENESS_DEGRADED_MS) → online", () => {
259
+ expect(runnerLivenessState(NOW - (LIVENESS_DEGRADED_MS - 1), NOW)).toBe("online")
260
+ })
261
+
262
+ test("age=25_000 (at LIVENESS_DEGRADED_MS) → degraded", () => {
263
+ expect(runnerLivenessState(NOW - LIVENESS_DEGRADED_MS, NOW)).toBe("degraded")
264
+ })
265
+
266
+ test("age=59_999 (just under LIVENESS_OFFLINE_MS) → degraded", () => {
267
+ expect(runnerLivenessState(NOW - (LIVENESS_OFFLINE_MS - 1), NOW)).toBe("degraded")
268
+ })
269
+
270
+ test("age=60_000 (at LIVENESS_OFFLINE_MS) → offline", () => {
271
+ expect(runnerLivenessState(NOW - LIVENESS_OFFLINE_MS, NOW)).toBe("offline")
272
+ })
273
+
274
+ test("age=100_000 (well above LIVENESS_OFFLINE_MS) → offline", () => {
275
+ expect(runnerLivenessState(NOW - 100_000, NOW)).toBe("offline")
276
+ })
277
+ })
@@ -0,0 +1,210 @@
1
+ import type { AgentProvider, TranscriptEntry, SessionStatus, PendingToolSnapshot } from "./types"
2
+
3
+ // ── Protocol versioning ──────────────────────────────────────────────
4
+
5
+ /** Current protocol version emitted by this runner build. */
6
+ export const PROTOCOL_VERSION = 1
7
+
8
+ /** Server-side supported protocol range. Runners outside [min, max] are incompatible. */
9
+ export const SUPPORTED_RANGE: { min: number; max: number } = { min: 1, max: 1 }
10
+
11
+ /** Returns true if v is within the supported protocol range. */
12
+ export function isProtocolSupported(v: number): boolean {
13
+ return v >= SUPPORTED_RANGE.min && v <= SUPPORTED_RANGE.max
14
+ }
15
+
16
+ // ── Liveness ─────────────────────────────────────────────────────────
17
+
18
+ /** Age threshold below which a runner is considered online (ms). */
19
+ export const LIVENESS_DEGRADED_MS = 25_000
20
+
21
+ /** Age threshold at-or-above which a runner is considered offline (ms). */
22
+ export const LIVENESS_OFFLINE_MS = 60_000
23
+
24
+ export type RunnerLivenessState = "online" | "degraded" | "offline"
25
+
26
+ /**
27
+ * Compute liveness state from last heartbeat timestamp and current time.
28
+ * Pure function — no I/O or side effects.
29
+ */
30
+ export function runnerLivenessState(
31
+ lastHeartbeatAt: number | null,
32
+ now: number,
33
+ ): RunnerLivenessState {
34
+ if (lastHeartbeatAt === null) return "offline"
35
+ const age = now - lastHeartbeatAt
36
+ if (age < LIVENESS_DEGRADED_MS) return "online"
37
+ if (age < LIVENESS_OFFLINE_MS) return "degraded"
38
+ return "offline"
39
+ }
40
+
41
+ // ── Subject helpers ──────────────────────────────────────────────────
42
+
43
+ const PREFIX = "runtime.runner"
44
+
45
+ export function runnerHeartbeatSubject(runnerId: string): string {
46
+ return `${PREFIX}.heartbeat.${runnerId}`
47
+ }
48
+
49
+ export function runnerCmdSubject(runnerId: string, cmd: string): string {
50
+ return `${PREFIX}.cmd.${runnerId}.${cmd}`
51
+ }
52
+
53
+ export function runnerEventsSubject(chatId: string): string {
54
+ return `${PREFIX}.evt.${chatId}`
55
+ }
56
+
57
+ // ── Constants ────────────────────────────────────────────────────────
58
+
59
+ /** KV bucket name for runner registration entries */
60
+ export const RUNNER_REGISTRY_BUCKET = "runtime_runner_registry"
61
+
62
+ /** JetStream stream name for runner turn events */
63
+ export const RUNNER_EVENTS_STREAM = "KANNA_RUNNER_EVENTS"
64
+
65
+ /** Wildcard: all runner events */
66
+ export const ALL_RUNNER_EVENTS = `${PREFIX}.evt.>`
67
+
68
+ // ── Command types ────────────────────────────────────────────────────
69
+
70
+ export interface StartTurnCommand {
71
+ chatId: string
72
+ provider: AgentProvider
73
+ content: string
74
+ delegatedContext?: string
75
+ isSpawned?: boolean
76
+ model: string
77
+ planMode: boolean
78
+ appendUserPrompt: boolean
79
+ workspaceLocalPath: string
80
+ sessionToken: string | null
81
+ chatTitle: string
82
+ existingMessageCount: number
83
+ workspaceId: string
84
+ /**
85
+ * Non-secret team env vars from the provider profile. The runner merges
86
+ * these with its own process.env (process.env wins on collision). Must
87
+ * NOT contain secrets (API keys, tokens, OAuth credentials) — secrets are
88
+ * resolved runner-side from local env and the OAuth pool and never transit
89
+ * the server↔runner boundary.
90
+ */
91
+ extraEnv?: Record<string, string>
92
+ }
93
+
94
+ export interface CancelTurnCommand {
95
+ chatId: string
96
+ }
97
+
98
+ export interface StopChatPtyCommand {
99
+ chatId: string
100
+ }
101
+
102
+ export interface RespondToolCommand {
103
+ chatId: string
104
+ toolUseId: string
105
+ result: string
106
+ }
107
+
108
+ export interface ShutdownCommand {
109
+ reason: string
110
+ }
111
+
112
+ // ── Turn event discriminated union ───────────────────────────────────
113
+
114
+ interface RunnerTurnEventBase {
115
+ chatId: string
116
+ }
117
+
118
+ interface TranscriptEvent extends RunnerTurnEventBase {
119
+ type: "transcript"
120
+ entry: TranscriptEntry
121
+ }
122
+
123
+ interface SessionTokenEvent extends RunnerTurnEventBase {
124
+ type: "session_token"
125
+ sessionToken: string
126
+ }
127
+
128
+ interface StatusChangeEvent extends RunnerTurnEventBase {
129
+ type: "status_change"
130
+ status: SessionStatus
131
+ }
132
+
133
+ interface PendingToolEvent extends RunnerTurnEventBase {
134
+ type: "pending_tool"
135
+ tool: PendingToolSnapshot | null
136
+ }
137
+
138
+ interface TurnFinishedEvent extends RunnerTurnEventBase {
139
+ type: "turn_finished"
140
+ }
141
+
142
+ interface TurnFailedEvent extends RunnerTurnEventBase {
143
+ type: "turn_failed"
144
+ error: string
145
+ }
146
+
147
+ interface TurnCancelledEvent extends RunnerTurnEventBase {
148
+ type: "turn_cancelled"
149
+ }
150
+
151
+ interface TitleGeneratedEvent extends RunnerTurnEventBase {
152
+ type: "title_generated"
153
+ title: string
154
+ }
155
+
156
+ interface PlanModeSetEvent extends RunnerTurnEventBase {
157
+ type: "plan_mode_set"
158
+ planMode: boolean
159
+ }
160
+
161
+ interface ProviderSetEvent extends RunnerTurnEventBase {
162
+ type: "provider_set"
163
+ provider: AgentProvider
164
+ }
165
+
166
+ interface ContextClearedEvent extends RunnerTurnEventBase {
167
+ type: "context_cleared"
168
+ }
169
+
170
+ export type RunnerTurnEvent =
171
+ | TranscriptEvent
172
+ | SessionTokenEvent
173
+ | StatusChangeEvent
174
+ | PendingToolEvent
175
+ | TurnFinishedEvent
176
+ | TurnFailedEvent
177
+ | TurnCancelledEvent
178
+ | TitleGeneratedEvent
179
+ | PlanModeSetEvent
180
+ | ProviderSetEvent
181
+ | ContextClearedEvent
182
+
183
+ // ── Registration & heartbeat ─────────────────────────────────────────
184
+
185
+ export interface RunnerCapabilities {
186
+ providers: AgentProvider[]
187
+ }
188
+
189
+ export interface RunnerRegistration {
190
+ runnerId: string
191
+ pid: number
192
+ startedAt: number
193
+ providers: AgentProvider[]
194
+ /** Protocol version reported by the runner. Missing → treated as incompatible. */
195
+ protocolVersion: number
196
+ /** Optional capability probe (shape only; rich probe added in PR4). */
197
+ capabilities?: RunnerCapabilities
198
+ /**
199
+ * Timestamp (ms since epoch) of the runner's last KV self-write, piggybacked on
200
+ * the heartbeat loop. Used by the discover path (no live heartbeat subscription)
201
+ * to judge liveness via runnerLivenessState. Not written by the server.
202
+ */
203
+ lastSeenAt?: number
204
+ }
205
+
206
+ export interface RunnerHeartbeat {
207
+ runnerId: string
208
+ activeChatIds: string[]
209
+ ts: number
210
+ }
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Runner team types (US-RTN).
3
+ *
4
+ * Operator-managed, display-only metadata for remote runners:
5
+ * - TeamMember: a flat "member" the single operator manages (names only — no
6
+ * auth, no accounts, no permissions).
7
+ * - RunnerLabel: a human name + optional member assignment, keyed by runnerId.
8
+ *
9
+ * Persisted as EventStore events (see events.ts `RunnerTeamEvent`), mirroring
10
+ * provider profiles. This is intentionally separate from the runner-owned NATS
11
+ * KV registry (`runtime_runner_registry`), which the runner rewrites on every
12
+ * heartbeat and would clobber any server-set fields. Routing/eligibility never
13
+ * reads this data.
14
+ */
15
+
16
+ /** A member of the operator's local "team". Names only — not an authenticated user. */
17
+ export interface TeamMember {
18
+ id: string
19
+ name: string
20
+ }
21
+
22
+ /** Human label + member assignment for a single runner. Upserted by runnerId. */
23
+ export interface RunnerLabel {
24
+ runnerId: string
25
+ /** Operator-given runner name. null ⇒ UI falls back to the short runnerId. */
26
+ name: string | null
27
+ /** Assigned member id, or null when unassigned. */
28
+ memberId: string | null
29
+ /** Unix epoch ms of the last label write. */
30
+ updatedAt: number
31
+ }
32
+
33
+ /** Stored runner-label record (currently identical to RunnerLabel; kept distinct for parity with ProviderProfileRecord). */
34
+ export type RunnerLabelRecord = RunnerLabel
35
+
36
+ /** Snapshot broadcast on the `runner-teams` subscription topic. */
37
+ export interface RunnerTeamSnapshot {
38
+ members: TeamMember[]
39
+ runners: RunnerLabel[]
40
+ }
41
+
42
+ /**
43
+ * Resolve a runner's display name: the operator label when set, else a short
44
+ * form of the runnerId (last two dash-separated segments). Pure — unit-tested.
45
+ */
46
+ export function resolveRunnerName(
47
+ runnerId: string,
48
+ labels: ReadonlyMap<string, RunnerLabel> | readonly RunnerLabel[],
49
+ ): string {
50
+ const label = Array.isArray(labels)
51
+ ? labels.find((l) => l.runnerId === runnerId)
52
+ : (labels as ReadonlyMap<string, RunnerLabel>).get(runnerId)
53
+ const name = label?.name?.trim()
54
+ if (name) return name
55
+ const parts = runnerId.split("-")
56
+ return parts.length > 1 ? parts.slice(-2).join("-") : runnerId
57
+ }
58
+
59
+ /** Resolve the member assigned to a runner, or null. Pure. */
60
+ export function resolveRunnerMember(
61
+ runnerId: string,
62
+ labels: ReadonlyMap<string, RunnerLabel> | readonly RunnerLabel[],
63
+ members: ReadonlyMap<string, TeamMember> | readonly TeamMember[],
64
+ ): TeamMember | null {
65
+ const label = Array.isArray(labels)
66
+ ? labels.find((l) => l.runnerId === runnerId)
67
+ : (labels as ReadonlyMap<string, RunnerLabel>).get(runnerId)
68
+ if (!label?.memberId) return null
69
+ const memberId = label.memberId
70
+ return Array.isArray(members)
71
+ ? (members.find((m) => m.id === memberId) ?? null)
72
+ : ((members as ReadonlyMap<string, TeamMember>).get(memberId) ?? null)
73
+ }
@@ -0,0 +1,48 @@
1
+ export type RuntimeSource = "managed" | "system"
2
+
3
+ export interface RuntimeEntry {
4
+ provider: "claude" | "codex"
5
+ version: string
6
+ source: RuntimeSource
7
+ binaryPath: string
8
+ installedAt: number
9
+ packageName: string
10
+ capabilities?: RuntimeCapabilities
11
+ }
12
+
13
+ export interface RuntimeHealthStatus {
14
+ provider: string
15
+ version: string
16
+ binaryPath: string
17
+ status: "healthy" | "degraded" | "unavailable"
18
+ lastChecked: number
19
+ error?: string
20
+ latencyMs: number
21
+ }
22
+
23
+ export interface DiscoveredModel {
24
+ value: string
25
+ displayName: string
26
+ description: string
27
+ supportsEffort?: boolean
28
+ supportedEffortLevels?: string[]
29
+ supportsAdaptiveThinking?: boolean
30
+ supportsFastMode?: boolean
31
+ supportsAutoMode?: boolean
32
+ }
33
+
34
+ export interface RuntimeCapabilities {
35
+ models: DiscoveredModel[]
36
+ probedAt: number
37
+ runtimeVersion: string
38
+ error?: string
39
+ }
40
+
41
+ export interface RuntimeRegistryState {
42
+ entries: RuntimeEntry[]
43
+ defaults: Record<string, string>
44
+ }
45
+
46
+ export interface RuntimeSnapshot {
47
+ runtimes: (RuntimeEntry & { health: RuntimeHealthStatus })[]
48
+ }
@@ -0,0 +1,53 @@
1
+ export type SandboxStatus = "creating" | "running" | "stopped" | "error"
2
+
3
+ export interface ResourceLimits {
4
+ cpuShares: number
5
+ memoryMb: number
6
+ diskMb: number
7
+ pidsLimit: number
8
+ }
9
+
10
+ export const DEFAULT_RESOURCE_LIMITS: ResourceLimits = {
11
+ cpuShares: 512,
12
+ memoryMb: 2048,
13
+ diskMb: 10240,
14
+ pidsLimit: 256,
15
+ }
16
+
17
+ export interface SandboxRecord {
18
+ id: string
19
+ workspaceId: string
20
+ containerId: string | null
21
+ status: SandboxStatus
22
+ resourceLimits: ResourceLimits
23
+ natsUrl: string
24
+ createdAt: number
25
+ updatedAt: number
26
+ lastHealthCheck: number | null
27
+ error: string | null
28
+ }
29
+
30
+ export interface SandboxHealthReport {
31
+ sandboxId: string
32
+ workspaceId: string
33
+ status: "healthy" | "unhealthy" | "unreachable"
34
+ uptimeMs: number
35
+ memoryUsageMb: number
36
+ cpuPercent: number
37
+ natsConnected: boolean
38
+ }
39
+
40
+ export interface ContainerInspect {
41
+ id: string
42
+ status: string
43
+ running: boolean
44
+ startedAt: string
45
+ memoryUsage: number
46
+ cpuPercent: number
47
+ }
48
+
49
+ export interface SandboxSnapshot {
50
+ workspaceId: string
51
+ sandbox: SandboxRecord | null
52
+ health: SandboxHealthReport | null
53
+ }
@@ -0,0 +1,12 @@
1
+ import { describe, expect, test } from "bun:test"
2
+
3
+ const INDEX_CSS_PATH = new URL("../index.css", import.meta.url)
4
+
5
+ describe("tailwind build entry", () => {
6
+ test('constrains Tailwind source scanning to the app source tree', async () => {
7
+ const css = await Bun.file(INDEX_CSS_PATH).text()
8
+
9
+ expect(css).toContain('@import "tailwindcss" source(".");')
10
+ expect(css).not.toContain('@import "tailwindcss";')
11
+ })
12
+ })