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.
- package/LICENSE +84 -0
- package/README.md +202 -0
- package/bin/airaknit +9 -0
- package/bin/airaknit-project +14 -0
- package/bin/kanna +9 -0
- package/dist/client/assets/CompactSummaryMessage-Yw0BDWEJ.js +1 -0
- package/dist/client/assets/ExitPlanModeMessage-DIdkQ4uF.js +1 -0
- package/dist/client/assets/LocalFilePreviewDialog-DQx2eiCc.js +3 -0
- package/dist/client/assets/LocalProjectsSection-C4xlWkgS.js +1 -0
- package/dist/client/assets/TextMessage-B5G39DEJ.js +1 -0
- package/dist/client/assets/UserMessage-CIkWk-0L.js +1 -0
- package/dist/client/assets/_basePickBy-CVrAFfnZ.js +1 -0
- package/dist/client/assets/_baseUniq-JL-aaF4P.js +1 -0
- package/dist/client/assets/arc-B07zg7ol.js +1 -0
- package/dist/client/assets/architecture-YZFGNWBL-PSLVJL3p.js +1 -0
- package/dist/client/assets/architectureDiagram-Q4EWVU46-DfWIF1G_.js +36 -0
- package/dist/client/assets/array-BGFCBI0e.js +1 -0
- package/dist/client/assets/blockDiagram-DXYQGD6D-CzwIeo_B.js +132 -0
- package/dist/client/assets/bundle-mjs-BDE2gWbQ.js +1 -0
- package/dist/client/assets/button-DO50qOGv.js +1 -0
- package/dist/client/assets/c4Diagram-AHTNJAMY-CR8DCQRE.js +10 -0
- package/dist/client/assets/channel-Dj-UUfaF.js +1 -0
- package/dist/client/assets/chunk-2KRD3SAO-dznP-cn8.js +1 -0
- package/dist/client/assets/chunk-336JU56O-Dqss5Vu6.js +2 -0
- package/dist/client/assets/chunk-426QAEUC-CEKis_0_.js +1 -0
- package/dist/client/assets/chunk-4BX2VUAB-BYOv0Gm1.js +1 -0
- package/dist/client/assets/chunk-4TB4RGXK-BxzubH5S.js +206 -0
- package/dist/client/assets/chunk-55IACEB6-BSlTj03a.js +1 -0
- package/dist/client/assets/chunk-5FUZZQ4R-9Au93Bi1.js +62 -0
- package/dist/client/assets/chunk-5PVQY5BW-BhksHFEZ.js +2 -0
- package/dist/client/assets/chunk-67CJDMHE-BFwhz-8t.js +1 -0
- package/dist/client/assets/chunk-7N4EOEYR-BDUPds87.js +1 -0
- package/dist/client/assets/chunk-AA7GKIK3-CEWTdyXO.js +1 -0
- package/dist/client/assets/chunk-BO2N2NFS-D0LvxnhU.js +103 -0
- package/dist/client/assets/chunk-BSJP7CBP-BNJnK6sq.js +1 -0
- package/dist/client/assets/chunk-Bj-mKKzh.js +1 -0
- package/dist/client/assets/chunk-CIAEETIT-CYhfoCeN.js +1 -0
- package/dist/client/assets/chunk-EDXVE4YY-C5ovJLc0.js +1 -0
- package/dist/client/assets/chunk-ENJZ2VHE-HOhYaeGr.js +10 -0
- package/dist/client/assets/chunk-FMBD7UC4-BLCiKcAQ.js +15 -0
- package/dist/client/assets/chunk-FOC6F5B3-B6GtY2ek.js +1 -0
- package/dist/client/assets/chunk-ICPOFSXX-DPoIZoC5.js +122 -0
- package/dist/client/assets/chunk-K5T4RW27-BsKN63rv.js +94 -0
- package/dist/client/assets/chunk-KGLVRYIC-BUGn9uuY.js +1 -0
- package/dist/client/assets/chunk-LIHQZDEY-DhaZyo03.js +1 -0
- package/dist/client/assets/chunk-ORNJ4GCN-DlpeeJyi.js +1 -0
- package/dist/client/assets/chunk-OYMX7WX6-Dc9q7aYA.js +231 -0
- package/dist/client/assets/chunk-QZHKN3VN-BEdrPoSb.js +1 -0
- package/dist/client/assets/chunk-U2HBQHQK-CIB3Bjjd.js +70 -0
- package/dist/client/assets/chunk-X2U36JSP-CtB-o8Yp.js +1 -0
- package/dist/client/assets/chunk-XPW4576I-C6iHhX_8.js +32 -0
- package/dist/client/assets/chunk-YZCP3GAM-CTmKr6ZH.js +1 -0
- package/dist/client/assets/chunk-ZZ45TVLE-BgU8A2RF.js +1 -0
- package/dist/client/assets/classDiagram-6PBFFD2Q-Bqk5e679.js +1 -0
- package/dist/client/assets/classDiagram-v2-HSJHXN6E-6pSaZOkC.js +1 -0
- package/dist/client/assets/client-BrKWI4CM.js +1 -0
- package/dist/client/assets/client-CGgNRU9w.js +1 -0
- package/dist/client/assets/client-DMSLRzg9.js +6 -0
- package/dist/client/assets/clone-DWcL7whJ.js +1 -0
- package/dist/client/assets/cose-bilkent-S5V4N54A-CrV5wsV_.js +1 -0
- package/dist/client/assets/cytoscape.esm--aLzKuep.js +321 -0
- package/dist/client/assets/dagre-CuRxWcrj.js +1 -0
- package/dist/client/assets/dagre-KV5264BT-BIDiVnkA.js +4 -0
- package/dist/client/assets/defaultLocale-CRZydyG6.js +1 -0
- package/dist/client/assets/diagram-5BDNPKRD-i1kjKRCB.js +10 -0
- package/dist/client/assets/diagram-G4DWMVQ6-9ZSLuhbl.js +24 -0
- package/dist/client/assets/diagram-MMDJMWI5-B4_CUjgv.js +43 -0
- package/dist/client/assets/diagram-TYMM5635-Ct5eTGS8.js +24 -0
- package/dist/client/assets/dist-CuB4kiSK.js +1 -0
- package/dist/client/assets/erDiagram-SMLLAGMA-Cy38ercc.js +85 -0
- package/dist/client/assets/flowDiagram-DWJPFMVM-CZKuYl0V.js +162 -0
- package/dist/client/assets/ganttDiagram-T4ZO3ILL-DLPjCh7a.js +292 -0
- package/dist/client/assets/gitGraph-7Q5UKJZL-DqbrtEp9.js +1 -0
- package/dist/client/assets/gitGraphDiagram-UUTBAWPF-BoRBkDhQ.js +106 -0
- package/dist/client/assets/graphlib-BcQ6qlQh.js +1 -0
- package/dist/client/assets/highlighted-body-OFNGDK62-BEpBVDTX.js +1 -0
- package/dist/client/assets/index-CetCiuqP.js +105 -0
- package/dist/client/assets/index-N29Mip7A.css +1 -0
- package/dist/client/assets/info-OMHHGYJF-D98DRBJX.js +1 -0
- package/dist/client/assets/infoDiagram-42DDH7IO-BAcdTWbt.js +2 -0
- package/dist/client/assets/init-B8gtcn7T.js +1 -0
- package/dist/client/assets/isArrayLikeObject-D8SJFmkN.js +1 -0
- package/dist/client/assets/isEmpty-BF3YX5Jk.js +1 -0
- package/dist/client/assets/ishikawaDiagram-UXIWVN3A-Ynu2VKdC.js +70 -0
- package/dist/client/assets/journeyDiagram-VCZTEJTY-BjfhQaN3.js +139 -0
- package/dist/client/assets/jsx-runtime-CyI9ICYU.js +1 -0
- package/dist/client/assets/kanban-definition-6JOO6SKY-JLXH9zUJ.js +89 -0
- package/dist/client/assets/katex-B94qP8b6.js +265 -0
- package/dist/client/assets/lib--QVjyxmL.js +29 -0
- package/dist/client/assets/lib-B6rgJiZ9.js +1 -0
- package/dist/client/assets/line-DCrYfLBn.js +1 -0
- package/dist/client/assets/linear-_4upLmeo.js +1 -0
- package/dist/client/assets/mermaid-GHXKKRXX-rwJHYUmW.js +1 -0
- package/dist/client/assets/mermaid-parser.core-KZinfW8o.js +4 -0
- package/dist/client/assets/mermaid.core-QqY9gSNe.js +11 -0
- package/dist/client/assets/mindmap-definition-QFDTVHPH-TWgHDAzp.js +96 -0
- package/dist/client/assets/ordinal-CCj7PWgZ.js +1 -0
- package/dist/client/assets/packet-4T2RLAQJ-DEvfkn3F.js +1 -0
- package/dist/client/assets/path-DZF-JdEe.js +1 -0
- package/dist/client/assets/pie-ZZUOXDRM-72e6WVjb.js +1 -0
- package/dist/client/assets/pieDiagram-DEJITSTG-Cl8PCsoj.js +30 -0
- package/dist/client/assets/preload-helper-rov5CBGT.js +1 -0
- package/dist/client/assets/pty-client-DZ27IS00.js +1 -0
- package/dist/client/assets/ptyInstancesStore-D9ag7SYd.js +1 -0
- package/dist/client/assets/quadrantDiagram-34T5L4WZ-CHyVGp9E.js +7 -0
- package/dist/client/assets/radar-PYXPWWZC-Cp7xd_EY.js +1 -0
- package/dist/client/assets/react-CClhXMB2.js +1 -0
- package/dist/client/assets/react-Dd6D81m0.js +1 -0
- package/dist/client/assets/react-dom--G6_6fQ_.js +1 -0
- package/dist/client/assets/requirementDiagram-MS252O5E-DaanG2iM.js +84 -0
- package/dist/client/assets/rough.esm-BsmKo2S5.js +1 -0
- package/dist/client/assets/sankeyDiagram-XADWPNL6-B_fhLY36.js +10 -0
- package/dist/client/assets/sequenceDiagram-FGHM5R23-C5FNrveI.js +157 -0
- package/dist/client/assets/src-DeTlMJAU.js +1 -0
- package/dist/client/assets/stateDiagram-FHFEXIEX-nTTcdjjQ.js +1 -0
- package/dist/client/assets/stateDiagram-v2-QKLJ7IA2-Dw0632j_.js +1 -0
- package/dist/client/assets/timeline-definition-GMOUNBTQ-DkQV1yP8.js +120 -0
- package/dist/client/assets/treeView-SZITEDCU-ZLIgC7_K.js +1 -0
- package/dist/client/assets/treemap-W4RFUUIX-BqaMbB6N.js +1 -0
- package/dist/client/assets/uiIdentityOverlay-Ba7GNj7m.js +1 -0
- package/dist/client/assets/vennDiagram-DHZGUBPP-DbZ2xgs6.js +34 -0
- package/dist/client/assets/wardley-RL74JXVD-DXQS8zf4.js +1 -0
- package/dist/client/assets/wardleyDiagram-NUSXRM2D-BzCJ6MAu.js +20 -0
- package/dist/client/assets/xychartDiagram-5P7HB3ND-BSlFecop.js +7 -0
- package/dist/client/favicon.png +0 -0
- package/dist/client/favicon.svg +15 -0
- package/dist/client/fonts/body-medium.woff2 +0 -0
- package/dist/client/fonts/body-regular-italic.woff2 +0 -0
- package/dist/client/fonts/body-regular.woff2 +0 -0
- package/dist/client/fonts/body-semibold.woff2 +0 -0
- package/dist/client/index.html +31 -0
- package/dist/client/manifest.webmanifest +12 -0
- package/dist/client/sw.js +32 -0
- package/package.json +122 -0
- package/src/nats/auth-callout/callout-config.test.ts +93 -0
- package/src/nats/auth-callout/callout-config.ts +109 -0
- package/src/nats/auth-callout/callout.integration.test.ts +332 -0
- package/src/nats/auth-callout/keys.ts +103 -0
- package/src/nats/auth-callout/responder.ts +241 -0
- package/src/nats/auth-callout/scope-policy.test.ts +159 -0
- package/src/nats/auth-callout/scope-policy.ts +210 -0
- package/src/nats/auth-callout/token.test.ts +163 -0
- package/src/nats/auth-callout/token.ts +157 -0
- package/src/nats/nats-daemon-callout.ts +194 -0
- package/src/nats/nats-daemon.test.ts +77 -0
- package/src/nats/nats-daemon.ts +50 -0
- package/src/nats/nats-token.test.ts +61 -0
- package/src/nats/nats-token.ts +59 -0
- package/src/runner/coordination-mcp-integration.test.ts +134 -0
- package/src/runner/nats-coordination-client.test.ts +49 -0
- package/src/runner/nats-coordination-client.ts +94 -0
- package/src/runner/runner-agent.test.ts +469 -0
- package/src/runner/runner-agent.ts +453 -0
- package/src/runner/runner-credential.test.ts +93 -0
- package/src/runner/runner-credential.ts +82 -0
- package/src/runner/runner-nats.test.ts +495 -0
- package/src/runner/runner-nats.ts +323 -0
- package/src/runner/runner-pair.test.ts +107 -0
- package/src/runner/runner-pair.ts +81 -0
- package/src/runner/runner.test.ts +135 -0
- package/src/runner/runner.ts +212 -0
- package/src/runner/turn-factories.test.ts +97 -0
- package/src/runner/turn-factories.ts +475 -0
- package/src/server/agent-config-journey.test.ts +106 -0
- package/src/server/agent.ts +8 -0
- package/src/server/auto-continue/auth-error-detector.ts +66 -0
- package/src/server/auto-continue/limit-detector.ts +194 -0
- package/src/server/bm25.test.ts +92 -0
- package/src/server/bm25.ts +101 -0
- package/src/server/chat-events-jetstream.test.ts +135 -0
- package/src/server/claude-harness.ts +360 -0
- package/src/server/claude-pty/agent-normalizers.ts +309 -0
- package/src/server/claude-pty/auth.test.ts +38 -0
- package/src/server/claude-pty/auth.ts +32 -0
- package/src/server/claude-pty/claude-session-registry.adapter.ts +81 -0
- package/src/server/claude-pty/claude-session-registry.test.ts +149 -0
- package/src/server/claude-pty/driver.test.ts +902 -0
- package/src/server/claude-pty/driver.ts +807 -0
- package/src/server/claude-pty/jsonl-path.adapter.ts +57 -0
- package/src/server/claude-pty/jsonl-path.test.ts +114 -0
- package/src/server/claude-pty/jsonl-to-event.test.ts +241 -0
- package/src/server/claude-pty/jsonl-to-event.ts +174 -0
- package/src/server/claude-pty/output-ring.test.ts +35 -0
- package/src/server/claude-pty/output-ring.ts +25 -0
- package/src/server/claude-pty/parity-matrix.test.ts +227 -0
- package/src/server/claude-pty/pid-registry.adapter.ts +135 -0
- package/src/server/claude-pty/pid-registry.test.ts +122 -0
- package/src/server/claude-pty/preflight/binary-fingerprint.adapter.ts +20 -0
- package/src/server/claude-pty/preflight/binary-fingerprint.test.ts +32 -0
- package/src/server/claude-pty/pty-instance-registry.test.ts +177 -0
- package/src/server/claude-pty/pty-instance-registry.ts +166 -0
- package/src/server/claude-pty/pty-memory-sampler.adapter.test.ts +103 -0
- package/src/server/claude-pty/pty-memory-sampler.adapter.ts +85 -0
- package/src/server/claude-pty/pty-process.adapter.ts +66 -0
- package/src/server/claude-pty/pty-process.test.ts +49 -0
- package/src/server/claude-pty/resolve-binary.adapter.ts +106 -0
- package/src/server/claude-pty/resolve-binary.test.ts +118 -0
- package/src/server/claude-pty/runtime-dir.adapter.ts +19 -0
- package/src/server/claude-pty/settings-writer.adapter.ts +27 -0
- package/src/server/claude-pty/settings-writer.test.ts +22 -0
- package/src/server/claude-pty/smoke-test-io.adapter.ts +28 -0
- package/src/server/claude-pty/smoke-test.test.ts +191 -0
- package/src/server/claude-pty/smoke-test.ts +185 -0
- package/src/server/claude-pty/subagent-orchestrator.ts +887 -0
- package/src/server/claude-pty/tool-callback.ts +274 -0
- package/src/server/claude-pty/tui-control.test.ts +272 -0
- package/src/server/claude-pty/tui-control.ts +182 -0
- package/src/server/claude-pty/tui-source.adapter.test.ts +360 -0
- package/src/server/claude-pty/tui-source.adapter.ts +343 -0
- package/src/server/claude-pty/tunnel-gateway.ts +12 -0
- package/src/server/claude-pty-mcp/canonical-args.ts +15 -0
- package/src/server/claude-pty-mcp/fs-stat.adapter.ts +8 -0
- package/src/server/claude-pty-mcp/history-primer.ts +90 -0
- package/src/server/claude-pty-mcp/http-server.adapter.ts +33 -0
- package/src/server/claude-pty-mcp/mcp-http.ts +177 -0
- package/src/server/claude-pty-mcp/mcp.ts +412 -0
- package/src/server/claude-pty-mcp/mention-parser.ts +25 -0
- package/src/server/claude-pty-mcp/paths.ts +24 -0
- package/src/server/claude-pty-mcp/permission-gate.ts +243 -0
- package/src/server/claude-pty-mcp/terminal-pid-registry.adapter.ts +107 -0
- package/src/server/claude-pty-mcp/tools/ask-user-question.test.ts +119 -0
- package/src/server/claude-pty-mcp/tools/ask-user-question.ts +61 -0
- package/src/server/claude-pty-mcp/tools/bash.adapter.ts +76 -0
- package/src/server/claude-pty-mcp/tools/bash.test.ts +56 -0
- package/src/server/claude-pty-mcp/tools/delegate-subagent.test.ts +155 -0
- package/src/server/claude-pty-mcp/tools/delegate-subagent.ts +111 -0
- package/src/server/claude-pty-mcp/tools/edit.adapter.ts +95 -0
- package/src/server/claude-pty-mcp/tools/edit.test.ts +93 -0
- package/src/server/claude-pty-mcp/tools/exit-plan-mode.test.ts +61 -0
- package/src/server/claude-pty-mcp/tools/exit-plan-mode.ts +50 -0
- package/src/server/claude-pty-mcp/tools/glob.adapter.ts +86 -0
- package/src/server/claude-pty-mcp/tools/glob.test.ts +61 -0
- package/src/server/claude-pty-mcp/tools/grep.adapter.ts +126 -0
- package/src/server/claude-pty-mcp/tools/grep.test.ts +62 -0
- package/src/server/claude-pty-mcp/tools/read.adapter.ts +58 -0
- package/src/server/claude-pty-mcp/tools/read.test.ts +62 -0
- package/src/server/claude-pty-mcp/tools/tool-callback-shim.ts +42 -0
- package/src/server/claude-pty-mcp/tools/webfetch.test.ts +81 -0
- package/src/server/claude-pty-mcp/tools/webfetch.ts +82 -0
- package/src/server/claude-pty-mcp/tools/websearch.test.ts +40 -0
- package/src/server/claude-pty-mcp/tools/websearch.ts +42 -0
- package/src/server/claude-pty-mcp/tools/write.adapter.ts +60 -0
- package/src/server/claude-pty-mcp/tools/write.test.ts +52 -0
- package/src/server/claude-pty-mcp/uploads.adapter.ts +98 -0
- package/src/server/claude-pty-mcp/uploads.ts +38 -0
- package/src/server/claude-turn.test.ts +176 -0
- package/src/server/cli-runtime.test.ts +456 -0
- package/src/server/cli-runtime.ts +374 -0
- package/src/server/cli-supervisor.ts +81 -0
- package/src/server/cli.ts +78 -0
- package/src/server/client-log-forwarder.test.ts +74 -0
- package/src/server/client-log-forwarder.ts +75 -0
- package/src/server/codex-app-server-protocol.ts +449 -0
- package/src/server/codex-app-server.test.ts +2990 -0
- package/src/server/codex-app-server.ts +1713 -0
- package/src/server/coordination-integration.test.ts +63 -0
- package/src/server/coordination-mcp.test.ts +149 -0
- package/src/server/coordination-mcp.ts +197 -0
- package/src/server/delegation-coordinator.test.ts +675 -0
- package/src/server/delegation-coordinator.ts +454 -0
- package/src/server/discovery.test.ts +211 -0
- package/src/server/discovery.ts +301 -0
- package/src/server/event-store-agent-config.test.ts +124 -0
- package/src/server/event-store-coordination.test.ts +149 -0
- package/src/server/event-store-profile.test.ts +132 -0
- package/src/server/event-store-repo.test.ts +154 -0
- package/src/server/event-store-runner-team.test.ts +104 -0
- package/src/server/event-store.test.ts +342 -0
- package/src/server/event-store.ts +2208 -0
- package/src/server/events.ts +379 -0
- package/src/server/extension-router.test.ts +183 -0
- package/src/server/extension-router.ts +114 -0
- package/src/server/extensions/agents/server.test.ts +191 -0
- package/src/server/extensions/agents/server.ts +108 -0
- package/src/server/extensions/c3/server.test.ts +284 -0
- package/src/server/extensions/c3/server.ts +212 -0
- package/src/server/extensions/code/server.test.ts +200 -0
- package/src/server/extensions/code/server.ts +150 -0
- package/src/server/extensions.config.ts +10 -0
- package/src/server/external-open.ts +69 -0
- package/src/server/generate-fork-context.ts +58 -0
- package/src/server/generate-merge-context.test.ts +290 -0
- package/src/server/generate-merge-context.ts +141 -0
- package/src/server/generate-title.ts +36 -0
- package/src/server/git-clone-policy.test.ts +138 -0
- package/src/server/git-clone-policy.ts +27 -0
- package/src/server/harness-types.ts +1 -0
- package/src/server/journey-verification.test.ts +640 -0
- package/src/server/journey-verification.ts +195 -0
- package/src/server/machine-name.ts +22 -0
- package/src/server/nats-auth.test.ts +92 -0
- package/src/server/nats-auth.ts +6 -0
- package/src/server/nats-bind-guard.test.ts +71 -0
- package/src/server/nats-bind-guard.ts +42 -0
- package/src/server/nats-bridge.test.ts +141 -0
- package/src/server/nats-bridge.ts +111 -0
- package/src/server/nats-connector.test.ts +56 -0
- package/src/server/nats-connector.ts +71 -0
- package/src/server/nats-daemon-manager.test.ts +76 -0
- package/src/server/nats-daemon-manager.ts +174 -0
- package/src/server/nats-publisher.test.ts +356 -0
- package/src/server/nats-publisher.ts +271 -0
- package/src/server/nats-responders.test.ts +1018 -0
- package/src/server/nats-responders.ts +925 -0
- package/src/server/nats-streams.test.ts +112 -0
- package/src/server/nats-streams.ts +129 -0
- package/src/server/oauth-pool/oauth-responders.ts +185 -0
- package/src/server/oauth-pool/oauth-settings-store.ts +173 -0
- package/src/server/oauth-pool/oauth-token-pool.ts +303 -0
- package/src/server/orchestration.test.ts +1063 -0
- package/src/server/orchestration.ts +716 -0
- package/src/server/pairing-endpoints.test.ts +171 -0
- package/src/server/pairing-store.test.ts +154 -0
- package/src/server/pairing-store.ts +124 -0
- package/src/server/paths.ts +27 -0
- package/src/server/pr3-liveness.test.ts +252 -0
- package/src/server/process-utils.ts +10 -0
- package/src/server/project-cli.ts +180 -0
- package/src/server/provider-catalog.test.ts +177 -0
- package/src/server/provider-catalog.ts +146 -0
- package/src/server/pty-responders.ts +345 -0
- package/src/server/push-notifications.test.ts +234 -0
- package/src/server/push-notifications.ts +188 -0
- package/src/server/quick-response.test.ts +196 -0
- package/src/server/quick-response.ts +154 -0
- package/src/server/read-models-agent-config.test.ts +59 -0
- package/src/server/read-models-coordination.test.ts +69 -0
- package/src/server/read-models.test.ts +332 -0
- package/src/server/read-models.ts +258 -0
- package/src/server/repo-journey.test.ts +96 -0
- package/src/server/repo-manager.test.ts +118 -0
- package/src/server/repo-manager.ts +97 -0
- package/src/server/repo-status.test.ts +54 -0
- package/src/server/repo-status.ts +82 -0
- package/src/server/restart.test.ts +27 -0
- package/src/server/restart.ts +30 -0
- package/src/server/runner-incompatible-gate.test.ts +383 -0
- package/src/server/runner-manager.test.ts +72 -0
- package/src/server/runner-manager.ts +312 -0
- package/src/server/runner-pairing-urls.test.ts +59 -0
- package/src/server/runner-pairing-urls.ts +67 -0
- package/src/server/runner-proxy.test.ts +456 -0
- package/src/server/runner-proxy.ts +494 -0
- package/src/server/runner-router.test.ts +429 -0
- package/src/server/runner-router.ts +212 -0
- package/src/server/runner-routing.test.ts +584 -0
- package/src/server/runtime-registry.test.ts +436 -0
- package/src/server/runtime-registry.ts +307 -0
- package/src/server/sandbox-health.test.ts +127 -0
- package/src/server/sandbox-health.ts +94 -0
- package/src/server/sandbox-journey.test.ts +232 -0
- package/src/server/sandbox-manager.test.ts +146 -0
- package/src/server/sandbox-manager.ts +159 -0
- package/src/server/server.test.ts +287 -0
- package/src/server/server.ts +1108 -0
- package/src/server/session-discovery.test.ts +129 -0
- package/src/server/session-discovery.ts +475 -0
- package/src/server/session-index.test.ts +362 -0
- package/src/server/session-index.ts +119 -0
- package/src/server/session-seed.ts +288 -0
- package/src/server/share.test.ts +108 -0
- package/src/server/share.ts +113 -0
- package/src/server/skill-discovery.test.ts +201 -0
- package/src/server/skill-discovery.ts +77 -0
- package/src/server/storage/test-helpers.ts +67 -0
- package/src/server/terminal-manager.test.ts +309 -0
- package/src/server/terminal-manager.ts +354 -0
- package/src/server/transcript-consumer.test.ts +339 -0
- package/src/server/transcript-consumer.ts +162 -0
- package/src/server/transcript-search.test.ts +193 -0
- package/src/server/transcript-search.ts +83 -0
- package/src/server/transcript-utils.ts +52 -0
- package/src/server/update-manager.test.ts +107 -0
- package/src/server/update-manager.ts +230 -0
- package/src/server/workflow-engine.test.ts +251 -0
- package/src/server/workflow-engine.ts +169 -0
- package/src/server/workflow-mcp.ts +49 -0
- package/src/server/workflow-store.test.ts +155 -0
- package/src/server/workflow-store.ts +139 -0
- package/src/server/workspace-agent-integration.test.ts +167 -0
- package/src/server/workspace-agent-routes.test.ts +127 -0
- package/src/server/workspace-agent-routes.ts +89 -0
- package/src/server/workspace-agent.test.ts +103 -0
- package/src/server/workspace-agent.ts +102 -0
- package/src/server/workspace-cli.test.ts +79 -0
- package/src/server/workspace-config-manager.test.ts +109 -0
- package/src/server/workspace-config-manager.ts +83 -0
- package/src/server/workspace-directory-policy.test.ts +109 -0
- package/src/server/workspace-directory-policy.ts +56 -0
- package/src/shared/agent-config-types.ts +25 -0
- package/src/shared/branding.test.ts +42 -0
- package/src/shared/branding.ts +54 -0
- package/src/shared/compression.test.ts +85 -0
- package/src/shared/compression.ts +42 -0
- package/src/shared/coordination-store.test.ts +24 -0
- package/src/shared/coordination-store.ts +26 -0
- package/src/shared/dev-ports.test.ts +84 -0
- package/src/shared/dev-ports.ts +100 -0
- package/src/shared/extension-types.ts +45 -0
- package/src/shared/fork-presets.ts +54 -0
- package/src/shared/harness-types.test.ts +15 -0
- package/src/shared/harness-types.ts +21 -0
- package/src/shared/log-sink.test.ts +112 -0
- package/src/shared/log-sink.ts +185 -0
- package/src/shared/mention-pattern.ts +7 -0
- package/src/shared/merge-presets.ts +41 -0
- package/src/shared/nats-subjects.test.ts +61 -0
- package/src/shared/nats-subjects.ts +131 -0
- package/src/shared/permission-policy.ts +136 -0
- package/src/shared/ports.ts +3 -0
- package/src/shared/preset-types.ts +15 -0
- package/src/shared/profile-types.ts +49 -0
- package/src/shared/projectFileUrl.ts +36 -0
- package/src/shared/protocol.ts +153 -0
- package/src/shared/pty-instance.ts +43 -0
- package/src/shared/puggy/diagnostics/result.ts +18 -0
- package/src/shared/puggy/expressions/evaluate.ts +292 -0
- package/src/shared/puggy/index.test.ts +101 -0
- package/src/shared/puggy/index.ts +69 -0
- package/src/shared/puggy/parser/ast.ts +110 -0
- package/src/shared/puggy/parser/parser.ts +624 -0
- package/src/shared/puggy/renderer/html.ts +447 -0
- package/src/shared/runner-protocol.test.ts +277 -0
- package/src/shared/runner-protocol.ts +210 -0
- package/src/shared/runner-team-types.ts +73 -0
- package/src/shared/runtime-types.ts +48 -0
- package/src/shared/sandbox-types.ts +53 -0
- package/src/shared/tailwind-build.test.ts +12 -0
- package/src/shared/tinkaria-system-prompt.ts +101 -0
- package/src/shared/tools.test.ts +335 -0
- package/src/shared/tools.ts +397 -0
- package/src/shared/transcript-entries.ts +27 -0
- package/src/shared/transcript-render.test.ts +225 -0
- package/src/shared/transcript-render.ts +467 -0
- package/src/shared/types.ts +1031 -0
- package/src/shared/vite-config.test.ts +47 -0
- package/src/shared/web-context.test.ts +110 -0
- package/src/shared/web-context.ts +76 -0
- package/src/shared/workflow-types.ts +51 -0
- package/src/shared/workspace-types.ts +100 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test"
|
|
2
|
+
import {
|
|
3
|
+
APP_NAME,
|
|
4
|
+
CLI_COMMAND,
|
|
5
|
+
LOG_PREFIX,
|
|
6
|
+
PACKAGE_NAME,
|
|
7
|
+
RUNTIME_PROFILE_ENV_VAR,
|
|
8
|
+
SDK_CLIENT_APP,
|
|
9
|
+
getDataDir,
|
|
10
|
+
getDataDirDisplay,
|
|
11
|
+
getDataRootName,
|
|
12
|
+
getCliInvocation,
|
|
13
|
+
getRuntimeProfile,
|
|
14
|
+
} from "./branding"
|
|
15
|
+
|
|
16
|
+
describe("runtime profile helpers", () => {
|
|
17
|
+
test("defaults to the prod profile when unset", () => {
|
|
18
|
+
expect(APP_NAME).toBe("Tinkaria")
|
|
19
|
+
expect(CLI_COMMAND).toBe("tinkaria")
|
|
20
|
+
expect(PACKAGE_NAME).toBe("tinkaria")
|
|
21
|
+
expect(LOG_PREFIX).toBe("[tinkaria]")
|
|
22
|
+
expect(SDK_CLIENT_APP).toStartWith("tinkaria/")
|
|
23
|
+
expect(getCliInvocation("--port 4000")).toBe("tinkaria --port 4000")
|
|
24
|
+
expect(getRuntimeProfile({})).toBe("prod")
|
|
25
|
+
expect(getDataRootName({})).toBe(".tinkaria")
|
|
26
|
+
expect(getDataDir("/tmp/home", {})).toBe("/tmp/home/.tinkaria/data")
|
|
27
|
+
expect(getDataDirDisplay({})).toBe("~/.tinkaria/data")
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
test("switches to dev paths for the dev profile", () => {
|
|
31
|
+
const env = { [RUNTIME_PROFILE_ENV_VAR]: "dev" }
|
|
32
|
+
|
|
33
|
+
expect(getRuntimeProfile(env)).toBe("dev")
|
|
34
|
+
expect(getDataRootName(env)).toBe(".tinkaria-dev")
|
|
35
|
+
expect(getDataDir("/tmp/home", env)).toBe("/tmp/home/.tinkaria-dev/data")
|
|
36
|
+
expect(getDataDirDisplay(env)).toBe("~/.tinkaria-dev/data")
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
test("still honors the legacy runtime profile environment variable for compatibility", () => {
|
|
40
|
+
expect(getRuntimeProfile({ KANNA_RUNTIME_PROFILE: "dev" })).toBe("dev")
|
|
41
|
+
})
|
|
42
|
+
})
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export const APP_NAME = "Tinkaria"
|
|
2
|
+
export const CLI_COMMAND = "tinkaria"
|
|
3
|
+
export const DATA_ROOT_NAME = ".tinkaria"
|
|
4
|
+
export const DEV_DATA_ROOT_NAME = ".tinkaria-dev"
|
|
5
|
+
export const PACKAGE_NAME = "tinkaria"
|
|
6
|
+
export const RUNTIME_PROFILE_ENV_VAR = "TINKARIA_RUNTIME_PROFILE"
|
|
7
|
+
export const LEGACY_RUNTIME_PROFILE_ENV_VAR = "KANNA_RUNTIME_PROFILE"
|
|
8
|
+
// Read version from package.json — JSON import works in both Bun and Vite
|
|
9
|
+
import pkg from "../../package.json"
|
|
10
|
+
export const SDK_CLIENT_APP = `tinkaria/${pkg.version}`
|
|
11
|
+
export const LOG_PREFIX = "[tinkaria]"
|
|
12
|
+
export const DEFAULT_NEW_PROJECT_ROOT = `~/${APP_NAME}`
|
|
13
|
+
|
|
14
|
+
export type RuntimeProfile = "dev" | "prod"
|
|
15
|
+
|
|
16
|
+
type RuntimeEnv = Record<string, string | undefined> | undefined
|
|
17
|
+
|
|
18
|
+
function getRuntimeEnv(): RuntimeEnv {
|
|
19
|
+
const candidate = globalThis as typeof globalThis & {
|
|
20
|
+
process?: {
|
|
21
|
+
env?: Record<string, string | undefined>
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return candidate.process?.env
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function getRuntimeProfile(env: RuntimeEnv = getRuntimeEnv()): RuntimeProfile {
|
|
28
|
+
const profile = env?.[RUNTIME_PROFILE_ENV_VAR] ?? env?.[LEGACY_RUNTIME_PROFILE_ENV_VAR]
|
|
29
|
+
return profile?.trim().toLowerCase() === "dev" ? "dev" : "prod"
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function getDataRootName(env: RuntimeEnv = getRuntimeEnv()) {
|
|
33
|
+
return getRuntimeProfile(env) === "dev" ? DEV_DATA_ROOT_NAME : DATA_ROOT_NAME
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function getDataRootDir(homeDir: string, env: RuntimeEnv = getRuntimeEnv()) {
|
|
37
|
+
return `${homeDir}/${getDataRootName(env)}`
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function getDataRootDirDisplay(env: RuntimeEnv = getRuntimeEnv()) {
|
|
41
|
+
return `~/${getDataRootName(env)}`
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function getDataDir(homeDir: string, env: RuntimeEnv = getRuntimeEnv()) {
|
|
45
|
+
return `${getDataRootDir(homeDir, env)}/data`
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function getDataDirDisplay(env: RuntimeEnv = getRuntimeEnv()) {
|
|
49
|
+
return `${getDataRootDirDisplay(env)}/data`
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function getCliInvocation(arg?: string) {
|
|
53
|
+
return arg ? `${CLI_COMMAND} ${arg}` : CLI_COMMAND
|
|
54
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { describe, test, expect } from "bun:test"
|
|
2
|
+
import { isGzipped, compressPayload, decompressPayload } from "./compression"
|
|
3
|
+
|
|
4
|
+
const encoder = new TextEncoder()
|
|
5
|
+
const decoder = new TextDecoder()
|
|
6
|
+
|
|
7
|
+
function makeJson(sizeHint: number): string {
|
|
8
|
+
const entry = { kind: "text", id: "msg-001", content: "x".repeat(200), timestamp: "2026-03-31T00:00:00Z" }
|
|
9
|
+
const entries: typeof entry[] = []
|
|
10
|
+
while (JSON.stringify(entries).length < sizeHint) {
|
|
11
|
+
entries.push({ ...entry, id: `msg-${entries.length}` })
|
|
12
|
+
}
|
|
13
|
+
return JSON.stringify(entries)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
describe("isGzipped", () => {
|
|
17
|
+
test("detects gzip magic bytes", () => {
|
|
18
|
+
expect(isGzipped(new Uint8Array([0x1f, 0x8b, 0x08]))).toBe(true)
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
test("rejects plain JSON", () => {
|
|
22
|
+
expect(isGzipped(encoder.encode('{"hello":"world"}'))).toBe(false)
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
test("rejects empty input", () => {
|
|
26
|
+
expect(isGzipped(new Uint8Array([]))).toBe(false)
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
test("rejects single-byte input", () => {
|
|
30
|
+
expect(isGzipped(new Uint8Array([0x1f]))).toBe(false)
|
|
31
|
+
})
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
describe("compressPayload", () => {
|
|
35
|
+
test("passes through small payloads unchanged", () => {
|
|
36
|
+
const small = encoder.encode('{"tiny":true}')
|
|
37
|
+
const result = compressPayload(small)
|
|
38
|
+
expect(result).toBe(small) // same reference — no copy
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
test("compresses payloads above 64 KB threshold", () => {
|
|
42
|
+
const largeJson = makeJson(100_000)
|
|
43
|
+
const raw = encoder.encode(largeJson)
|
|
44
|
+
expect(raw.length).toBeGreaterThan(65_536)
|
|
45
|
+
|
|
46
|
+
const compressed = compressPayload(raw)
|
|
47
|
+
expect(compressed.length).toBeLessThan(raw.length)
|
|
48
|
+
expect(isGzipped(compressed)).toBe(true)
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
test("compressed output is valid gzip that roundtrips", async () => {
|
|
52
|
+
const largeJson = makeJson(100_000)
|
|
53
|
+
const raw = encoder.encode(largeJson)
|
|
54
|
+
const compressed = compressPayload(raw)
|
|
55
|
+
|
|
56
|
+
const decompressed = await decompressPayload(compressed)
|
|
57
|
+
expect(decoder.decode(decompressed)).toBe(largeJson)
|
|
58
|
+
})
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
describe("decompressPayload", () => {
|
|
62
|
+
test("passes through non-gzipped data unchanged", async () => {
|
|
63
|
+
const plain = encoder.encode('{"hello":"world"}')
|
|
64
|
+
const result = await decompressPayload(plain)
|
|
65
|
+
expect(decoder.decode(result)).toBe('{"hello":"world"}')
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
test("decompresses gzipped data correctly", async () => {
|
|
69
|
+
const largeJson = makeJson(100_000)
|
|
70
|
+
const raw = encoder.encode(largeJson)
|
|
71
|
+
const compressed = compressPayload(raw)
|
|
72
|
+
|
|
73
|
+
const result = await decompressPayload(compressed)
|
|
74
|
+
expect(decoder.decode(result)).toBe(largeJson)
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
test("roundtrip: compressPayload -> decompressPayload", async () => {
|
|
78
|
+
const largeJson = makeJson(200_000)
|
|
79
|
+
const raw = encoder.encode(largeJson)
|
|
80
|
+
const compressed = compressPayload(raw)
|
|
81
|
+
const decompressed = await decompressPayload(compressed)
|
|
82
|
+
|
|
83
|
+
expect(decoder.decode(decompressed)).toBe(largeJson)
|
|
84
|
+
})
|
|
85
|
+
})
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transparent gzip compression for NATS payloads.
|
|
3
|
+
*
|
|
4
|
+
* Large chat snapshots exceed NATS max_payload (8 MB).
|
|
5
|
+
* JSON compresses 10-20x, raising the effective ceiling to ~80-160 MB.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const COMPRESS_THRESHOLD = 65_536
|
|
9
|
+
|
|
10
|
+
export function isGzipped(data: Uint8Array): boolean {
|
|
11
|
+
return data.length >= 2 && data[0] === 0x1f && data[1] === 0x8b
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// TS 5.8 widens Uint8Array to Uint8Array<ArrayBufferLike>, but Bun APIs require Uint8Array<ArrayBuffer>.
|
|
15
|
+
// TextEncoder.encode() always backs by ArrayBuffer, making the narrowing safe.
|
|
16
|
+
type BunBytes = Uint8Array<ArrayBuffer>
|
|
17
|
+
|
|
18
|
+
function toBunBytes(data: Uint8Array): BunBytes {
|
|
19
|
+
if (data.buffer instanceof ArrayBuffer) {
|
|
20
|
+
return new Uint8Array(data.buffer, data.byteOffset, data.byteLength)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return new Uint8Array(data.slice())
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function compressPayload(raw: Uint8Array): Uint8Array {
|
|
27
|
+
if (raw.length <= COMPRESS_THRESHOLD) return raw
|
|
28
|
+
return Bun.gzipSync(toBunBytes(raw), { level: 1 })
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export async function decompressPayload(data: Uint8Array): Promise<Uint8Array> {
|
|
32
|
+
if (!isGzipped(data)) return data
|
|
33
|
+
// Server (Bun): use synchronous gunzip — no stream overhead
|
|
34
|
+
if (typeof Bun !== "undefined") {
|
|
35
|
+
return Bun.gunzipSync(toBunBytes(data))
|
|
36
|
+
}
|
|
37
|
+
// Browser fallback: DecompressionStream
|
|
38
|
+
const ds = new DecompressionStream("gzip")
|
|
39
|
+
const writer = ds.writable.getWriter()
|
|
40
|
+
void writer.write(toBunBytes(data)).then(() => writer.close())
|
|
41
|
+
return new Uint8Array(await new Response(ds.readable).arrayBuffer())
|
|
42
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { describe, test, expect } from "bun:test"
|
|
2
|
+
import type { CoordinationStore } from "./coordination-store"
|
|
3
|
+
|
|
4
|
+
describe("CoordinationStore interface", () => {
|
|
5
|
+
test("type-checks against EventStore shape", () => {
|
|
6
|
+
// This is a compile-time test — if CoordinationStore is incompatible
|
|
7
|
+
// with EventStore's methods, tsc will fail.
|
|
8
|
+
const mockStore: CoordinationStore = {
|
|
9
|
+
state: { coordinationByWorkspace: new Map() },
|
|
10
|
+
addTodo: async () => {},
|
|
11
|
+
claimTodo: async () => {},
|
|
12
|
+
completeTodo: async () => {},
|
|
13
|
+
abandonTodo: async () => {},
|
|
14
|
+
createClaim: async () => {},
|
|
15
|
+
releaseClaim: async () => {},
|
|
16
|
+
createWorktree: async () => {},
|
|
17
|
+
assignWorktree: async () => {},
|
|
18
|
+
removeWorktree: async () => {},
|
|
19
|
+
setRule: async () => {},
|
|
20
|
+
removeRule: async () => {},
|
|
21
|
+
}
|
|
22
|
+
expect(mockStore).toBeDefined()
|
|
23
|
+
})
|
|
24
|
+
})
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { WorkspaceCoordinationState } from "../server/events"
|
|
2
|
+
import type { WorkspaceCoordinationSnapshot, TodoPriority } from "./workspace-types"
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Minimal interface for project coordination operations.
|
|
6
|
+
* Implemented by EventStore (server-side, in-process) and
|
|
7
|
+
* NatsCoordinationClient (runner-side, over NATS).
|
|
8
|
+
*/
|
|
9
|
+
export interface CoordinationStore {
|
|
10
|
+
state: {
|
|
11
|
+
coordinationByWorkspace: Map<string, WorkspaceCoordinationState>
|
|
12
|
+
}
|
|
13
|
+
addTodo(workspaceId: string, todoId: string, description: string, priority: TodoPriority, createdBy: string): Promise<void>
|
|
14
|
+
claimTodo(workspaceId: string, todoId: string, sessionId: string): Promise<void>
|
|
15
|
+
completeTodo(workspaceId: string, todoId: string, outputs: string[]): Promise<void>
|
|
16
|
+
abandonTodo(workspaceId: string, todoId: string): Promise<void>
|
|
17
|
+
createClaim(workspaceId: string, claimId: string, intent: string, files: string[], sessionId: string): Promise<void>
|
|
18
|
+
releaseClaim(workspaceId: string, claimId: string): Promise<void>
|
|
19
|
+
createWorktree(workspaceId: string, worktreeId: string, branch: string, baseBranch: string, path: string): Promise<void>
|
|
20
|
+
assignWorktree(workspaceId: string, worktreeId: string, sessionId: string): Promise<void>
|
|
21
|
+
removeWorktree(workspaceId: string, worktreeId: string): Promise<void>
|
|
22
|
+
setRule(workspaceId: string, ruleId: string, content: string, setBy: string): Promise<void>
|
|
23
|
+
removeRule(workspaceId: string, ruleId: string): Promise<void>
|
|
24
|
+
/** Optional: fetch a full coordination snapshot (used when state is not in-process). */
|
|
25
|
+
getSnapshot?(workspaceId: string): Promise<WorkspaceCoordinationSnapshot>
|
|
26
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test"
|
|
2
|
+
import {
|
|
3
|
+
DEFAULT_DEV_CLIENT_PORT,
|
|
4
|
+
getDefaultDevServerPort,
|
|
5
|
+
parseDevArgs,
|
|
6
|
+
resolveDevPorts,
|
|
7
|
+
stripPortArg,
|
|
8
|
+
} from "./dev-ports"
|
|
9
|
+
|
|
10
|
+
describe("getDefaultDevServerPort", () => {
|
|
11
|
+
test("derives the default backend port from the client port", () => {
|
|
12
|
+
expect(getDefaultDevServerPort()).toBe(DEFAULT_DEV_CLIENT_PORT + 1)
|
|
13
|
+
expect(getDefaultDevServerPort(4000)).toBe(4001)
|
|
14
|
+
})
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
describe("resolveDevPorts", () => {
|
|
18
|
+
test("uses default dev ports when no port override is provided", () => {
|
|
19
|
+
expect(resolveDevPorts([])).toEqual({
|
|
20
|
+
clientPort: DEFAULT_DEV_CLIENT_PORT,
|
|
21
|
+
serverPort: DEFAULT_DEV_CLIENT_PORT + 1,
|
|
22
|
+
})
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
test("treats --port as the client port and derives the backend port", () => {
|
|
26
|
+
expect(resolveDevPorts(["--remote", "--port", "4000"])).toEqual({
|
|
27
|
+
clientPort: 4000,
|
|
28
|
+
serverPort: 4001,
|
|
29
|
+
})
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
test("uses the last provided --port value", () => {
|
|
33
|
+
expect(resolveDevPorts(["--port", "4000", "--port", "4100"])).toEqual({
|
|
34
|
+
clientPort: 4100,
|
|
35
|
+
serverPort: 4101,
|
|
36
|
+
})
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
test("throws when --port is missing a value", () => {
|
|
40
|
+
expect(() => resolveDevPorts(["--port"])).toThrow("Missing value for --port")
|
|
41
|
+
expect(() => resolveDevPorts(["--port", "--remote"])).toThrow("Missing value for --port")
|
|
42
|
+
})
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
describe("stripPortArg", () => {
|
|
46
|
+
test("removes --port and its value while preserving other args", () => {
|
|
47
|
+
expect(stripPortArg(["--remote", "--port", "4000", "--host", "dev-box"])).toEqual([
|
|
48
|
+
"--remote",
|
|
49
|
+
"--host",
|
|
50
|
+
"dev-box",
|
|
51
|
+
])
|
|
52
|
+
})
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
describe("parseDevArgs", () => {
|
|
56
|
+
test("derives dev share options from the client port", () => {
|
|
57
|
+
expect(parseDevArgs(["--share", "--port", "3333"], "dev-machine")).toEqual({
|
|
58
|
+
clientPort: 3333,
|
|
59
|
+
serverPort: 3334,
|
|
60
|
+
share: true,
|
|
61
|
+
backendTargetHost: "127.0.0.1",
|
|
62
|
+
allowedHosts: true,
|
|
63
|
+
serverArgs: [],
|
|
64
|
+
})
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
test("rejects combining --share with --host or --remote", () => {
|
|
68
|
+
expect(() => parseDevArgs(["--share", "--host", "dev-box"], "dev-machine")).toThrow("--share cannot be used with --host")
|
|
69
|
+
expect(() => parseDevArgs(["--host", "dev-box", "--share"], "dev-machine")).toThrow("--share cannot be used with --host")
|
|
70
|
+
expect(() => parseDevArgs(["--share", "--remote"], "dev-machine")).toThrow("--share cannot be used with --remote")
|
|
71
|
+
expect(() => parseDevArgs(["--remote", "--share"], "dev-machine")).toThrow("--share cannot be used with --remote")
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
test("preserves existing remote host behavior when share is off", () => {
|
|
75
|
+
expect(parseDevArgs(["--remote", "--port", "3333"], "dev-machine")).toEqual({
|
|
76
|
+
clientPort: 3333,
|
|
77
|
+
serverPort: 3334,
|
|
78
|
+
share: false,
|
|
79
|
+
backendTargetHost: "127.0.0.1",
|
|
80
|
+
allowedHosts: true,
|
|
81
|
+
serverArgs: ["--remote"],
|
|
82
|
+
})
|
|
83
|
+
})
|
|
84
|
+
})
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
export const DEFAULT_DEV_CLIENT_PORT = 5174
|
|
2
|
+
|
|
3
|
+
export function getDefaultDevServerPort(clientPort = DEFAULT_DEV_CLIENT_PORT) {
|
|
4
|
+
return clientPort + 1
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface DevArgResolution {
|
|
8
|
+
clientPort: number
|
|
9
|
+
serverPort: number
|
|
10
|
+
share: boolean
|
|
11
|
+
backendTargetHost: string
|
|
12
|
+
allowedHosts: true | string[]
|
|
13
|
+
serverArgs: string[]
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function resolveDevPorts(args: string[]) {
|
|
17
|
+
let clientPort = DEFAULT_DEV_CLIENT_PORT
|
|
18
|
+
|
|
19
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
20
|
+
const arg = args[index]
|
|
21
|
+
if (arg !== "--port") continue
|
|
22
|
+
|
|
23
|
+
const next = args[index + 1]
|
|
24
|
+
if (!next || next.startsWith("-")) {
|
|
25
|
+
throw new Error("Missing value for --port")
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const parsed = Number(next)
|
|
29
|
+
if (!Number.isFinite(parsed)) throw new Error(`Invalid port: ${next}`)
|
|
30
|
+
clientPort = parsed
|
|
31
|
+
index += 1
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
clientPort,
|
|
36
|
+
serverPort: getDefaultDevServerPort(clientPort),
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function stripPortArg(args: string[]) {
|
|
41
|
+
const stripped: string[] = []
|
|
42
|
+
|
|
43
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
44
|
+
const arg = args[index]
|
|
45
|
+
if (arg === "--port") {
|
|
46
|
+
index += 1
|
|
47
|
+
continue
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
stripped.push(arg)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return stripped
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function parseDevArgs(args: string[], localHostname: string): DevArgResolution {
|
|
57
|
+
const { clientPort, serverPort } = resolveDevPorts(args)
|
|
58
|
+
const serverArgs = stripPortArg(args).filter((arg) => arg !== "--share")
|
|
59
|
+
let share = false
|
|
60
|
+
let sawHost = false
|
|
61
|
+
let sawRemote = false
|
|
62
|
+
let backendTargetHost = "127.0.0.1"
|
|
63
|
+
let allowAllHosts = false
|
|
64
|
+
const hosts = new Set<string>(["localhost", "127.0.0.1", "0.0.0.0", localHostname])
|
|
65
|
+
|
|
66
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
67
|
+
const arg = args[index]
|
|
68
|
+
if (arg === "--share") {
|
|
69
|
+
if (sawHost) throw new Error("--share cannot be used with --host")
|
|
70
|
+
if (sawRemote) throw new Error("--share cannot be used with --remote")
|
|
71
|
+
share = true
|
|
72
|
+
continue
|
|
73
|
+
}
|
|
74
|
+
if (arg === "--remote") {
|
|
75
|
+
if (share) throw new Error("--share cannot be used with --remote")
|
|
76
|
+
sawRemote = true
|
|
77
|
+
backendTargetHost = "127.0.0.1"
|
|
78
|
+
allowAllHosts = true
|
|
79
|
+
continue
|
|
80
|
+
}
|
|
81
|
+
if (arg !== "--host") continue
|
|
82
|
+
|
|
83
|
+
const next = args[index + 1]
|
|
84
|
+
if (!next || next.startsWith("-")) continue
|
|
85
|
+
if (share) throw new Error("--share cannot be used with --host")
|
|
86
|
+
sawHost = true
|
|
87
|
+
hosts.add(next)
|
|
88
|
+
backendTargetHost = next === "0.0.0.0" ? "127.0.0.1" : next
|
|
89
|
+
index += 1
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
clientPort,
|
|
94
|
+
serverPort,
|
|
95
|
+
share,
|
|
96
|
+
backendTargetHost,
|
|
97
|
+
allowedHosts: share || allowAllHosts ? true : [...hosts],
|
|
98
|
+
serverArgs,
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/** Extension manifest — shared metadata declaring identity and detection probes */
|
|
2
|
+
export interface ExtensionManifest {
|
|
3
|
+
id: string
|
|
4
|
+
name: string
|
|
5
|
+
icon: string
|
|
6
|
+
detect: string[]
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** A single route declared by a server extension */
|
|
10
|
+
export interface ExtensionRoute {
|
|
11
|
+
method: "GET" | "POST"
|
|
12
|
+
path: string
|
|
13
|
+
handler: (req: Request, params: Record<string, string>) => Promise<Response>
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Server-side extension — declares routes scoped to a project path */
|
|
17
|
+
export interface ServerExtension extends ExtensionManifest {
|
|
18
|
+
routes(ctx: { projectPath: string }): ExtensionRoute[]
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Props passed to every client extension component */
|
|
22
|
+
export interface ExtensionProps {
|
|
23
|
+
localPath: string
|
|
24
|
+
groupKey: string
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Result of filesystem probe detection */
|
|
28
|
+
export interface DetectionResult {
|
|
29
|
+
extensionId: string
|
|
30
|
+
name: string
|
|
31
|
+
icon: string
|
|
32
|
+
detected: boolean
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Persisted user preference for an extension (level 3 of the hierarchy) */
|
|
36
|
+
export interface ExtensionPreference {
|
|
37
|
+
extensionId: string
|
|
38
|
+
enabled: boolean
|
|
39
|
+
updatedAt: number
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Snapshot published to subscribers of extension-preferences topic */
|
|
43
|
+
export interface ExtensionPreferencesSnapshot {
|
|
44
|
+
preferences: ExtensionPreference[]
|
|
45
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { type PresetDefinition, getPreset } from "./preset-types"
|
|
2
|
+
|
|
3
|
+
export type ForkPresetDefinition = PresetDefinition
|
|
4
|
+
|
|
5
|
+
export const FORK_PRESETS: readonly ForkPresetDefinition[] = [
|
|
6
|
+
{
|
|
7
|
+
id: "implementation_branch",
|
|
8
|
+
label: "Implementation branch",
|
|
9
|
+
description: "Continue toward a concrete feature or code change.",
|
|
10
|
+
defaultIntent: "Continue this work as an implementation branch. Carry forward the essential technical context, note the main constraints, and focus the new session on the next concrete coding steps.",
|
|
11
|
+
generatorHint: "Bias toward an execution-ready brief with concrete next implementation steps.",
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
id: "alternative_approach",
|
|
15
|
+
label: "Alternative approach",
|
|
16
|
+
description: "Explore a different design or implementation path.",
|
|
17
|
+
defaultIntent: "Fork this into an alternative approach. Preserve only the key constraints and decisions from the current chat, then frame the new session around a distinctly different implementation strategy.",
|
|
18
|
+
generatorHint: "Emphasize the constraints and assumptions that still apply, but optimize for exploring a different solution path.",
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
id: "bug_investigation",
|
|
22
|
+
label: "Bug investigation",
|
|
23
|
+
description: "Turn the current state into a focused debugging branch.",
|
|
24
|
+
defaultIntent: "Fork this into a bug investigation. Extract the symptoms, likely causes, relevant files, and the strongest reproduction or verification steps so the new session can debug efficiently.",
|
|
25
|
+
generatorHint: "Prioritize symptoms, repro steps, affected surfaces, and likely fault boundaries.",
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
id: "cleanup_refactor",
|
|
29
|
+
label: "Cleanup / refactor",
|
|
30
|
+
description: "Narrow the work to code quality and simplification.",
|
|
31
|
+
defaultIntent: "Fork this into a cleanup and refactor pass. Keep the important behavioral constraints, identify the code areas most worth simplifying, and focus the new session on safer structural improvement.",
|
|
32
|
+
generatorHint: "Prioritize invariants, areas of complexity, and low-risk refactor opportunities.",
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
id: "tests",
|
|
36
|
+
label: "Write tests",
|
|
37
|
+
description: "Build a testing-focused branch from the current work.",
|
|
38
|
+
defaultIntent: "Fork this into a test-writing pass. Capture the intended behavior, risky edges, missing verification, and the best targets for regression or integration tests.",
|
|
39
|
+
generatorHint: "Emphasize expected behavior, regressions to guard against, and concrete verification targets.",
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
id: "docs_spec",
|
|
43
|
+
label: "Docs / spec",
|
|
44
|
+
description: "Extract the current work into a clearer brief or spec.",
|
|
45
|
+
defaultIntent: "Fork this into a docs or spec-writing session. Distill the relevant decisions, architecture, constraints, and open questions into a cleaner written brief for follow-up work.",
|
|
46
|
+
generatorHint: "Bias toward structured explanation, decisions, constraints, and unresolved questions.",
|
|
47
|
+
},
|
|
48
|
+
] as const
|
|
49
|
+
|
|
50
|
+
export const DEFAULT_FORK_PRESET_ID = FORK_PRESETS[0]!.id
|
|
51
|
+
|
|
52
|
+
export function getForkPreset(id?: string | null): ForkPresetDefinition | null {
|
|
53
|
+
return getPreset(FORK_PRESETS, id)
|
|
54
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { describe, test, expect } from "bun:test"
|
|
2
|
+
|
|
3
|
+
describe("shared harness-types", () => {
|
|
4
|
+
test("HarnessEvent type and HarnessTurn type are exportable from shared", async () => {
|
|
5
|
+
// Dynamic import to test module resolution
|
|
6
|
+
const mod = await import("./harness-types")
|
|
7
|
+
// Module should export these (even if type-only, the module must resolve)
|
|
8
|
+
expect(mod).toBeDefined()
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
test("server re-export still resolves", async () => {
|
|
12
|
+
const mod = await import("../server/harness-types")
|
|
13
|
+
expect(mod).toBeDefined()
|
|
14
|
+
})
|
|
15
|
+
})
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { AccountInfo, AgentProvider, NormalizedToolCall, TranscriptEntry } from "./types"
|
|
2
|
+
|
|
3
|
+
export interface HarnessEvent {
|
|
4
|
+
type: "transcript" | "session_token" | "rate_limit"
|
|
5
|
+
entry?: TranscriptEntry
|
|
6
|
+
sessionToken?: string
|
|
7
|
+
rateLimit?: { resetAt: number; tz: string }
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface HarnessToolRequest {
|
|
11
|
+
tool: NormalizedToolCall & { toolKind: "ask_user_question" | "exit_plan_mode" }
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface HarnessTurn {
|
|
15
|
+
provider: AgentProvider
|
|
16
|
+
stream: AsyncIterable<HarnessEvent>
|
|
17
|
+
getAccountInfo?: () => Promise<AccountInfo | null>
|
|
18
|
+
getContextUsage?: () => Promise<{ percentage: number; totalTokens: number; maxTokens: number } | null>
|
|
19
|
+
interrupt: () => Promise<void>
|
|
20
|
+
close: () => void
|
|
21
|
+
}
|