@iowarp/clio-coder 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -0
- package/README.md +50 -53
- package/dist/acp-FPR54DGL.js +138 -0
- package/dist/{agents-Q4MYPMUW.js → agents-OGPIHPJH.js} +33 -25
- package/dist/assets/codewiki.json +1 -0
- package/dist/assets/grammars/notices/@vscode__tree-sitter-wasm/LICENSE +21 -0
- package/dist/assets/grammars/notices/@vscode__tree-sitter-wasm/cgmanifest.json +16 -0
- package/dist/assets/grammars/notices/tree-sitter-wasms/LICENSE +24 -0
- package/dist/assets/grammars/tree-sitter-c-sharp.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-c.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-cpp.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-go.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-java.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-javascript.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-python.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-ruby.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-rust.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-tsx.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-typescript.wasm +0 -0
- package/dist/assets/grammars/tree-sitter.wasm +0 -0
- package/dist/{auth-O6HYIJ6J.js → auth-IC3K6NIZ.js} +22 -15
- package/dist/{chunk-KKKPTZLM.js → chunk-2STGEDFV.js} +8 -1
- package/dist/chunk-3I7MS7N2.js +40 -0
- package/dist/chunk-3R73A4XB.js +69 -0
- package/dist/{chunk-26BZQOAD.js → chunk-474KN5II.js} +86 -115
- package/dist/{chunk-NI4DEJMC.js → chunk-4QKXUHSR.js} +26 -3
- package/dist/{chunk-X3BR7HWV.js → chunk-5WIGXA4T.js} +7 -1
- package/dist/{chunk-TFSSEXL6.js → chunk-673JJUWJ.js} +14 -4
- package/dist/{chunk-GNGDQYDU.js → chunk-7SS2CTV2.js} +27922 -1249
- package/dist/{chunk-7RBKDI66.js → chunk-ASND7OZK.js} +104 -12
- package/dist/{chunk-X3NE4WVW.js → chunk-BNAZZHFG.js} +7 -1
- package/dist/{chunk-RQDWMVRB.js → chunk-BSU2YIWB.js} +9 -3
- package/dist/{chunk-CLJ5HLUD.js → chunk-C4PTHK7P.js} +24 -5
- package/dist/{chunk-QV47YRF4.js → chunk-CGKSTWHD.js} +7 -1
- package/dist/{chunk-BYEU76JP.js → chunk-DKGKUHFA.js} +34 -9
- package/dist/chunk-EYOKLTMF.js +170 -0
- package/dist/{chunk-PS4PFJQP.js → chunk-FCIH3BIZ.js} +15258 -14130
- package/dist/{chunk-2J63S4SF.js → chunk-FST4FYJB.js} +82 -14
- package/dist/{chunk-3DANZDGR.js → chunk-G34LV2PF.js} +34 -9
- package/dist/{chunk-BBUH4VAA.js → chunk-GAEBEQVI.js} +34 -21
- package/dist/chunk-GB6QRBXN.js +8543 -0
- package/dist/chunk-GEP36Y4X.js +12796 -0
- package/dist/{chunk-TKHQ4DGZ.js → chunk-H6F6BYOH.js} +496 -121
- package/dist/{chunk-UGYAX5YI.js → chunk-HQQID6OA.js} +10 -5
- package/dist/chunk-IHXBNWMM.js +137 -0
- package/dist/{chunk-ME6DNWIU.js → chunk-IS3ONKU3.js} +7 -1
- package/dist/{chunk-DXQNI4PC.js → chunk-IWHMRKLL.js} +8 -1
- package/dist/chunk-K2ITRMHZ.js +642 -0
- package/dist/{chunk-KBR4MZZR.js → chunk-K5XEMXTI.js} +7 -1
- package/dist/{chunk-AMFR5YA3.js → chunk-KKNLWXI6.js} +24 -10
- package/dist/{chunk-JWHCJDCI.js → chunk-KY56HMHH.js} +145 -61
- package/dist/{chunk-E3NYWENM.js → chunk-LU4TK2PR.js} +52 -7
- package/dist/{chunk-UWIJNAOB.js → chunk-M5T5VO65.js} +109 -42
- package/dist/{chunk-JPOWPFCU.js → chunk-MAR7Y6HW.js} +38 -16
- package/dist/chunk-N6F52NLF.js +6951 -0
- package/dist/{chunk-UHTSULZS.js → chunk-NMOX6HFD.js} +20 -7
- package/dist/{chunk-WD6AJM35.js → chunk-OLBBMFRD.js} +30 -13
- package/dist/{chunk-VOO7NYPP.js → chunk-PFEFKVGL.js} +22 -6
- package/dist/{chunk-6CWDTGUC.js → chunk-PIUMUEMV.js} +7 -1
- package/dist/chunk-PV4JUBVJ.js +462 -0
- package/dist/{chunk-527KG6XR.js → chunk-Q3RUPKEJ.js} +22 -4
- package/dist/{chunk-D5YD55AR.js → chunk-Q5WJOSJ7.js} +11 -1
- package/dist/{chunk-5N2FG33Q.js → chunk-R346GLFC.js} +7 -1
- package/dist/{chunk-4UQA7NCT.js → chunk-R5KLMSBV.js} +7 -2
- package/dist/{chunk-PIDUD6M2.js → chunk-RDLVBZEO.js} +11 -6
- package/dist/{chunk-O4EJEDHO.js → chunk-RPTR2H26.js} +40 -31
- package/dist/{chunk-HBU5MTAM.js → chunk-SVNXH4L2.js} +7 -1
- package/dist/{chunk-XNISANGE.js → chunk-TEKV33Q5.js} +122 -57
- package/dist/chunk-TXOTCRLG.js +15 -0
- package/dist/{chunk-VPAWTYLY.js → chunk-WEPFGWHJ.js} +7 -1
- package/dist/{chunk-HMYNFFY4.js → chunk-XPLRXC72.js} +7 -2
- package/dist/{chunk-UU3R62TT.js → chunk-XYWBQRDM.js} +13 -4
- package/dist/{chunk-7BHLZB3A.js → chunk-ZPY3JZ5E.js} +32 -10
- package/dist/cli/index.js +39 -33
- package/dist/clio-BZVGEUFJ.js +58 -0
- package/dist/{components-JVHMUBEB.js → components-DMAOEKFB.js} +26 -9
- package/dist/{config-ZFCDBMDC.js → config-IRUQ7SE4.js} +42 -31
- package/dist/configure-S7S6F6CL.js +32 -0
- package/dist/{context-CDXTP2MP.js → context-3KWFLHJG.js} +17 -11
- package/dist/{context-E3KIFVXI.js → context-5RADCKTR.js} +33 -28
- package/dist/{context-clear-3F4PLXOS.js → context-clear-7TSNPAAI.js} +36 -28
- package/dist/{context-index-Q7YSYTR3.js → context-index-W4RLWOQH.js} +10 -4
- package/dist/{docs-YIETIWZI.js → docs-5AWSPS37.js} +16 -10
- package/dist/doctor-UC5NAJYQ.js +77 -0
- package/dist/{eval-B3KZZESM.js → eval-U6TJHRLX.js} +77 -24
- package/dist/{evidence-V67CHM35.js → evidence-YEGUW4L3.js} +34 -26
- package/dist/{evolve-YDZSUQYA.js → evolve-TXARCTPG.js} +39 -26
- package/dist/{extensions-SRG7XCAH.js → extensions-OZFJ3A3G.js} +13 -7
- package/dist/{fleet-CA2CRTVG.js → fleet-6G3DHNYE.js} +45 -37
- package/dist/fleet-preflight-DSNT37JK.js +23 -0
- package/dist/{init-2OZDJE2D.js → init-KZ5QTF6M.js} +42 -34
- package/dist/{memory-3PIQQAKX.js → memory-73ESV5YC.js} +35 -27
- package/dist/{models-DY35XI7Y.js → models-A4PVNWJK.js} +34 -23
- package/dist/{paths-5OMXW7Z4.js → paths-C4H6IV77.js} +12 -6
- package/dist/preload-6WVMHX3A.js +13 -0
- package/dist/{reset-PIFYNOS3.js → reset-BGW6OGMV.js} +17 -11
- package/dist/{run-3VSPP24F.js → run-YTPEYQOH.js} +60 -48
- package/dist/{share-D36RQCXM.js → share-YIFFV4NQ.js} +16 -10
- package/dist/{skills-F2MRLELY.js → skills-2V6RA3OQ.js} +18 -11
- package/dist/{skills-eval-E2ZTW4PL.js → skills-eval-S2TVJO4F.js} +45 -36
- package/dist/{targets-DZMEZAH4.js → targets-TYXLPB23.js} +61 -59
- package/dist/{trace-7NYCUI2J.js → trace-GGOJ6Q6Z.js} +9 -3
- package/dist/{uninstall-AD3JWHBB.js → uninstall-LLLT4F4W.js} +14 -8
- package/dist/{upgrade-WYYBKGDY.js → upgrade-33G2LMM5.js} +45 -23
- package/dist/{usage-ULIDAGFF.js → usage-ZAFSXKKG.js} +35 -27
- package/dist/version-KGEG7EPO.js +21 -0
- package/dist/{wiki-generate-PKFIX6OB.js → wiki-generate-NUQCVOQ3.js} +55 -45
- package/dist/worker/entry.js +101 -43
- package/docs/README.md +12 -9
- package/docs/acp.md +28 -5
- package/docs/alcf-provider.md +1 -1
- package/docs/architecture.md +23 -2
- package/docs/artifact-placement.md +101 -0
- package/docs/artifact-versions.md +1 -1
- package/docs/built-in-agents.md +4 -2
- package/docs/capacity-and-scheduling.md +1 -1
- package/docs/commands-and-modes.md +125 -41
- package/docs/configuration-and-targets.md +88 -18
- package/docs/context-engine.md +6 -2
- package/docs/development-pipeline.md +77 -0
- package/docs/documentation-coverage.md +4 -4
- package/docs/documentation-guide.md +3 -3
- package/docs/environment-variables.md +2 -1
- package/docs/eval-runner.md +3 -3
- package/docs/evals-internal.md +2 -2
- package/docs/evidence-and-memory.md +6 -2
- package/docs/evolution.md +1 -1
- package/docs/exit-codes-and-output.md +1 -1
- package/docs/extensions-and-sharing.md +18 -11
- package/docs/fleet-demo-runbook.md +22 -23
- package/docs/fleet-dispatch.md +111 -12
- package/docs/glossary.md +107 -15
- package/docs/html/agents_blueprint.html +3 -3
- package/docs/html/alcf_blueprint.html +3 -3
- package/docs/html/architecture_blueprint.html +3 -3
- package/docs/html/commands_blueprint.html +187 -42
- package/docs/html/configuration_blueprint.html +7 -7
- package/docs/html/context_blueprint.html +3 -3
- package/docs/html/documentation_blueprint.html +1 -1
- package/docs/html/environment_blueprint.html +3 -3
- package/docs/html/eval_blueprint.html +4 -4
- package/docs/html/evals_internal_blueprint.html +3 -3
- package/docs/html/evolution_blueprint.html +3 -3
- package/docs/html/extensions_blueprint.html +3 -3
- package/docs/html/fleet_dispatch_blueprint.html +8 -8
- package/docs/html/index.html +5 -5
- package/docs/html/lifecycle_blueprint.html +4 -4
- package/docs/html/memory_blueprint.html +3 -3
- package/docs/html/middleware_blueprint.html +3 -3
- package/docs/html/models_blueprint.html +2 -2
- package/docs/html/observability_blueprint.html +2 -2
- package/docs/html/provider_adapter_blueprint.html +3 -3
- package/docs/html/safety_blueprint.html +3 -3
- package/docs/html/skills_blueprint.html +2 -2
- package/docs/html/soak_blueprint.html +3 -3
- package/docs/html/tool_usage_blueprint.html +4 -4
- package/docs/html/tools_blueprint.html +2 -2
- package/docs/html/trace_blueprint.html +3 -3
- package/docs/html/tui_design_blueprint.html +100 -40
- package/docs/html/validation_blueprint.html +1 -1
- package/docs/html/worker_dispatch_blueprint.html +3 -3
- package/docs/installation-and-lifecycle.md +62 -11
- package/docs/middleware-and-components.md +1 -1
- package/docs/model-catalog.md +2 -2
- package/docs/observability.md +3 -3
- package/docs/proactive-memory.md +12 -12
- package/docs/prompt-envelope-and-tools.md +2 -2
- package/docs/provider-adapter-cookbook.md +1 -1
- package/docs/release-cut-checklist.md +4 -0
- package/docs/safety-model.md +21 -5
- package/docs/scientific-validation.md +3 -3
- package/docs/session-lifecycle.md +2 -2
- package/docs/skills-marketplace.md +1 -1
- package/docs/time-conventions.md +101 -0
- package/docs/tool-usage.md +5 -4
- package/docs/trace-store.md +1 -1
- package/docs/troubleshooting.md +1 -1
- package/docs/tui-design.md +83 -27
- package/docs/worker-dispatch-mechanics.md +3 -3
- package/package.json +16 -16
- package/skills/README.md +5 -6
- package/skills/git/file-ticket/SKILL.md +107 -0
- package/skills/git/file-ticket/evals.md +54 -0
- package/skills/git/fix-issue/SKILL.md +106 -0
- package/skills/git/fix-issue/evals.md +71 -0
- package/skills/git/ship/SKILL.md +92 -0
- package/skills/git/ship/evals.md +72 -0
- package/skills/skill-marketplace.json +12 -20
- package/src/cli/acp.ts +88 -0
- package/src/cli/agents.ts +60 -0
- package/src/cli/args.ts +280 -0
- package/src/cli/argv.ts +170 -0
- package/src/cli/ask.ts +34 -0
- package/src/cli/auth.ts +468 -0
- package/src/cli/bootstrap-generate.ts +498 -0
- package/src/cli/clio.ts +34 -0
- package/src/cli/components.ts +195 -0
- package/src/cli/config-inspect.ts +330 -0
- package/src/cli/config.ts +72 -0
- package/src/cli/configure-interop.ts +67 -0
- package/src/cli/configure-layout.ts +172 -0
- package/src/cli/configure.ts +1487 -0
- package/src/cli/context-clear.ts +76 -0
- package/src/cli/context-index.ts +102 -0
- package/src/cli/context.ts +316 -0
- package/src/cli/default-target.ts +63 -0
- package/src/cli/docs.ts +340 -0
- package/src/cli/doctor.ts +54 -0
- package/src/cli/eval.ts +315 -0
- package/src/cli/evidence.ts +222 -0
- package/src/cli/evolve.ts +219 -0
- package/src/cli/extensions.ts +205 -0
- package/src/cli/fleet.ts +827 -0
- package/src/cli/index.ts +309 -0
- package/src/cli/init.ts +219 -0
- package/src/cli/initial-message.ts +47 -0
- package/src/cli/internal-dispatch.ts +55 -0
- package/src/cli/memory.ts +180 -0
- package/src/cli/models.ts +257 -0
- package/src/cli/modes/json-stream.ts +85 -0
- package/src/cli/modes/jsonl.ts +9 -0
- package/src/cli/modes/print.ts +589 -0
- package/src/cli/oauth-manual-input.ts +72 -0
- package/src/cli/oauth-select.ts +36 -0
- package/src/cli/output-guard.ts +48 -0
- package/src/cli/paths.ts +44 -0
- package/src/cli/provider-target.ts +113 -0
- package/src/cli/removal.ts +72 -0
- package/src/cli/reset.ts +253 -0
- package/src/cli/run.ts +497 -0
- package/src/cli/share.ts +243 -0
- package/src/cli/shared.ts +60 -0
- package/src/cli/skills-eval.ts +1225 -0
- package/src/cli/skills.ts +470 -0
- package/src/cli/steer-channel.ts +86 -0
- package/src/cli/targets.ts +1150 -0
- package/src/cli/text-layout.ts +102 -0
- package/src/cli/trace.ts +274 -0
- package/src/cli/uninstall.ts +405 -0
- package/src/cli/upgrade.ts +270 -0
- package/src/cli/usage.ts +869 -0
- package/src/cli/validate-model.ts +28 -0
- package/src/cli/version.ts +7 -0
- package/src/cli/wiki-generate.ts +509 -0
- package/src/core/artifact-paths.ts +43 -0
- package/src/core/bash-exec.ts +242 -0
- package/src/core/boot-trace.ts +37 -0
- package/src/core/bus-events.ts +728 -0
- package/src/core/bus-trace.ts +53 -0
- package/src/core/c-header-language.ts +265 -0
- package/src/core/clio-repo.ts +78 -0
- package/src/core/config.ts +1593 -0
- package/src/core/context-floor.ts +33 -0
- package/src/core/defaults.ts +625 -0
- package/src/core/domain-loader.ts +170 -0
- package/src/core/event-bus.ts +94 -0
- package/src/core/file-references.ts +282 -0
- package/src/core/guardrails.ts +185 -0
- package/src/core/headless-permission.ts +21 -0
- package/src/core/init.ts +223 -0
- package/src/core/json-payload.ts +58 -0
- package/src/core/package-root.ts +54 -0
- package/src/core/path-canonical.ts +37 -0
- package/src/core/process-identity.ts +41 -0
- package/src/core/recent-models.ts +91 -0
- package/src/core/release.ts +2 -0
- package/src/core/residency-protection.ts +56 -0
- package/src/core/resolve-config-value.ts +88 -0
- package/src/core/response-schema.ts +279 -0
- package/src/core/run-overrides.ts +77 -0
- package/src/core/safe-exec.ts +193 -0
- package/src/core/safe-id.ts +37 -0
- package/src/core/safe-resource-write.ts +162 -0
- package/src/core/session-routing.ts +339 -0
- package/src/core/settings-layers.ts +220 -0
- package/src/core/shared-bus.ts +8 -0
- package/src/core/shell-quote.ts +26 -0
- package/src/core/skill-activation.ts +190 -0
- package/src/core/startup-timer.ts +37 -0
- package/src/core/state-file-lock.ts +207 -0
- package/src/core/termination.ts +202 -0
- package/src/core/timers.ts +38 -0
- package/src/core/tool-names.ts +65 -0
- package/src/core/verification-scripts.ts +13 -0
- package/src/core/workspace-files.ts +492 -0
- package/src/core/xdg.ts +177 -0
- package/src/domains/agents/builtins/architect.md +4 -4
- package/src/domains/agents/builtins/coder.md +3 -2
- package/src/domains/agents/builtins/debugger.md +1 -1
- package/src/domains/agents/builtins/documenter.md +1 -1
- package/src/domains/agents/builtins/git-master.md +3 -3
- package/src/domains/agents/builtins/provenance.md +1 -1
- package/src/domains/agents/builtins/researcher.md +1 -1
- package/src/domains/agents/builtins/scout.md +1 -1
- package/src/domains/agents/builtins/tester.md +1 -1
- package/src/domains/agents/builtins/verifier.md +1 -1
- package/src/domains/agents/builtins/wiki-writer.md +1 -1
- package/src/domains/agents/catalog.ts +172 -0
- package/src/domains/agents/contract.ts +16 -0
- package/src/domains/agents/extension.ts +110 -0
- package/src/domains/agents/fleet-commands.ts +154 -0
- package/src/domains/agents/fleet-contract.ts +797 -0
- package/src/domains/agents/frontmatter.ts +40 -0
- package/src/domains/agents/index.ts +102 -0
- package/src/domains/agents/manifest.ts +6 -0
- package/src/domains/agents/recipe-schema.ts +202 -0
- package/src/domains/agents/recipe.ts +125 -0
- package/src/domains/agents/registry.ts +111 -0
- package/src/domains/agents/result-contract.ts +1265 -0
- package/src/domains/agents/spec.ts +371 -0
- package/src/domains/agents/write-boundary.ts +109 -0
- package/src/domains/components/diff.ts +99 -0
- package/src/domains/components/hash.ts +21 -0
- package/src/domains/components/index.ts +3 -0
- package/src/domains/components/scan.ts +304 -0
- package/src/domains/components/snapshot.ts +108 -0
- package/src/domains/components/types.ts +82 -0
- package/src/domains/config/agent-namespace.ts +13 -0
- package/src/domains/config/classify.ts +94 -0
- package/src/domains/config/contract.ts +22 -0
- package/src/domains/config/extension.ts +136 -0
- package/src/domains/config/index.ts +13 -0
- package/src/domains/config/keybindings.ts +164 -0
- package/src/domains/config/manifest.ts +6 -0
- package/src/domains/config/watcher.ts +41 -0
- package/src/domains/context/adoption.ts +880 -0
- package/src/domains/context/bootstrap-prompt.ts +273 -0
- package/src/domains/context/bootstrap.ts +1409 -0
- package/src/domains/context/clear.ts +86 -0
- package/src/domains/context/clio-md.ts +327 -0
- package/src/domains/context/codewiki/cmake.ts +356 -0
- package/src/domains/context/codewiki/cooperative.ts +46 -0
- package/src/domains/context/codewiki/digest.ts +135 -0
- package/src/domains/context/codewiki/grammar-assets.ts +33 -0
- package/src/domains/context/codewiki/indexer.ts +1614 -0
- package/src/domains/context/codewiki/tree-sitter.ts +771 -0
- package/src/domains/context/contract.ts +62 -0
- package/src/domains/context/excluded-dirs.ts +1 -0
- package/src/domains/context/extension.ts +407 -0
- package/src/domains/context/fingerprint.ts +196 -0
- package/src/domains/context/index.ts +164 -0
- package/src/domains/context/init-options.ts +69 -0
- package/src/domains/context/manifest.ts +6 -0
- package/src/domains/context/operator-profile.ts +157 -0
- package/src/domains/context/project-metadata.ts +510 -0
- package/src/domains/context/project-rules.ts +227 -0
- package/src/domains/context/prompt-context.ts +62 -0
- package/src/domains/context/refresh.ts +170 -0
- package/src/domains/context/sibling-files.ts +10 -0
- package/src/domains/context/state.ts +237 -0
- package/src/domains/context/wiki/assemble.ts +303 -0
- package/src/domains/context/wiki/frontmatter.ts +210 -0
- package/src/domains/context/wiki/generate.ts +590 -0
- package/src/domains/context/wiki/layout.ts +111 -0
- package/src/domains/context/wiki/meta.ts +221 -0
- package/src/domains/context/wiki/plan-store.ts +217 -0
- package/src/domains/context/wiki/plan.ts +250 -0
- package/src/domains/context/wiki/prompts.ts +270 -0
- package/src/domains/context/wiki/staleness.ts +198 -0
- package/src/domains/dispatch/active-route-planner.ts +168 -0
- package/src/domains/dispatch/admission-queue.ts +150 -0
- package/src/domains/dispatch/admission.ts +334 -0
- package/src/domains/dispatch/agent-candidates.ts +307 -0
- package/src/domains/dispatch/agent-ledger-hub.ts +71 -0
- package/src/domains/dispatch/agent-ledger-store.ts +257 -0
- package/src/domains/dispatch/agent-ledger.ts +212 -0
- package/src/domains/dispatch/agent-plan-adapter.ts +85 -0
- package/src/domains/dispatch/assignment-events.ts +132 -0
- package/src/domains/dispatch/assignment-reconcile.ts +76 -0
- package/src/domains/dispatch/assignment-store.ts +162 -0
- package/src/domains/dispatch/assignment.ts +278 -0
- package/src/domains/dispatch/backoff.ts +59 -0
- package/src/domains/dispatch/batch-store.ts +134 -0
- package/src/domains/dispatch/batch-tracker.ts +66 -0
- package/src/domains/dispatch/capability-match.ts +155 -0
- package/src/domains/dispatch/capacity-lease.ts +413 -0
- package/src/domains/dispatch/code-step-store.ts +52 -0
- package/src/domains/dispatch/code-step.ts +368 -0
- package/src/domains/dispatch/contract.ts +278 -0
- package/src/domains/dispatch/dedup.ts +133 -0
- package/src/domains/dispatch/event-pump.ts +251 -0
- package/src/domains/dispatch/execution-handoff.ts +29 -0
- package/src/domains/dispatch/execution-plan.ts +328 -0
- package/src/domains/dispatch/execution-role.ts +277 -0
- package/src/domains/dispatch/execution-scheduler.ts +583 -0
- package/src/domains/dispatch/extension.ts +5869 -0
- package/src/domains/dispatch/failure-classification.ts +141 -0
- package/src/domains/dispatch/fleet-plan.ts +225 -0
- package/src/domains/dispatch/fleet-preflight.ts +394 -0
- package/src/domains/dispatch/gate-decisions.ts +1040 -0
- package/src/domains/dispatch/gate-role-prompts.ts +58 -0
- package/src/domains/dispatch/heartbeat.ts +27 -0
- package/src/domains/dispatch/index.ts +137 -0
- package/src/domains/dispatch/joint-route-adapter.ts +114 -0
- package/src/domains/dispatch/joint-route-resolver.ts +283 -0
- package/src/domains/dispatch/manifest.ts +6 -0
- package/src/domains/dispatch/orphan-recovery.ts +224 -0
- package/src/domains/dispatch/outcome.ts +109 -0
- package/src/domains/dispatch/phase-timing.ts +47 -0
- package/src/domains/dispatch/placement.ts +202 -0
- package/src/domains/dispatch/receipt-findings.ts +255 -0
- package/src/domains/dispatch/receipt-integrity.ts +378 -0
- package/src/domains/dispatch/recovery-candidates.ts +74 -0
- package/src/domains/dispatch/reproducibility.ts +48 -0
- package/src/domains/dispatch/reservation-store.ts +501 -0
- package/src/domains/dispatch/route-approval.ts +177 -0
- package/src/domains/dispatch/route-candidates.ts +57 -0
- package/src/domains/dispatch/route-decision.ts +1079 -0
- package/src/domains/dispatch/route-facts.ts +187 -0
- package/src/domains/dispatch/route-history.ts +238 -0
- package/src/domains/dispatch/route-observer.ts +488 -0
- package/src/domains/dispatch/route-policy.ts +327 -0
- package/src/domains/dispatch/route-quality.ts +256 -0
- package/src/domains/dispatch/route-readiness.ts +120 -0
- package/src/domains/dispatch/routing-intent.ts +287 -0
- package/src/domains/dispatch/run-identity.ts +56 -0
- package/src/domains/dispatch/scout-transition.ts +130 -0
- package/src/domains/dispatch/state.ts +277 -0
- package/src/domains/dispatch/tool-stats.ts +132 -0
- package/src/domains/dispatch/transport.ts +209 -0
- package/src/domains/dispatch/types.ts +785 -0
- package/src/domains/dispatch/validation-grounding.ts +154 -0
- package/src/domains/dispatch/validation.ts +721 -0
- package/src/domains/dispatch/worker-protocol.ts +275 -0
- package/src/domains/dispatch/worker-spawn.ts +566 -0
- package/src/domains/dispatch/write-boundary-enforcer.ts +97 -0
- package/src/domains/dispatch/write-boundary.ts +426 -0
- package/src/domains/eval/artifacts/redact.ts +42 -0
- package/src/domains/eval/artifacts/store.ts +173 -0
- package/src/domains/eval/compare/compare.ts +33 -0
- package/src/domains/eval/compare/gates.ts +66 -0
- package/src/domains/eval/compare/thresholds.ts +92 -0
- package/src/domains/eval/harness-metrics.ts +62 -0
- package/src/domains/eval/index.ts +66 -0
- package/src/domains/eval/metrics/chaos-stream.ts +93 -0
- package/src/domains/eval/metrics/context.ts +34 -0
- package/src/domains/eval/metrics/coverage.ts +21 -0
- package/src/domains/eval/metrics/evidence.ts +182 -0
- package/src/domains/eval/metrics/fleet-loop-stream.ts +196 -0
- package/src/domains/eval/metrics/invariants.ts +736 -0
- package/src/domains/eval/metrics/latency.ts +4 -0
- package/src/domains/eval/metrics/token-stream.ts +139 -0
- package/src/domains/eval/metrics/tokens.ts +51 -0
- package/src/domains/eval/metrics/tool-calls.ts +7 -0
- package/src/domains/eval/proactive-memory.ts +279 -0
- package/src/domains/eval/provenance.ts +35 -0
- package/src/domains/eval/report.ts +234 -0
- package/src/domains/eval/reports/json.ts +5 -0
- package/src/domains/eval/reports/junit.ts +23 -0
- package/src/domains/eval/reports/markdown.ts +20 -0
- package/src/domains/eval/reports/swe-jsonl.ts +16 -0
- package/src/domains/eval/reports/text.ts +25 -0
- package/src/domains/eval/run-compare.ts +274 -0
- package/src/domains/eval/runner.ts +244 -0
- package/src/domains/eval/runners/clio-run.ts +148 -0
- package/src/domains/eval/runners/context-index.ts +56 -0
- package/src/domains/eval/runners/context-init.ts +203 -0
- package/src/domains/eval/runners/external-command.ts +350 -0
- package/src/domains/eval/runtime-paths.ts +171 -0
- package/src/domains/eval/schema/artifact.ts +75 -0
- package/src/domains/eval/schema/suite.ts +235 -0
- package/src/domains/eval/schema/validate.ts +339 -0
- package/src/domains/eval/store.ts +392 -0
- package/src/domains/eval/suites/load.ts +74 -0
- package/src/domains/eval/suites/matrix.ts +19 -0
- package/src/domains/eval/suites/resolve.ts +44 -0
- package/src/domains/eval/suites/run.ts +325 -0
- package/src/domains/eval/task-file.ts +186 -0
- package/src/domains/eval/types.ts +141 -0
- package/src/domains/eval/verifiers/command.ts +27 -0
- package/src/domains/eval/verifiers/file-exists.ts +6 -0
- package/src/domains/eval/verifiers/patch.ts +22 -0
- package/src/domains/eval/workspaces/git.ts +41 -0
- package/src/domains/eval/workspaces/local.ts +17 -0
- package/src/domains/eval/workspaces/temp-copy.ts +29 -0
- package/src/domains/evidence/build.ts +1714 -0
- package/src/domains/evidence/eval.ts +605 -0
- package/src/domains/evidence/failure-attribution.ts +54 -0
- package/src/domains/evidence/finish-contract-map.ts +42 -0
- package/src/domains/evidence/index.ts +55 -0
- package/src/domains/evidence/provenance.ts +200 -0
- package/src/domains/evidence/redact.ts +81 -0
- package/src/domains/evidence/store.ts +291 -0
- package/src/domains/evidence/types.ts +325 -0
- package/src/domains/evolution/SELF_EDIT_GATE.md +91 -0
- package/src/domains/evolution/index.ts +26 -0
- package/src/domains/evolution/manifest.ts +154 -0
- package/src/domains/evolution/validate.ts +304 -0
- package/src/domains/extensions/contract.ts +22 -0
- package/src/domains/extensions/discovery.ts +193 -0
- package/src/domains/extensions/extension.ts +46 -0
- package/src/domains/extensions/index.ts +34 -0
- package/src/domains/extensions/manager.ts +30 -0
- package/src/domains/extensions/manifest.ts +6 -0
- package/src/domains/extensions/resources.ts +38 -0
- package/src/domains/extensions/state.ts +224 -0
- package/src/domains/extensions/types.ts +83 -0
- package/src/domains/interop/consent.ts +185 -0
- package/src/domains/interop/contract.ts +29 -0
- package/src/domains/interop/detect.ts +173 -0
- package/src/domains/interop/extension.ts +59 -0
- package/src/domains/interop/index.ts +34 -0
- package/src/domains/interop/manifest.ts +6 -0
- package/src/domains/interop/registry.ts +139 -0
- package/src/domains/interop/state.ts +92 -0
- package/src/domains/interop/types.ts +109 -0
- package/src/domains/lifecycle/contract.ts +11 -0
- package/src/domains/lifecycle/doctor.ts +536 -0
- package/src/domains/lifecycle/extension.ts +23 -0
- package/src/domains/lifecycle/index.ts +21 -0
- package/src/domains/lifecycle/install-method.ts +51 -0
- package/src/domains/lifecycle/manifest.ts +6 -0
- package/src/domains/lifecycle/migrations/index.ts +94 -0
- package/src/domains/lifecycle/state.ts +93 -0
- package/src/domains/lifecycle/upgrade-notice.ts +35 -0
- package/src/domains/lifecycle/version.ts +35 -0
- package/src/domains/memory/index.ts +128 -0
- package/src/domains/memory/operations.ts +143 -0
- package/src/domains/memory/prompt-section.ts +86 -0
- package/src/domains/memory/proposal.ts +180 -0
- package/src/domains/memory/store.ts +163 -0
- package/src/domains/memory/task-bank.ts +229 -0
- package/src/domains/memory/task-memory-handoff.ts +222 -0
- package/src/domains/memory/task-memory-policy.ts +602 -0
- package/src/domains/memory/task-memory-status.ts +58 -0
- package/src/domains/memory/task-memory-telemetry.ts +346 -0
- package/src/domains/memory/task-memory-trace.ts +89 -0
- package/src/domains/memory/types.ts +74 -0
- package/src/domains/memory/validate.ts +297 -0
- package/src/domains/middleware/budget.ts +216 -0
- package/src/domains/middleware/contract.ts +35 -0
- package/src/domains/middleware/dispatch-nudge.ts +469 -0
- package/src/domains/middleware/extension.ts +129 -0
- package/src/domains/middleware/hook-receipts.ts +70 -0
- package/src/domains/middleware/hooks-io.ts +174 -0
- package/src/domains/middleware/hooks.ts +432 -0
- package/src/domains/middleware/index.ts +154 -0
- package/src/domains/middleware/manifest.ts +6 -0
- package/src/domains/middleware/memory-intervention.ts +701 -0
- package/src/domains/middleware/rules.ts +42 -0
- package/src/domains/middleware/runtime.ts +333 -0
- package/src/domains/middleware/skills-reminder.ts +187 -0
- package/src/domains/middleware/snapshot.ts +71 -0
- package/src/domains/middleware/stalled-turn.ts +71 -0
- package/src/domains/middleware/task-board-reminder.ts +87 -0
- package/src/domains/middleware/task-nudge.ts +77 -0
- package/src/domains/middleware/tool-choice-control.ts +42 -0
- package/src/domains/middleware/types.ts +131 -0
- package/src/domains/middleware/validate.ts +329 -0
- package/src/domains/observability/accountability.ts +67 -0
- package/src/domains/observability/contract.ts +168 -0
- package/src/domains/observability/cost.ts +206 -0
- package/src/domains/observability/evidence-index.ts +123 -0
- package/src/domains/observability/extension.ts +281 -0
- package/src/domains/observability/index.ts +78 -0
- package/src/domains/observability/manifest.ts +10 -0
- package/src/domains/observability/metrics.ts +37 -0
- package/src/domains/observability/projection.ts +477 -0
- package/src/domains/observability/telemetry.ts +89 -0
- package/src/domains/observability/trace-store.ts +1454 -0
- package/src/domains/prompts/compiler.ts +556 -0
- package/src/domains/prompts/contract.ts +30 -0
- package/src/domains/prompts/extension.ts +304 -0
- package/src/domains/prompts/fragment-loader.ts +139 -0
- package/src/domains/prompts/fragments/identity/clio.md +3 -2
- package/src/domains/prompts/fragments/identity/self-awareness.md +63 -0
- package/src/domains/prompts/fragments/operating/contract.md +10 -1
- package/src/domains/prompts/hash.ts +73 -0
- package/src/domains/prompts/index.ts +32 -0
- package/src/domains/prompts/manifest.ts +8 -0
- package/src/domains/prompts/memory-intervention.ts +57 -0
- package/src/domains/prompts/preload.ts +82 -0
- package/src/domains/providers/auth/api-key.ts +47 -0
- package/src/domains/providers/auth/backend-file.ts +69 -0
- package/src/domains/providers/auth/backend-memory.ts +17 -0
- package/src/domains/providers/auth/index.ts +37 -0
- package/src/domains/providers/auth/oauth.ts +36 -0
- package/src/domains/providers/auth/storage.ts +667 -0
- package/src/domains/providers/capabilities.ts +50 -0
- package/src/domains/providers/catalog.ts +162 -0
- package/src/domains/providers/contract.ts +151 -0
- package/src/domains/providers/credentials.ts +20 -0
- package/src/domains/providers/eligibility.ts +24 -0
- package/src/domains/providers/errors.ts +64 -0
- package/src/domains/providers/extension.ts +536 -0
- package/src/domains/providers/index.ts +142 -0
- package/src/domains/providers/knowledge-base-path.ts +102 -0
- package/src/domains/providers/manifest.ts +6 -0
- package/src/domains/providers/model-capabilities.ts +136 -0
- package/src/domains/providers/model-discovery.ts +144 -0
- package/src/domains/providers/model-family.ts +32 -0
- package/src/domains/providers/model-runtime-capabilities.ts +712 -0
- package/src/domains/providers/models/local-models/clio-local-coding-targets.yaml +2 -2
- package/src/domains/providers/plugins.ts +59 -0
- package/src/domains/providers/probe/fingerprint.ts +44 -0
- package/src/domains/providers/probe/http.ts +114 -0
- package/src/domains/providers/probe/reasoning.ts +111 -0
- package/src/domains/providers/registry.ts +166 -0
- package/src/domains/providers/resolver.ts +156 -0
- package/src/domains/providers/runtime-resolution.ts +720 -0
- package/src/domains/providers/runtimes/antigravity/antigravity-code.ts +90 -0
- package/src/domains/providers/runtimes/builtins.ts +78 -0
- package/src/domains/providers/runtimes/claude/claude-code.ts +38 -0
- package/src/domains/providers/runtimes/claude/claude-sdk.ts +38 -0
- package/src/domains/providers/runtimes/claude/common.ts +55 -0
- package/src/domains/providers/runtimes/cloud/alcf.ts +171 -0
- package/src/domains/providers/runtimes/cloud/anthropic-max.ts +71 -0
- package/src/domains/providers/runtimes/cloud/anthropic.ts +43 -0
- package/src/domains/providers/runtimes/cloud/bedrock.ts +35 -0
- package/src/domains/providers/runtimes/cloud/deepseek.ts +50 -0
- package/src/domains/providers/runtimes/cloud/google.ts +41 -0
- package/src/domains/providers/runtimes/cloud/groq.ts +46 -0
- package/src/domains/providers/runtimes/cloud/mistral.ts +46 -0
- package/src/domains/providers/runtimes/cloud/openai-codex.ts +49 -0
- package/src/domains/providers/runtimes/cloud/openai.ts +46 -0
- package/src/domains/providers/runtimes/cloud/openrouter.ts +111 -0
- package/src/domains/providers/runtimes/common/lmstudio-logger.ts +32 -0
- package/src/domains/providers/runtimes/common/local-synth.ts +165 -0
- package/src/domains/providers/runtimes/common/probe-helpers.ts +474 -0
- package/src/domains/providers/runtimes/local-native/lemonade-anthropic.ts +27 -0
- package/src/domains/providers/runtimes/local-native/lemonade-openai.ts +26 -0
- package/src/domains/providers/runtimes/local-native/llamacpp-anthropic.ts +88 -0
- package/src/domains/providers/runtimes/local-native/llamacpp-completion.ts +207 -0
- package/src/domains/providers/runtimes/local-native/llamacpp-embed.ts +180 -0
- package/src/domains/providers/runtimes/local-native/llamacpp-rerank.ts +126 -0
- package/src/domains/providers/runtimes/local-native/llamacpp.ts +98 -0
- package/src/domains/providers/runtimes/local-native/lmstudio-native.ts +491 -0
- package/src/domains/providers/runtimes/local-native/ollama-native.ts +117 -0
- package/src/domains/providers/runtimes/local-native/sglang.ts +26 -0
- package/src/domains/providers/runtimes/local-native/vllm.ts +27 -0
- package/src/domains/providers/runtimes/protocol/anthropic-compat.ts +104 -0
- package/src/domains/providers/runtimes/protocol/anthropic-messages.ts +28 -0
- package/src/domains/providers/runtimes/protocol/bedrock.ts +26 -0
- package/src/domains/providers/runtimes/protocol/google.ts +27 -0
- package/src/domains/providers/runtimes/protocol/openai-compat.ts +145 -0
- package/src/domains/providers/support.ts +238 -0
- package/src/domains/providers/thinking-control-policy.ts +85 -0
- package/src/domains/providers/types/capability-flags.ts +114 -0
- package/src/domains/providers/types/cost-provenance.ts +7 -0
- package/src/domains/providers/types/inference.ts +41 -0
- package/src/domains/providers/types/knowledge-base.ts +156 -0
- package/src/domains/providers/types/local-model-quirks.ts +218 -0
- package/src/domains/providers/types/runtime-descriptor.ts +170 -0
- package/src/domains/providers/types/target-descriptor.ts +38 -0
- package/src/domains/resources/collision.ts +92 -0
- package/src/domains/resources/common-loader.ts +140 -0
- package/src/domains/resources/contract.ts +25 -0
- package/src/domains/resources/extension.ts +61 -0
- package/src/domains/resources/index.ts +74 -0
- package/src/domains/resources/loader.ts +86 -0
- package/src/domains/resources/manifest.ts +6 -0
- package/src/domains/resources/prompts/loader.ts +232 -0
- package/src/domains/resources/prompts/substitute.ts +65 -0
- package/src/domains/resources/skills/content-hash.ts +105 -0
- package/src/domains/resources/skills/evals.ts +175 -0
- package/src/domains/resources/skills/install.ts +410 -0
- package/src/domains/resources/skills/loader.ts +978 -0
- package/src/domains/resources/skills/marketplace.ts +255 -0
- package/src/domains/resources/skills/provenance-pin.ts +115 -0
- package/src/domains/safety/action-classifier.ts +268 -0
- package/src/domains/safety/approval-axis.ts +23 -0
- package/src/domains/safety/audit.ts +487 -0
- package/src/domains/safety/autonomy.ts +174 -0
- package/src/domains/safety/call-target.ts +59 -0
- package/src/domains/safety/contract.ts +65 -0
- package/src/domains/safety/damage-control.ts +44 -0
- package/src/domains/safety/default-path-policy.ts +117 -0
- package/src/domains/safety/extension.ts +383 -0
- package/src/domains/safety/finish-contract-registration.ts +128 -0
- package/src/domains/safety/finish-contract.ts +554 -0
- package/src/domains/safety/index.ts +44 -0
- package/src/domains/safety/loop-detector.ts +143 -0
- package/src/domains/safety/manifest.ts +6 -0
- package/src/domains/safety/path-policy.ts +164 -0
- package/src/domains/safety/policy-engine.ts +994 -0
- package/src/domains/safety/project-policy.ts +391 -0
- package/src/domains/safety/protected-artifacts-registration.ts +189 -0
- package/src/domains/safety/protected-artifacts.ts +993 -0
- package/src/domains/safety/rejection-feedback.ts +102 -0
- package/src/domains/safety/rigor.ts +72 -0
- package/src/domains/safety/rule-compiler.ts +48 -0
- package/src/domains/safety/rule-pack-loader.ts +92 -0
- package/src/domains/safety/run-effects.ts +197 -0
- package/src/domains/safety/scope.ts +61 -0
- package/src/domains/scheduling/budget.ts +35 -0
- package/src/domains/scheduling/cluster.ts +175 -0
- package/src/domains/scheduling/contract.ts +30 -0
- package/src/domains/scheduling/extension.ts +91 -0
- package/src/domains/scheduling/index.ts +12 -0
- package/src/domains/scheduling/manifest.ts +6 -0
- package/src/domains/session/archive-readers.ts +208 -0
- package/src/domains/session/checkpoint.ts +38 -0
- package/src/domains/session/compaction/auto.ts +89 -0
- package/src/domains/session/compaction/branch-summary.ts +186 -0
- package/src/domains/session/compaction/compact.ts +493 -0
- package/src/domains/session/compaction/cut-point.ts +171 -0
- package/src/domains/session/compaction/defaults.ts +34 -0
- package/src/domains/session/compaction/mask-observations.ts +265 -0
- package/src/domains/session/compaction/session-entries.ts +18 -0
- package/src/domains/session/compaction/tokens.ts +147 -0
- package/src/domains/session/context-accounting.ts +583 -0
- package/src/domains/session/context-ledger.ts +348 -0
- package/src/domains/session/contract.ts +144 -0
- package/src/domains/session/cwd-fallback.ts +65 -0
- package/src/domains/session/entries.ts +509 -0
- package/src/domains/session/extension.ts +322 -0
- package/src/domains/session/history.ts +172 -0
- package/src/domains/session/index.ts +84 -0
- package/src/domains/session/manager.ts +128 -0
- package/src/domains/session/manifest.ts +6 -0
- package/src/domains/session/migrations/index.ts +27 -0
- package/src/domains/session/prompt-manifest.ts +173 -0
- package/src/domains/session/protected-artifact-journal.ts +241 -0
- package/src/domains/session/protected-artifacts.ts +90 -0
- package/src/domains/session/retry.ts +238 -0
- package/src/domains/session/task-board.ts +375 -0
- package/src/domains/session/tree/active-path.ts +98 -0
- package/src/domains/session/tree/fork.ts +160 -0
- package/src/domains/session/tree/manager.ts +128 -0
- package/src/domains/session/tree/navigator.ts +177 -0
- package/src/domains/session/tree/preview.ts +259 -0
- package/src/domains/session/usage.ts +148 -0
- package/src/domains/session/workspace/git-probe.ts +161 -0
- package/src/domains/session/workspace/index.ts +4 -0
- package/src/domains/session/workspace/project-type.ts +217 -0
- package/src/domains/session/workspace/snapshot.ts +74 -0
- package/src/domains/share/archive.ts +684 -0
- package/src/domains/share/contract.ts +9 -0
- package/src/domains/share/extension.ts +26 -0
- package/src/domains/share/index.ts +28 -0
- package/src/domains/share/manifest.ts +6 -0
- package/src/engine/acp/adapter.ts +397 -0
- package/src/engine/acp/errors.ts +32 -0
- package/src/engine/acp/event-mapper.ts +154 -0
- package/src/engine/acp/server.ts +656 -0
- package/src/engine/acp/tool-mediator.ts +686 -0
- package/src/engine/acp/transport.ts +654 -0
- package/src/engine/acp/types.ts +170 -0
- package/src/engine/agent.ts +29 -0
- package/src/engine/ai.ts +202 -0
- package/src/engine/alcf-oauth.ts +198 -0
- package/src/engine/antigravity/subprocess-runtime.ts +205 -0
- package/src/engine/apis/degraded-inference.ts +95 -0
- package/src/engine/apis/index.ts +20 -0
- package/src/engine/apis/llamacpp-residency.ts +252 -0
- package/src/engine/apis/lmstudio-native.ts +1438 -0
- package/src/engine/apis/lmstudio-residency.ts +92 -0
- package/src/engine/apis/ollama-native.ts +507 -0
- package/src/engine/apis/openai-completions.ts +716 -0
- package/src/engine/apis/output-budget.ts +99 -0
- package/src/engine/apis/residency-lock.ts +29 -0
- package/src/engine/apis/residency.ts +640 -0
- package/src/engine/apis/resident-models.ts +42 -0
- package/src/engine/apis/sampling-overrides.ts +38 -0
- package/src/engine/apis/thinking-replay.ts +11 -0
- package/src/engine/claude/sdk-runtime.ts +685 -0
- package/src/engine/claude/session-id.ts +5 -0
- package/src/engine/claude/subprocess-runtime.ts +316 -0
- package/src/engine/claude/tool-safety.ts +400 -0
- package/src/engine/external-subprocess.ts +23 -0
- package/src/engine/harmony-response.ts +165 -0
- package/src/engine/loop-guard.ts +1127 -0
- package/src/engine/oauth.ts +192 -0
- package/src/engine/pi-mono-names.ts +13 -0
- package/src/engine/provider-payload.ts +315 -0
- package/src/engine/select-list.ts +53 -0
- package/src/engine/session.ts +834 -0
- package/src/engine/strip-tokenizer-sentinels.ts +125 -0
- package/src/engine/tui.ts +103 -0
- package/src/engine/types.ts +66 -0
- package/src/engine/worker-events.ts +100 -0
- package/src/engine/worker-runtime.ts +1022 -0
- package/src/engine/worker-tools.ts +203 -0
- package/src/entry/orchestrator.ts +1873 -0
- package/src/interactive/application-controller.ts +346 -0
- package/src/interactive/bus-notices.ts +265 -0
- package/src/interactive/chat-loop-messages.ts +626 -0
- package/src/interactive/chat-loop-policy.ts +18 -0
- package/src/interactive/chat-loop.ts +865 -0
- package/src/interactive/chat-panel.ts +1694 -0
- package/src/interactive/chat-renderer.ts +1038 -0
- package/src/interactive/clio-editor.ts +166 -0
- package/src/interactive/command-fallbacks.ts +23 -0
- package/src/interactive/command-output.ts +85 -0
- package/src/interactive/context-activity.ts +203 -0
- package/src/interactive/context-meter.ts +223 -0
- package/src/interactive/context-overlay.ts +220 -0
- package/src/interactive/cost-overlay.ts +279 -0
- package/src/interactive/dispatch-board.ts +1319 -0
- package/src/interactive/dispatch-steering.ts +86 -0
- package/src/interactive/editor-bash.ts +46 -0
- package/src/interactive/editor-steer.ts +51 -0
- package/src/interactive/editor-submit.ts +303 -0
- package/src/interactive/external-editor.ts +67 -0
- package/src/interactive/follow-up-queue-panel.ts +75 -0
- package/src/interactive/footer/dashboard.ts +534 -0
- package/src/interactive/footer/notifications.ts +275 -0
- package/src/interactive/footer/widgets.ts +1246 -0
- package/src/interactive/footer-panel.ts +187 -0
- package/src/interactive/format-time.ts +85 -0
- package/src/interactive/index.ts +11 -0
- package/src/interactive/interactive-application.ts +755 -0
- package/src/interactive/interactive-event-projection.ts +380 -0
- package/src/interactive/interactive-input-runtime.ts +261 -0
- package/src/interactive/interactive-presentation.ts +452 -0
- package/src/interactive/interactive-shell.ts +134 -0
- package/src/interactive/interactive-slash-runtime.ts +492 -0
- package/src/interactive/interactive-subscriptions.ts +111 -0
- package/src/interactive/interactive-tickers.ts +152 -0
- package/src/interactive/keybinding-manager.ts +496 -0
- package/src/interactive/layout.ts +20 -0
- package/src/interactive/leader-key.ts +143 -0
- package/src/interactive/loop-guard-interrupt.ts +101 -0
- package/src/interactive/memory-overlay.ts +280 -0
- package/src/interactive/overlay-ask-user-lifecycle.ts +110 -0
- package/src/interactive/overlay-auth-lifecycle.ts +308 -0
- package/src/interactive/overlay-frame.ts +502 -0
- package/src/interactive/overlay-general-openers.ts +217 -0
- package/src/interactive/overlay-key-routing.ts +213 -0
- package/src/interactive/overlay-lifecycle.ts +413 -0
- package/src/interactive/overlay-model-selectors.ts +127 -0
- package/src/interactive/overlay-permission-lifecycle.ts +344 -0
- package/src/interactive/overlay-resource-openers.ts +112 -0
- package/src/interactive/overlay-session-lifecycle.ts +270 -0
- package/src/interactive/overlay-transitions.ts +57 -0
- package/src/interactive/overlays/agents.ts +69 -0
- package/src/interactive/overlays/ask-user.ts +921 -0
- package/src/interactive/overlays/auth-dialog.ts +221 -0
- package/src/interactive/overlays/context-reset.ts +108 -0
- package/src/interactive/overlays/cwd-fallback.ts +141 -0
- package/src/interactive/overlays/extensions.ts +54 -0
- package/src/interactive/overlays/help-reference.ts +140 -0
- package/src/interactive/overlays/interop.ts +139 -0
- package/src/interactive/overlays/keybinding-detail.ts +90 -0
- package/src/interactive/overlays/list-overlay.ts +606 -0
- package/src/interactive/overlays/message-picker.ts +155 -0
- package/src/interactive/overlays/model-selector.ts +1091 -0
- package/src/interactive/overlays/prompts.ts +72 -0
- package/src/interactive/overlays/session-selector-search.ts +31 -0
- package/src/interactive/overlays/session-selector.ts +266 -0
- package/src/interactive/overlays/settings.ts +3363 -0
- package/src/interactive/overlays/skills-hub.ts +237 -0
- package/src/interactive/overlays/tree-selector.ts +387 -0
- package/src/interactive/permission-overlay.ts +170 -0
- package/src/interactive/render-trace.ts +125 -0
- package/src/interactive/renderers/branch-summary.ts +86 -0
- package/src/interactive/renderers/code-ink.ts +420 -0
- package/src/interactive/renderers/compaction-summary.ts +112 -0
- package/src/interactive/renderers/diff.ts +126 -0
- package/src/interactive/renderers/notice.ts +28 -0
- package/src/interactive/renderers/retry-status.ts +31 -0
- package/src/interactive/renderers/structured.ts +89 -0
- package/src/interactive/renderers/tool-execution.ts +1104 -0
- package/src/interactive/renderers/worker-entry.ts +264 -0
- package/src/interactive/session-last-turn.ts +186 -0
- package/src/interactive/session-transcript.ts +105 -0
- package/src/interactive/session-usage-reseed.ts +74 -0
- package/src/interactive/slash-autocomplete.ts +364 -0
- package/src/interactive/slash-commands.ts +1319 -0
- package/src/interactive/slash-spec.ts +453 -0
- package/src/interactive/status/controller.ts +256 -0
- package/src/interactive/status/index.ts +23 -0
- package/src/interactive/status/state-machine.ts +530 -0
- package/src/interactive/status/summary.ts +170 -0
- package/src/interactive/status/types.ts +121 -0
- package/src/interactive/status/verbs.ts +163 -0
- package/src/interactive/status/watchdog.ts +24 -0
- package/src/interactive/tasks-overlay.ts +186 -0
- package/src/interactive/theme/components.ts +55 -0
- package/src/interactive/theme/glyphs.ts +70 -0
- package/src/interactive/theme/index.ts +15 -0
- package/src/interactive/theme/labels.ts +88 -0
- package/src/interactive/theme/rules.ts +138 -0
- package/src/interactive/theme/segments.ts +88 -0
- package/src/interactive/theme/tokens.ts +121 -0
- package/src/interactive/thinking-level-policy.ts +6 -0
- package/src/interactive/tool-prose-loop.ts +122 -0
- package/src/interactive/tool-prose-registration.ts +48 -0
- package/src/interactive/turn-context.ts +854 -0
- package/src/interactive/turn-middleware.ts +283 -0
- package/src/interactive/turn-persistence.ts +441 -0
- package/src/interactive/turn-queues.ts +169 -0
- package/src/interactive/turn-recovery.ts +306 -0
- package/src/interactive/turn-runtime.ts +802 -0
- package/src/interactive/turn-state.ts +123 -0
- package/src/interactive/view/artifacts.ts +1342 -0
- package/src/interactive/view/view-overlay.ts +732 -0
- package/src/interactive/welcome-dashboard.ts +536 -0
- package/src/interactive/worker-receipts.ts +94 -0
- package/src/interactive/worker-replay.ts +111 -0
- package/src/interactive/worker-share.ts +100 -0
- package/src/interactive/worker-stream.ts +442 -0
- package/src/interactive/workspace-facts.ts +141 -0
- package/src/tools/agent-tools.ts +382 -0
- package/src/tools/artifact.ts +103 -0
- package/src/tools/ask-user.ts +656 -0
- package/src/tools/bash.ts +176 -0
- package/src/tools/bootstrap.ts +474 -0
- package/src/tools/codewiki/code-nav.ts +563 -0
- package/src/tools/codewiki/shared.ts +115 -0
- package/src/tools/compete-worktrees.ts +898 -0
- package/src/tools/context/docs-engine.ts +619 -0
- package/src/tools/context/index.ts +435 -0
- package/src/tools/credential-present.ts +151 -0
- package/src/tools/dispatch-arguments.ts +228 -0
- package/src/tools/dispatch-plan.ts +741 -0
- package/src/tools/dispatch-scout.ts +461 -0
- package/src/tools/dispatch.ts +3338 -0
- package/src/tools/edit-diff.ts +534 -0
- package/src/tools/edit.ts +128 -0
- package/src/tools/executables.ts +22 -0
- package/src/tools/file-mutation-queue.ts +35 -0
- package/src/tools/find.ts +292 -0
- package/src/tools/grep.ts +495 -0
- package/src/tools/ignore-policy.ts +169 -0
- package/src/tools/ledger.ts +206 -0
- package/src/tools/ls.ts +110 -0
- package/src/tools/monitor.ts +797 -0
- package/src/tools/network-policy.ts +29 -0
- package/src/tools/observation.ts +421 -0
- package/src/tools/observers.ts +99 -0
- package/src/tools/path-utils.ts +79 -0
- package/src/tools/policy.ts +154 -0
- package/src/tools/profiles.ts +108 -0
- package/src/tools/read.ts +173 -0
- package/src/tools/registry.ts +1157 -0
- package/src/tools/result-shaping.ts +204 -0
- package/src/tools/safe-exec.ts +128 -0
- package/src/tools/spawn-hygiene.ts +182 -0
- package/src/tools/steer.ts +88 -0
- package/src/tools/string-enum.ts +15 -0
- package/src/tools/tasks.ts +168 -0
- package/src/tools/truncate-utf8.ts +17 -0
- package/src/tools/truncate.ts +202 -0
- package/src/tools/verify/frontend.ts +685 -0
- package/src/tools/verify/index.ts +66 -0
- package/src/tools/verify/scripts.ts +108 -0
- package/src/tools/web-fetch.ts +777 -0
- package/src/tools/worker-evidence.ts +215 -0
- package/src/tools/write.ts +52 -0
- package/src/utils/exif-orientation.ts +192 -0
- package/src/utils/git.ts +24 -0
- package/src/utils/image-resize.ts +148 -0
- package/src/utils/photon.ts +103 -0
- package/src/worker/control-lane.ts +22 -0
- package/src/worker/entry.ts +257 -0
- package/src/worker/event-projection.ts +56 -0
- package/src/worker/heartbeat.ts +24 -0
- package/src/worker/ledger-mirror.ts +95 -0
- package/src/worker/ndjson.ts +40 -0
- package/src/worker/protocol.ts +529 -0
- package/src/worker/resource-facts.ts +79 -0
- package/src/worker/runtime-registry.ts +12 -0
- package/src/worker/spec-contract.ts +654 -0
- package/src/worker/stdin-demux.ts +316 -0
- package/dist/acp-UMLFVA3F.js +0 -92
- package/dist/chunk-262G75JS.js +0 -35
- package/dist/chunk-5LDRNKX2.js +0 -1063
- package/dist/chunk-67MTHP2E.js +0 -135
- package/dist/chunk-GOTUR54M.js +0 -9
- package/dist/chunk-TPOCL34A.js +0 -2876
- package/dist/chunk-XV4ZJ6ZM.js +0 -3177
- package/dist/clio-KIQ5SNDS.js +0 -53
- package/dist/configure-G4E3A2PG.js +0 -27
- package/dist/doctor-M5HJJZOL.js +0 -61
- package/dist/domains/agents/builtins/architect.md +0 -33
- package/dist/domains/agents/builtins/coder.md +0 -31
- package/dist/domains/agents/builtins/context-bootstrap.md +0 -38
- package/dist/domains/agents/builtins/debugger.md +0 -30
- package/dist/domains/agents/builtins/documenter.md +0 -31
- package/dist/domains/agents/builtins/git-master.md +0 -30
- package/dist/domains/agents/builtins/provenance.md +0 -30
- package/dist/domains/agents/builtins/researcher.md +0 -71
- package/dist/domains/agents/builtins/scout.md +0 -42
- package/dist/domains/agents/builtins/tester.md +0 -31
- package/dist/domains/agents/builtins/verifier.md +0 -30
- package/dist/domains/agents/builtins/wiki-writer.md +0 -41
- package/dist/fleet-preflight-CLIAX7YR.js +0 -21
- package/dist/preload-KZVHET2B.js +0 -11
- package/dist/version-ROZ6CZKH.js +0 -16
- package/skills/git/commit-crafting/SKILL.md +0 -79
- package/skills/git/commit-crafting/evals.md +0 -92
- package/skills/git/create-pr/SKILL.md +0 -116
- package/skills/git/create-pr/evals.md +0 -114
- package/skills/git/investigate-issue/SKILL.md +0 -139
- package/skills/git/investigate-issue/evals.md +0 -94
- package/skills/git/review-changes/SKILL.md +0 -103
- package/skills/git/review-changes/evals.md +0 -85
|
@@ -0,0 +1,834 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clio session JSONL writer + reader (Phase 3 slice 1).
|
|
3
|
+
*
|
|
4
|
+
* On-disk layout under `clioStateDir()`:
|
|
5
|
+
* sessions/<cwdHash>/<sessionId>/
|
|
6
|
+
* meta.json ClioSessionMeta
|
|
7
|
+
* current.jsonl append-only structured session entries
|
|
8
|
+
* tree.json [{id, parentId, at, kind}, ...]
|
|
9
|
+
*
|
|
10
|
+
* Atomicity:
|
|
11
|
+
* - Appends go to an O_APPEND fd held for the writer's lifetime; each line
|
|
12
|
+
* is one write(2). fsync is debounced after appends and forced on
|
|
13
|
+
* checkpoint (`persistTree`) and `close`. A torn last line from a crash
|
|
14
|
+
* is tolerated by the reader (skipped with a warning).
|
|
15
|
+
* - `replaceEntries` rewrites current.jsonl via `writeJsonlFileAtomic`
|
|
16
|
+
* (`.tmp` + fsync + rename) and reopens the append fd afterwards.
|
|
17
|
+
* - tree.json and meta.json are written via `atomicWrite` (tmp + fsync + rename).
|
|
18
|
+
*
|
|
19
|
+
* This module sits in `src/engine/` because it is the engine's artifact
|
|
20
|
+
* contract with the session domain, but it imports no pi-mono packages.
|
|
21
|
+
* It is pure node: fs, path, crypto.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import { createHash, randomBytes } from "node:crypto";
|
|
25
|
+
import {
|
|
26
|
+
closeSync,
|
|
27
|
+
existsSync,
|
|
28
|
+
constants as fsConstants,
|
|
29
|
+
fstatSync,
|
|
30
|
+
fsyncSync,
|
|
31
|
+
mkdirSync,
|
|
32
|
+
openSync,
|
|
33
|
+
readdirSync,
|
|
34
|
+
readFileSync,
|
|
35
|
+
readSync,
|
|
36
|
+
renameSync,
|
|
37
|
+
statSync,
|
|
38
|
+
writeSync,
|
|
39
|
+
} from "node:fs";
|
|
40
|
+
import { dirname, join, resolve } from "node:path";
|
|
41
|
+
import { StringDecoder } from "node:string_decoder";
|
|
42
|
+
import { readClioVersion, readPiMonoVersion } from "../core/package-root.js";
|
|
43
|
+
import { assertSafeId } from "../core/safe-id.js";
|
|
44
|
+
import { fsyncDirectory, safeResourceWrite } from "../core/safe-resource-write.js";
|
|
45
|
+
import { clioStateDir, stateRootRemoved } from "../core/xdg.js";
|
|
46
|
+
|
|
47
|
+
export interface ClioSessionMeta {
|
|
48
|
+
id: string;
|
|
49
|
+
cwd: string;
|
|
50
|
+
cwdHash: string;
|
|
51
|
+
createdAt: string;
|
|
52
|
+
endedAt: string | null;
|
|
53
|
+
model: string | null;
|
|
54
|
+
target: string | null;
|
|
55
|
+
clioVersion: string;
|
|
56
|
+
piMonoVersion: string;
|
|
57
|
+
platform: string;
|
|
58
|
+
nodeVersion: string;
|
|
59
|
+
/**
|
|
60
|
+
* Version 3 on every new session. Readers reject earlier versions and
|
|
61
|
+
* sessions that omit this field.
|
|
62
|
+
*/
|
|
63
|
+
sessionFormatVersion?: number;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export const CURRENT_SESSION_FORMAT_VERSION = 3;
|
|
67
|
+
|
|
68
|
+
export interface ClioSessionJsonlHeader {
|
|
69
|
+
type: "session";
|
|
70
|
+
version: number;
|
|
71
|
+
id: string;
|
|
72
|
+
timestamp: string;
|
|
73
|
+
cwd: string;
|
|
74
|
+
parentSession?: string;
|
|
75
|
+
parentTurnId?: string;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface ClioTurnRecord {
|
|
79
|
+
id: string;
|
|
80
|
+
parentId: string | null;
|
|
81
|
+
at: string;
|
|
82
|
+
kind: "user" | "assistant" | "tool_call" | "tool_result" | "system" | "checkpoint";
|
|
83
|
+
payload: unknown;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export interface SessionTreeNode {
|
|
87
|
+
id: string;
|
|
88
|
+
parentId: string | null;
|
|
89
|
+
at: string;
|
|
90
|
+
kind: ClioTurnRecord["kind"];
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export interface ClioSessionFile {
|
|
94
|
+
current: string;
|
|
95
|
+
tree: string;
|
|
96
|
+
meta: string;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export interface ClioSessionWriter {
|
|
100
|
+
/** Write an ordinary turn as a structured message entry and add its tree node. */
|
|
101
|
+
append(turn: ClioTurnRecord): void;
|
|
102
|
+
/**
|
|
103
|
+
* Write a pre-composed structured session entry as a JSON line. Callers
|
|
104
|
+
* supply `treeNode` when the entry must project into the turn tree.
|
|
105
|
+
*/
|
|
106
|
+
appendEntry(entry: unknown, opts?: { treeNode?: SessionTreeNode }): void;
|
|
107
|
+
/** Atomically replace current.jsonl entries while preserving the session header. */
|
|
108
|
+
replaceEntries(entries: ReadonlyArray<unknown>): void;
|
|
109
|
+
persistTree(): Promise<void>;
|
|
110
|
+
/** Synchronously fsync append-only transcript bytes without rewriting tree/meta. */
|
|
111
|
+
flushAppends(): void;
|
|
112
|
+
close(): Promise<void>;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export interface ClioSessionReader {
|
|
116
|
+
meta(): ClioSessionMeta;
|
|
117
|
+
turns(): ReadonlyArray<unknown>;
|
|
118
|
+
fileEntries(): ReadonlyArray<unknown>;
|
|
119
|
+
header(): ClioSessionJsonlHeader | null;
|
|
120
|
+
tree(): ReadonlyArray<SessionTreeNode>;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function cwdHash(cwd: string): string {
|
|
124
|
+
const normalized = resolve(cwd);
|
|
125
|
+
return createHash("sha256").update(normalized).digest("hex").slice(0, 16);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export function sessionPaths(meta: ClioSessionMeta): ClioSessionFile {
|
|
129
|
+
const dir = join(clioStateDir(), "sessions", meta.cwdHash, meta.id);
|
|
130
|
+
mkdirSync(dir, { recursive: true });
|
|
131
|
+
return {
|
|
132
|
+
current: join(dir, "current.jsonl"),
|
|
133
|
+
tree: join(dir, "tree.json"),
|
|
134
|
+
meta: join(dir, "meta.json"),
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// meta.json and tree.json rewrites delegate to the canonical writer. Neither
|
|
139
|
+
// file is recovered from a leftover temp, so the randomized hidden temp name is
|
|
140
|
+
// safe here (unlike current.jsonl, which promotes a deterministic `.tmp`).
|
|
141
|
+
export function atomicWrite(targetPath: string, contents: string | Uint8Array): void {
|
|
142
|
+
safeResourceWrite(targetPath, contents);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export interface SessionJsonlWarning {
|
|
146
|
+
path: string;
|
|
147
|
+
line: number;
|
|
148
|
+
message: string;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export type SessionJsonlWarningSink = (warning: SessionJsonlWarning) => void;
|
|
152
|
+
|
|
153
|
+
export interface SessionJsonlReadOptions {
|
|
154
|
+
onWarning?: SessionJsonlWarningSink;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export interface SessionJsonlWriteOptions {
|
|
158
|
+
beforeRename?: (tmpPath: string, targetPath: string) => void;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* One damaged line, one message. A single ledger is read several times per
|
|
163
|
+
* command by callers that do not know about each other (resume, the turn tree,
|
|
164
|
+
* history), and each read re-reported every unparseable line, so one torn tail
|
|
165
|
+
* printed the identical skip line three times and read as three problems. The
|
|
166
|
+
* key is the exact warning, so a second defect in the same file is still said.
|
|
167
|
+
*/
|
|
168
|
+
const reportedSessionJsonlWarnings = new Set<string>();
|
|
169
|
+
// A long-lived process sweeping a large store must not grow this without
|
|
170
|
+
// bound. Forgetting everything at the cap at worst repeats a warning once.
|
|
171
|
+
const REPORTED_SESSION_JSONL_WARNING_LIMIT = 1000;
|
|
172
|
+
|
|
173
|
+
function defaultSessionJsonlWarning(warning: SessionJsonlWarning): void {
|
|
174
|
+
const key = `${warning.path}:${warning.line}:${warning.message}`;
|
|
175
|
+
if (reportedSessionJsonlWarnings.has(key)) return;
|
|
176
|
+
if (reportedSessionJsonlWarnings.size >= REPORTED_SESSION_JSONL_WARNING_LIMIT) reportedSessionJsonlWarnings.clear();
|
|
177
|
+
reportedSessionJsonlWarnings.add(key);
|
|
178
|
+
process.stderr.write(`[clio:session] ${warning.path}:${warning.line}: ${warning.message}\n`);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function serializeJsonl(entries: ReadonlyArray<unknown>): string {
|
|
182
|
+
if (entries.length === 0) return "";
|
|
183
|
+
const lines = entries.map((entry, index) => {
|
|
184
|
+
const serialized = JSON.stringify(entry);
|
|
185
|
+
if (serialized === undefined) {
|
|
186
|
+
throw new Error(`session JSONL entry ${index + 1} is not serializable`);
|
|
187
|
+
}
|
|
188
|
+
return serialized;
|
|
189
|
+
});
|
|
190
|
+
return `${lines.join("\n")}\n`;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Rewrite a JSONL file through `<target>.tmp` and rename over the target.
|
|
195
|
+
* A crash or interruption before the rename leaves the original target
|
|
196
|
+
* untouched; when no target exists yet, recovery readers can promote the tmp.
|
|
197
|
+
*/
|
|
198
|
+
export function writeJsonlFileAtomic(
|
|
199
|
+
targetPath: string,
|
|
200
|
+
entries: ReadonlyArray<unknown>,
|
|
201
|
+
options: SessionJsonlWriteOptions = {},
|
|
202
|
+
): void {
|
|
203
|
+
const dir = dirname(targetPath);
|
|
204
|
+
mkdirSync(dir, { recursive: true });
|
|
205
|
+
const body = serializeJsonl(entries);
|
|
206
|
+
const tmp = `${targetPath}.tmp`;
|
|
207
|
+
const fd = openSync(tmp, "w");
|
|
208
|
+
try {
|
|
209
|
+
writeSync(fd, body);
|
|
210
|
+
fsyncSync(fd);
|
|
211
|
+
} finally {
|
|
212
|
+
closeSync(fd);
|
|
213
|
+
}
|
|
214
|
+
options.beforeRename?.(tmp, targetPath);
|
|
215
|
+
renameSync(tmp, targetPath);
|
|
216
|
+
fsyncDirectory(dir);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function recoverJsonlTargetIfMissing(targetPath: string): string | null {
|
|
220
|
+
if (existsSync(targetPath)) return targetPath;
|
|
221
|
+
const tmp = `${targetPath}.tmp`;
|
|
222
|
+
try {
|
|
223
|
+
if (!statSync(tmp).isFile()) return null;
|
|
224
|
+
renameSync(tmp, targetPath);
|
|
225
|
+
fsyncDirectory(dirname(targetPath));
|
|
226
|
+
return targetPath;
|
|
227
|
+
} catch {
|
|
228
|
+
return existsSync(targetPath) ? targetPath : existsSync(tmp) ? tmp : null;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const SESSION_JSONL_READ_CHUNK_BYTES = 64 * 1024;
|
|
233
|
+
|
|
234
|
+
function parseSessionJsonlLine(
|
|
235
|
+
line: string,
|
|
236
|
+
lineNumber: number,
|
|
237
|
+
readPath: string,
|
|
238
|
+
entries: unknown[],
|
|
239
|
+
warn: SessionJsonlWarningSink,
|
|
240
|
+
): void {
|
|
241
|
+
if (line.trim().length === 0) return;
|
|
242
|
+
try {
|
|
243
|
+
entries.push(JSON.parse(line) as unknown);
|
|
244
|
+
} catch (error) {
|
|
245
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
246
|
+
warn({ path: readPath, line: lineNumber, message: `invalid JSON skipped: ${message}` });
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
export function readSessionFileEntries(path: string, options: SessionJsonlReadOptions = {}): unknown[] {
|
|
251
|
+
const readPath = recoverJsonlTargetIfMissing(path);
|
|
252
|
+
if (readPath === null) return [];
|
|
253
|
+
const entries: unknown[] = [];
|
|
254
|
+
const warn = options.onWarning ?? defaultSessionJsonlWarning;
|
|
255
|
+
const fd = openSync(readPath, "r");
|
|
256
|
+
const buffer = Buffer.allocUnsafe(SESSION_JSONL_READ_CHUNK_BYTES);
|
|
257
|
+
const decoder = new StringDecoder("utf8");
|
|
258
|
+
let pending = "";
|
|
259
|
+
let lineNumber = 0;
|
|
260
|
+
try {
|
|
261
|
+
for (;;) {
|
|
262
|
+
const bytesRead = readSync(fd, buffer, 0, buffer.length, null);
|
|
263
|
+
if (bytesRead === 0) break;
|
|
264
|
+
pending += decoder.write(buffer.subarray(0, bytesRead));
|
|
265
|
+
for (;;) {
|
|
266
|
+
const newlineIndex = pending.indexOf("\n");
|
|
267
|
+
if (newlineIndex < 0) break;
|
|
268
|
+
const line = pending.slice(0, newlineIndex);
|
|
269
|
+
pending = pending.slice(newlineIndex + 1);
|
|
270
|
+
lineNumber += 1;
|
|
271
|
+
parseSessionJsonlLine(line, lineNumber, readPath, entries, warn);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
pending += decoder.end();
|
|
275
|
+
if (pending.length > 0) {
|
|
276
|
+
lineNumber += 1;
|
|
277
|
+
parseSessionJsonlLine(pending, lineNumber, readPath, entries, warn);
|
|
278
|
+
}
|
|
279
|
+
} finally {
|
|
280
|
+
closeSync(fd);
|
|
281
|
+
}
|
|
282
|
+
return entries;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
export interface SessionTailReadResult {
|
|
286
|
+
/** Parsed tail entries in file order (header included only if BOF was reached). */
|
|
287
|
+
entries: unknown[];
|
|
288
|
+
/** Non-empty JSONL lines parsed — the bounded-work signal (≈ maxEntries, not file size). */
|
|
289
|
+
linesParsed: number;
|
|
290
|
+
/** True when the read consumed the whole file from its start (small files). */
|
|
291
|
+
reachedStart: boolean;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/** Read exactly `length` bytes at `position`, looping over short reads. */
|
|
295
|
+
function readExactAt(fd: number, buffer: Buffer, position: number, length: number): void {
|
|
296
|
+
let read = 0;
|
|
297
|
+
while (read < length) {
|
|
298
|
+
const got = readSync(fd, buffer, read, length - read, position + read);
|
|
299
|
+
if (got === 0) break; // truncated under us; parse what we have
|
|
300
|
+
read += got;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Read only the last `maxEntries` non-empty JSONL lines of a session ledger by
|
|
306
|
+
* scanning backward from EOF, instead of parsing the whole file. Cost is bounded
|
|
307
|
+
* by `maxEntries` and the trailing bytes those lines occupy, not by session
|
|
308
|
+
* length. The trailing window starts at one chunk and doubles until it holds
|
|
309
|
+
* enough complete lines or reaches the file start; the first line of a non-BOF
|
|
310
|
+
* window is dropped as a partial line (its start lies before the window), which
|
|
311
|
+
* at worst discards one extra oldest line — never one of the last `maxEntries`.
|
|
312
|
+
*
|
|
313
|
+
* Behaviour matches `readSessionFileEntries` line-for-line over the tail it
|
|
314
|
+
* returns: same `parseSessionJsonlLine` (torn-tail tolerant), same warning sink.
|
|
315
|
+
*/
|
|
316
|
+
export function readSessionFileTailEntries(
|
|
317
|
+
path: string,
|
|
318
|
+
maxEntries: number,
|
|
319
|
+
options: SessionJsonlReadOptions & { chunkBytes?: number } = {},
|
|
320
|
+
): SessionTailReadResult {
|
|
321
|
+
const readPath = recoverJsonlTargetIfMissing(path);
|
|
322
|
+
if (readPath === null) return { entries: [], linesParsed: 0, reachedStart: true };
|
|
323
|
+
const warn = options.onWarning ?? defaultSessionJsonlWarning;
|
|
324
|
+
const bound = Number.isFinite(maxEntries) && maxEntries > 0 ? Math.floor(maxEntries) : 1;
|
|
325
|
+
const chunkBytes =
|
|
326
|
+
options.chunkBytes !== undefined && options.chunkBytes > 0
|
|
327
|
+
? Math.floor(options.chunkBytes)
|
|
328
|
+
: SESSION_JSONL_READ_CHUNK_BYTES;
|
|
329
|
+
const fd = openSync(readPath, "r");
|
|
330
|
+
try {
|
|
331
|
+
const size = fstatSync(fd).size;
|
|
332
|
+
if (size === 0) return { entries: [], linesParsed: 0, reachedStart: true };
|
|
333
|
+
let windowBytes = Math.min(size, chunkBytes);
|
|
334
|
+
for (;;) {
|
|
335
|
+
const offset = Math.max(0, size - windowBytes);
|
|
336
|
+
const length = size - offset;
|
|
337
|
+
const buffer = Buffer.allocUnsafe(length);
|
|
338
|
+
readExactAt(fd, buffer, offset, length);
|
|
339
|
+
const decoder = new StringDecoder("utf8");
|
|
340
|
+
const text = decoder.write(buffer) + decoder.end();
|
|
341
|
+
const reachedStart = offset === 0;
|
|
342
|
+
// A non-BOF window's first line is partial (it began before `offset`).
|
|
343
|
+
const lines = text.split("\n");
|
|
344
|
+
const candidate = reachedStart ? lines : lines.slice(1);
|
|
345
|
+
const nonEmpty = candidate.filter((line) => line.trim().length > 0);
|
|
346
|
+
if (nonEmpty.length >= bound || reachedStart) {
|
|
347
|
+
const tail = nonEmpty.slice(Math.max(0, nonEmpty.length - bound));
|
|
348
|
+
const entries: unknown[] = [];
|
|
349
|
+
let lineNumber = 0;
|
|
350
|
+
for (const line of tail) {
|
|
351
|
+
lineNumber += 1;
|
|
352
|
+
parseSessionJsonlLine(line, lineNumber, readPath, entries, warn);
|
|
353
|
+
}
|
|
354
|
+
return { entries, linesParsed: tail.length, reachedStart };
|
|
355
|
+
}
|
|
356
|
+
if (windowBytes >= size) return { entries: [], linesParsed: 0, reachedStart: true };
|
|
357
|
+
windowBytes = Math.min(size, windowBytes * 2);
|
|
358
|
+
}
|
|
359
|
+
} finally {
|
|
360
|
+
closeSync(fd);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Tail-scoped counterpart to `openSession(id).turns()`: the last `maxTurns`
|
|
366
|
+
* non-header entries of the session ledger, in file order. Reads one extra line
|
|
367
|
+
* so a header consuming a slot in a wholly-read small file never shrinks the
|
|
368
|
+
* turn count below `maxTurns`.
|
|
369
|
+
*/
|
|
370
|
+
export function readSessionTailTurns(id: string, maxTurns: number): SessionTailReadResult {
|
|
371
|
+
const currentPath = sessionCurrentPath(id);
|
|
372
|
+
const result = readSessionFileTailEntries(currentPath, maxTurns + 1);
|
|
373
|
+
const turns = result.entries.filter((entry) => !isSessionJsonlHeader(entry));
|
|
374
|
+
return {
|
|
375
|
+
entries: turns.slice(Math.max(0, turns.length - maxTurns)),
|
|
376
|
+
linesParsed: result.linesParsed,
|
|
377
|
+
reachedStart: result.reachedStart,
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
function isPositiveInteger(value: unknown): value is number {
|
|
382
|
+
return typeof value === "number" && Number.isInteger(value) && value > 0;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
function isOptionalString(value: unknown): boolean {
|
|
386
|
+
return value === undefined || typeof value === "string";
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
function isSessionJsonlHeader(value: unknown): value is ClioSessionJsonlHeader {
|
|
390
|
+
if (!value || typeof value !== "object") return false;
|
|
391
|
+
const v = value as Record<string, unknown>;
|
|
392
|
+
return (
|
|
393
|
+
v.type === "session" &&
|
|
394
|
+
isPositiveInteger(v.version) &&
|
|
395
|
+
typeof v.id === "string" &&
|
|
396
|
+
typeof v.timestamp === "string" &&
|
|
397
|
+
typeof v.cwd === "string" &&
|
|
398
|
+
isOptionalString(v.parentSession) &&
|
|
399
|
+
isOptionalString(v.parentTurnId)
|
|
400
|
+
);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
function sessionHeaderFromMeta(
|
|
404
|
+
meta: ClioSessionMeta,
|
|
405
|
+
options: { parentSession?: string; parentTurnId?: string } = {},
|
|
406
|
+
): ClioSessionJsonlHeader {
|
|
407
|
+
const header: ClioSessionJsonlHeader = {
|
|
408
|
+
type: "session",
|
|
409
|
+
version: CURRENT_SESSION_FORMAT_VERSION,
|
|
410
|
+
id: meta.id,
|
|
411
|
+
timestamp: meta.createdAt,
|
|
412
|
+
cwd: meta.cwd,
|
|
413
|
+
};
|
|
414
|
+
if (options.parentSession !== undefined) header.parentSession = options.parentSession;
|
|
415
|
+
if (options.parentTurnId !== undefined) header.parentTurnId = options.parentTurnId;
|
|
416
|
+
return header;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
function ensureSessionHeader(
|
|
420
|
+
meta: ClioSessionMeta,
|
|
421
|
+
entries: ReadonlyArray<unknown>,
|
|
422
|
+
options: { parentSession?: string; parentTurnId?: string } = {},
|
|
423
|
+
): unknown[] {
|
|
424
|
+
const first = entries[0];
|
|
425
|
+
if (isSessionJsonlHeader(first)) return [...entries];
|
|
426
|
+
return [sessionHeaderFromMeta(meta, options), ...entries];
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
function recordFromTurn(turn: ClioTurnRecord): unknown {
|
|
430
|
+
const entry: Record<string, unknown> = {
|
|
431
|
+
kind: "message",
|
|
432
|
+
turnId: turn.id,
|
|
433
|
+
parentTurnId: turn.parentId,
|
|
434
|
+
timestamp: turn.at,
|
|
435
|
+
role: turn.kind,
|
|
436
|
+
payload: turn.payload,
|
|
437
|
+
};
|
|
438
|
+
return entry;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
function newTurnId(): string {
|
|
442
|
+
const n = BigInt(`0x${randomBytes(8).toString("hex")}`);
|
|
443
|
+
const raw = n.toString(36);
|
|
444
|
+
if (raw.length >= 12) return raw.slice(0, 12);
|
|
445
|
+
return raw.padStart(12, "0");
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
function buildMeta(input: { cwd: string; model?: string | null; target?: string | null }): ClioSessionMeta {
|
|
449
|
+
const resolvedCwd = resolve(input.cwd);
|
|
450
|
+
return {
|
|
451
|
+
id: newTurnId(),
|
|
452
|
+
cwd: resolvedCwd,
|
|
453
|
+
cwdHash: cwdHash(resolvedCwd),
|
|
454
|
+
createdAt: new Date().toISOString(),
|
|
455
|
+
endedAt: null,
|
|
456
|
+
model: input.model ?? null,
|
|
457
|
+
target: input.target ?? null,
|
|
458
|
+
clioVersion: readClioVersion(),
|
|
459
|
+
piMonoVersion: readPiMonoVersion(),
|
|
460
|
+
platform: process.platform,
|
|
461
|
+
nodeVersion: process.version,
|
|
462
|
+
sessionFormatVersion: CURRENT_SESSION_FORMAT_VERSION,
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
function readMetaFile(path: string): ClioSessionMeta {
|
|
467
|
+
const raw = readFileSync(path, "utf8");
|
|
468
|
+
return JSON.parse(raw) as ClioSessionMeta;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
const TURN_KINDS: readonly ClioTurnRecord["kind"][] = [
|
|
472
|
+
"user",
|
|
473
|
+
"assistant",
|
|
474
|
+
"tool_call",
|
|
475
|
+
"tool_result",
|
|
476
|
+
"system",
|
|
477
|
+
"checkpoint",
|
|
478
|
+
];
|
|
479
|
+
|
|
480
|
+
function isTurnKind(value: unknown): value is ClioTurnRecord["kind"] {
|
|
481
|
+
return typeof value === "string" && (TURN_KINDS as readonly string[]).includes(value);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
function nullableString(value: unknown): value is string | null {
|
|
485
|
+
return value === null || typeof value === "string";
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
function isSessionTreeNode(value: unknown): value is SessionTreeNode {
|
|
489
|
+
if (!value || typeof value !== "object") return false;
|
|
490
|
+
const node = value as Record<string, unknown>;
|
|
491
|
+
return (
|
|
492
|
+
typeof node.id === "string" && nullableString(node.parentId) && typeof node.at === "string" && isTurnKind(node.kind)
|
|
493
|
+
);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
function readTreeFile(path: string): SessionTreeNode[] {
|
|
497
|
+
if (!existsSync(path)) return [];
|
|
498
|
+
try {
|
|
499
|
+
const raw = readFileSync(path, "utf8");
|
|
500
|
+
if (raw.trim().length === 0) return [];
|
|
501
|
+
const parsed = JSON.parse(raw) as unknown;
|
|
502
|
+
if (!Array.isArray(parsed)) return [];
|
|
503
|
+
return parsed.filter(isSessionTreeNode);
|
|
504
|
+
} catch {
|
|
505
|
+
return [];
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
function treeNodeFromFileEntry(entry: unknown): SessionTreeNode | null {
|
|
510
|
+
if (!entry || typeof entry !== "object" || isSessionJsonlHeader(entry)) return null;
|
|
511
|
+
const value = entry as Record<string, unknown>;
|
|
512
|
+
if (
|
|
513
|
+
value.kind === "message" &&
|
|
514
|
+
typeof value.turnId === "string" &&
|
|
515
|
+
nullableString(value.parentTurnId) &&
|
|
516
|
+
typeof value.timestamp === "string" &&
|
|
517
|
+
isTurnKind(value.role) &&
|
|
518
|
+
Object.hasOwn(value, "payload")
|
|
519
|
+
) {
|
|
520
|
+
return { id: value.turnId, parentId: value.parentTurnId, at: value.timestamp, kind: value.role };
|
|
521
|
+
}
|
|
522
|
+
return null;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
function treeFromFileEntries(fileEntries: ReadonlyArray<unknown>): SessionTreeNode[] {
|
|
526
|
+
const nodes: SessionTreeNode[] = [];
|
|
527
|
+
for (const entry of fileEntries) {
|
|
528
|
+
const node = treeNodeFromFileEntry(entry);
|
|
529
|
+
if (node) nodes.push(node);
|
|
530
|
+
}
|
|
531
|
+
return nodes;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
function sameTreeNode(a: SessionTreeNode | undefined, b: SessionTreeNode): boolean {
|
|
535
|
+
return !!a && a.id === b.id && a.parentId === b.parentId && a.at === b.at && a.kind === b.kind;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
function sameTree(a: ReadonlyArray<SessionTreeNode>, b: ReadonlyArray<SessionTreeNode>): boolean {
|
|
539
|
+
if (a.length !== b.length) return false;
|
|
540
|
+
for (let i = 0; i < a.length; i += 1) {
|
|
541
|
+
const left = a[i];
|
|
542
|
+
const right = b[i];
|
|
543
|
+
if (!left || !right || !sameTreeNode(left, right)) return false;
|
|
544
|
+
}
|
|
545
|
+
return true;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
function recoverTreeFromJsonl(diskTree: SessionTreeNode[], fileEntries: ReadonlyArray<unknown>): SessionTreeNode[] {
|
|
549
|
+
const recovered = treeFromFileEntries(fileEntries);
|
|
550
|
+
if (recovered.length === 0) return diskTree;
|
|
551
|
+
return sameTree(diskTree, recovered) ? diskTree : recovered;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
export function sessionCurrentPath(id: string): string {
|
|
555
|
+
return join(findSessionDir(id), "current.jsonl");
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
function findSessionDir(id: string): string {
|
|
559
|
+
// Session ids are identifiers, not paths. Reject a traversal id before any
|
|
560
|
+
// filesystem read so it can never resolve a directory outside the sessions
|
|
561
|
+
// root (`join(sessionsRoot, entry, id)` would otherwise escape).
|
|
562
|
+
assertSafeId(id, "session");
|
|
563
|
+
const sessionsRoot = join(clioStateDir(), "sessions");
|
|
564
|
+
if (!existsSync(sessionsRoot)) {
|
|
565
|
+
throw new Error(`session not found: ${id}`);
|
|
566
|
+
}
|
|
567
|
+
for (const entry of readdirSync(sessionsRoot, { withFileTypes: true })) {
|
|
568
|
+
if (!entry.isDirectory()) continue;
|
|
569
|
+
const candidate = join(sessionsRoot, entry.name, id);
|
|
570
|
+
if (existsSync(candidate) && statSync(candidate).isDirectory()) {
|
|
571
|
+
return candidate;
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
throw new Error(`session not found: ${id}`);
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
/** Read only meta.json for callers that do not need to parse the transcript. */
|
|
578
|
+
export function readSessionMeta(id: string): ClioSessionMeta {
|
|
579
|
+
return readMetaFile(join(findSessionDir(id), "meta.json"));
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
const APPEND_FSYNC_DEBOUNCE_MS = 500;
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* True when the file's last byte is a newline (or the file is empty or
|
|
586
|
+
* missing). A false result means a crash left a torn partial line that an
|
|
587
|
+
* O_APPEND writer must terminate before writing, or the next record would
|
|
588
|
+
* fuse onto the fragment and corrupt itself too.
|
|
589
|
+
*/
|
|
590
|
+
function endsWithNewline(path: string): boolean {
|
|
591
|
+
let size: number;
|
|
592
|
+
try {
|
|
593
|
+
size = statSync(path).size;
|
|
594
|
+
} catch {
|
|
595
|
+
return true;
|
|
596
|
+
}
|
|
597
|
+
if (size === 0) return true;
|
|
598
|
+
const fd = openSync(path, "r");
|
|
599
|
+
try {
|
|
600
|
+
const buf = Buffer.alloc(1);
|
|
601
|
+
readSync(fd, buf, 0, 1, size - 1);
|
|
602
|
+
return buf[0] === 0x0a;
|
|
603
|
+
} finally {
|
|
604
|
+
closeSync(fd);
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
/**
|
|
609
|
+
* Durably append one entry to an existing session JSONL file without reading
|
|
610
|
+
* or replacing its prior contents. This is the off-current counterpart to the
|
|
611
|
+
* long-lived writer: a torn final fragment is terminated and left visible to
|
|
612
|
+
* the tolerant reader, then the new record is written through O_APPEND and
|
|
613
|
+
* fsynced before returning.
|
|
614
|
+
*/
|
|
615
|
+
export function appendSessionFileEntry(targetPath: string, entry: unknown): void {
|
|
616
|
+
const appendPath = recoverJsonlTargetIfMissing(targetPath);
|
|
617
|
+
if (appendPath === null) throw new Error(`session JSONL file not found: ${targetPath}`);
|
|
618
|
+
const serialized = JSON.stringify(entry);
|
|
619
|
+
if (serialized === undefined) throw new Error("session JSONL entry is not serializable");
|
|
620
|
+
const line = Buffer.from(`${endsWithNewline(appendPath) ? "" : "\n"}${serialized}\n`, "utf8");
|
|
621
|
+
const fd = openSync(appendPath, fsConstants.O_WRONLY | fsConstants.O_APPEND);
|
|
622
|
+
try {
|
|
623
|
+
const written = writeSync(fd, line);
|
|
624
|
+
if (written !== line.length) {
|
|
625
|
+
throw new Error(`short session JSONL append: wrote ${written} of ${line.length} bytes`);
|
|
626
|
+
}
|
|
627
|
+
fsyncSync(fd);
|
|
628
|
+
} finally {
|
|
629
|
+
closeSync(fd);
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
function createWriter(
|
|
634
|
+
meta: ClioSessionMeta,
|
|
635
|
+
initialTree: SessionTreeNode[],
|
|
636
|
+
initialFileEntries: ReadonlyArray<unknown>,
|
|
637
|
+
headerOptions: { parentSession?: string; parentTurnId?: string } = {},
|
|
638
|
+
): ClioSessionWriter {
|
|
639
|
+
const paths = sessionPaths(meta);
|
|
640
|
+
const tree: SessionTreeNode[] = [...initialTree];
|
|
641
|
+
const fileEntries = ensureSessionHeader(meta, initialFileEntries, headerOptions);
|
|
642
|
+
let closed = false;
|
|
643
|
+
let appendFd: number | null = null;
|
|
644
|
+
let fsyncTimer: NodeJS.Timeout | null = null;
|
|
645
|
+
|
|
646
|
+
// One-time normalization for resumes of pre-header files: rewrite once so
|
|
647
|
+
// fd-appended lines land after a header. Disk and memory match from here on.
|
|
648
|
+
if (!isSessionJsonlHeader(initialFileEntries[0])) {
|
|
649
|
+
writeJsonlFileAtomic(paths.current, fileEntries);
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
function openAppendFd(): number {
|
|
653
|
+
if (appendFd !== null) return appendFd;
|
|
654
|
+
const tornTail = !endsWithNewline(paths.current);
|
|
655
|
+
appendFd = openSync(paths.current, "a");
|
|
656
|
+
// Terminating the fragment keeps the reader's torn-tail behavior:
|
|
657
|
+
// it skips exactly one invalid line with a warning.
|
|
658
|
+
if (tornTail) writeSync(appendFd, "\n");
|
|
659
|
+
return appendFd;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
function scheduleFsync(): void {
|
|
663
|
+
if (fsyncTimer !== null) return;
|
|
664
|
+
fsyncTimer = setTimeout(() => {
|
|
665
|
+
fsyncTimer = null;
|
|
666
|
+
if (appendFd === null) return;
|
|
667
|
+
try {
|
|
668
|
+
fsyncSync(appendFd);
|
|
669
|
+
} catch {
|
|
670
|
+
// A concurrent close already flushed and released the fd.
|
|
671
|
+
}
|
|
672
|
+
}, APPEND_FSYNC_DEBOUNCE_MS);
|
|
673
|
+
fsyncTimer.unref?.();
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
function closeAppendFd(opts: { flush: boolean }): void {
|
|
677
|
+
if (fsyncTimer !== null) {
|
|
678
|
+
clearTimeout(fsyncTimer);
|
|
679
|
+
fsyncTimer = null;
|
|
680
|
+
}
|
|
681
|
+
if (appendFd === null) return;
|
|
682
|
+
try {
|
|
683
|
+
if (opts.flush) fsyncSync(appendFd);
|
|
684
|
+
} finally {
|
|
685
|
+
closeSync(appendFd);
|
|
686
|
+
appendFd = null;
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
function appendLine(entry: unknown): void {
|
|
691
|
+
const serialized = JSON.stringify(entry);
|
|
692
|
+
if (serialized === undefined) {
|
|
693
|
+
throw new Error("session JSONL entry is not serializable");
|
|
694
|
+
}
|
|
695
|
+
writeSync(openAppendFd(), `${serialized}\n`);
|
|
696
|
+
scheduleFsync();
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
return {
|
|
700
|
+
append(turn: ClioTurnRecord): void {
|
|
701
|
+
if (closed) throw new Error("session writer closed");
|
|
702
|
+
const record = recordFromTurn(turn);
|
|
703
|
+
appendLine(record);
|
|
704
|
+
fileEntries.push(record);
|
|
705
|
+
tree.push({
|
|
706
|
+
id: turn.id,
|
|
707
|
+
parentId: turn.parentId,
|
|
708
|
+
at: turn.at,
|
|
709
|
+
kind: turn.kind,
|
|
710
|
+
});
|
|
711
|
+
},
|
|
712
|
+
appendEntry(entry: unknown, opts?: { treeNode?: SessionTreeNode }): void {
|
|
713
|
+
if (closed) throw new Error("session writer closed");
|
|
714
|
+
appendLine(entry);
|
|
715
|
+
fileEntries.push(entry);
|
|
716
|
+
if (opts?.treeNode) tree.push(opts.treeNode);
|
|
717
|
+
},
|
|
718
|
+
replaceEntries(entries: ReadonlyArray<unknown>): void {
|
|
719
|
+
if (closed) throw new Error("session writer closed");
|
|
720
|
+
// The rename below replaces the inode; the held fd would keep
|
|
721
|
+
// appending to the orphaned old file. Drop it, reopen lazily.
|
|
722
|
+
closeAppendFd({ flush: false });
|
|
723
|
+
const existingHeader = fileEntries.find(isSessionJsonlHeader);
|
|
724
|
+
const body = entries.filter((entry) => !isSessionJsonlHeader(entry));
|
|
725
|
+
const nextEntries = existingHeader ? [existingHeader, ...body] : ensureSessionHeader(meta, body, headerOptions);
|
|
726
|
+
writeJsonlFileAtomic(paths.current, nextEntries);
|
|
727
|
+
fileEntries.length = 0;
|
|
728
|
+
fileEntries.push(...nextEntries);
|
|
729
|
+
const recoveredTree = treeFromFileEntries(nextEntries);
|
|
730
|
+
if (recoveredTree.length > 0) {
|
|
731
|
+
tree.length = 0;
|
|
732
|
+
tree.push(...recoveredTree);
|
|
733
|
+
}
|
|
734
|
+
},
|
|
735
|
+
async persistTree(): Promise<void> {
|
|
736
|
+
// Checkpoint: make appended lines durable alongside the tree.
|
|
737
|
+
if (appendFd !== null) fsyncSync(appendFd);
|
|
738
|
+
// `paths` was resolved at construction, but atomicWrite mkdirs the
|
|
739
|
+
// session directory again, so an uninstall that has already removed the
|
|
740
|
+
// state root would be undone here. Fsyncing the held fd first is safe
|
|
741
|
+
// either way: it writes into an unlinked inode and creates nothing.
|
|
742
|
+
if (stateRootRemoved()) return;
|
|
743
|
+
atomicWrite(paths.tree, JSON.stringify(tree, null, 2));
|
|
744
|
+
},
|
|
745
|
+
flushAppends(): void {
|
|
746
|
+
if (appendFd !== null) fsyncSync(appendFd);
|
|
747
|
+
},
|
|
748
|
+
async close(): Promise<void> {
|
|
749
|
+
if (closed) return;
|
|
750
|
+
closeAppendFd({ flush: true });
|
|
751
|
+
// Closed regardless: the writer is done either way, and a removed state
|
|
752
|
+
// root must not get tree.json and meta.json written back into it.
|
|
753
|
+
closed = true;
|
|
754
|
+
if (stateRootRemoved()) return;
|
|
755
|
+
atomicWrite(paths.tree, JSON.stringify(tree, null, 2));
|
|
756
|
+
const ended: ClioSessionMeta = { ...meta, endedAt: new Date().toISOString() };
|
|
757
|
+
atomicWrite(paths.meta, JSON.stringify(ended, null, 2));
|
|
758
|
+
meta.endedAt = ended.endedAt;
|
|
759
|
+
},
|
|
760
|
+
};
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
export function createSession(input: {
|
|
764
|
+
cwd: string;
|
|
765
|
+
model?: string | null;
|
|
766
|
+
target?: string | null;
|
|
767
|
+
initialEntries?: ReadonlyArray<unknown>;
|
|
768
|
+
initialTree?: ReadonlyArray<SessionTreeNode>;
|
|
769
|
+
parentSession?: string;
|
|
770
|
+
parentTurnId?: string;
|
|
771
|
+
}): {
|
|
772
|
+
meta: ClioSessionMeta;
|
|
773
|
+
writer: ClioSessionWriter;
|
|
774
|
+
} {
|
|
775
|
+
const meta = buildMeta(input);
|
|
776
|
+
const paths = sessionPaths(meta);
|
|
777
|
+
atomicWrite(paths.meta, JSON.stringify(meta, null, 2));
|
|
778
|
+
const headerOptions: { parentSession?: string; parentTurnId?: string } = {};
|
|
779
|
+
if (input.parentSession !== undefined) headerOptions.parentSession = input.parentSession;
|
|
780
|
+
if (input.parentTurnId !== undefined) headerOptions.parentTurnId = input.parentTurnId;
|
|
781
|
+
const initialEntries = ensureSessionHeader(meta, input.initialEntries ?? [], headerOptions);
|
|
782
|
+
const initialTree = [...(input.initialTree ?? [])];
|
|
783
|
+
writeJsonlFileAtomic(paths.current, initialEntries);
|
|
784
|
+
atomicWrite(paths.tree, JSON.stringify(initialTree, null, 2));
|
|
785
|
+
const writer = createWriter(meta, initialTree, initialEntries, headerOptions);
|
|
786
|
+
return { meta, writer };
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
export function openSession(id: string): ClioSessionReader {
|
|
790
|
+
const dir = findSessionDir(id);
|
|
791
|
+
const metaPath = join(dir, "meta.json");
|
|
792
|
+
const meta = readMetaFile(metaPath);
|
|
793
|
+
const currentPath = join(dir, "current.jsonl");
|
|
794
|
+
const fileEntries = readSessionFileEntries(currentPath);
|
|
795
|
+
const turns = fileEntries.filter((entry) => !isSessionJsonlHeader(entry));
|
|
796
|
+
const header = fileEntries.find(isSessionJsonlHeader) ?? null;
|
|
797
|
+
const tree = recoverTreeFromJsonl(readTreeFile(join(dir, "tree.json")), fileEntries);
|
|
798
|
+
return {
|
|
799
|
+
meta(): ClioSessionMeta {
|
|
800
|
+
return meta;
|
|
801
|
+
},
|
|
802
|
+
turns(): ReadonlyArray<unknown> {
|
|
803
|
+
return turns;
|
|
804
|
+
},
|
|
805
|
+
fileEntries(): ReadonlyArray<unknown> {
|
|
806
|
+
return fileEntries;
|
|
807
|
+
},
|
|
808
|
+
header(): ClioSessionJsonlHeader | null {
|
|
809
|
+
return header;
|
|
810
|
+
},
|
|
811
|
+
tree(): ReadonlyArray<SessionTreeNode> {
|
|
812
|
+
return tree;
|
|
813
|
+
},
|
|
814
|
+
};
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
export function resumeSession(id: string): {
|
|
818
|
+
meta: ClioSessionMeta;
|
|
819
|
+
writer: ClioSessionWriter;
|
|
820
|
+
tree: ReadonlyArray<SessionTreeNode>;
|
|
821
|
+
} {
|
|
822
|
+
const dir = findSessionDir(id);
|
|
823
|
+
const metaPath = join(dir, "meta.json");
|
|
824
|
+
const meta = readMetaFile(metaPath);
|
|
825
|
+
// resume reopens an active session; clear endedAt if it was set by a prior close
|
|
826
|
+
if (meta.endedAt !== null) {
|
|
827
|
+
meta.endedAt = null;
|
|
828
|
+
atomicWrite(metaPath, JSON.stringify(meta, null, 2));
|
|
829
|
+
}
|
|
830
|
+
const existingFileEntries = readSessionFileEntries(join(dir, "current.jsonl"));
|
|
831
|
+
const existingTree = recoverTreeFromJsonl(readTreeFile(join(dir, "tree.json")), existingFileEntries);
|
|
832
|
+
const writer = createWriter(meta, existingTree, existingFileEntries);
|
|
833
|
+
return { meta, writer, tree: existingTree };
|
|
834
|
+
}
|