@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,1104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured renderer for tool-execution chat segments (Slice A of the
|
|
3
|
+
* pi-coding-agent parity work). pi-coding-agent renders every tool call as
|
|
4
|
+
* a header line plus an optional args body and a result/error block. Clio
|
|
5
|
+
* previously emitted a single inline string per call, which collapsed
|
|
6
|
+
* structure (multi-line outputs vanished) and prevented the live and replay
|
|
7
|
+
* paths from sharing one renderer.
|
|
8
|
+
*
|
|
9
|
+
* Pure functions: no I/O, no console writes, no module-level mutable state.
|
|
10
|
+
* The chat-panel tool segment renderer (live path) and the chat-renderer
|
|
11
|
+
* orphan tool-result fallback (replay path) both consume this module so the
|
|
12
|
+
* two surfaces stay byte-identical.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { sanitizeCallTargetText } from "../../domains/safety/call-target.js";
|
|
16
|
+
import { visibleWidth, wrapTextWithAnsi } from "../../engine/tui.js";
|
|
17
|
+
import { clioTheme, formatCompactMs, GLYPH } from "../theme/index.js";
|
|
18
|
+
import { type DiffRenderInput, renderUnifiedDiff } from "./diff.js";
|
|
19
|
+
import { tryRenderJson, tryRenderXml } from "./structured.js";
|
|
20
|
+
|
|
21
|
+
const theme = clioTheme();
|
|
22
|
+
const dim = (text: string): string => theme.fg("dim", text);
|
|
23
|
+
const red = (text: string): string => theme.fg("error", text);
|
|
24
|
+
const green = (text: string): string => theme.fg("success", text);
|
|
25
|
+
const yellow = (text: string): string => theme.fg("warning", text);
|
|
26
|
+
const cyan = (text: string): string => theme.fg("accent", text);
|
|
27
|
+
const cyanBold = (text: string): string => theme.style("accent", text, { bold: true });
|
|
28
|
+
|
|
29
|
+
// Visible width of the rail prefix is 2 columns (`│ `). Width budgets and
|
|
30
|
+
// diff renderers compute against the visible length, not the styled length,
|
|
31
|
+
// so the constant is kept as the plain-text representation.
|
|
32
|
+
const BODY_INDENT_PLAIN = "│ ";
|
|
33
|
+
const BODY_INDENT_VISIBLE_WIDTH = 2;
|
|
34
|
+
const HEADER_PREFIX_PLAIN = "▸ ";
|
|
35
|
+
const ARG_PREVIEW_LIMIT = 60;
|
|
36
|
+
const WEB_FETCH_ARG_PREVIEW_LIMIT = 140;
|
|
37
|
+
const RESULT_PREVIEW_LIMIT = 4000;
|
|
38
|
+
const FULL_RESULT_PREVIEW_LIMIT = 60_000;
|
|
39
|
+
const FULL_RESULT_ROW_LIMIT = 120;
|
|
40
|
+
const STREAMING_RESULT_ROW_LIMIT = 20;
|
|
41
|
+
const ARGS_BODY_LINE_LIMIT = 24;
|
|
42
|
+
const STATUS_OK_GLYPH = GLYPH.ok;
|
|
43
|
+
const STATUS_ERROR_GLYPH = GLYPH.error;
|
|
44
|
+
|
|
45
|
+
// Hoisted rail prefixes. `indentAndWrap` would otherwise allocate two fresh
|
|
46
|
+
// styled strings per rendered line; by precomputing the dim and error variants
|
|
47
|
+
// once at module scope, repeated rendering of long result blocks stays cheap.
|
|
48
|
+
const RAIL_DIM = dim(BODY_INDENT_PLAIN);
|
|
49
|
+
const RAIL_ERROR = red(BODY_INDENT_PLAIN);
|
|
50
|
+
|
|
51
|
+
export interface ToolExecutionStart {
|
|
52
|
+
toolCallId: string;
|
|
53
|
+
toolName: string;
|
|
54
|
+
args: unknown;
|
|
55
|
+
/** Live elapsed time supplied by the panel for running segments. */
|
|
56
|
+
elapsedMs?: number | undefined;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface ToolExecutionFinished {
|
|
60
|
+
toolCallId: string;
|
|
61
|
+
toolName: string;
|
|
62
|
+
args?: unknown;
|
|
63
|
+
result: unknown;
|
|
64
|
+
isError: boolean;
|
|
65
|
+
durationMs?: number | undefined;
|
|
66
|
+
/** Persisted summary (bytes, truncated, offloadPath, observation counts). */
|
|
67
|
+
resultSummary?: Record<string, unknown> | undefined;
|
|
68
|
+
/** Honest terminal outcome for synthetic/or permission-blocked calls. */
|
|
69
|
+
outcome?: "blocked" | "aborted" | "orphaned" | undefined;
|
|
70
|
+
/**
|
|
71
|
+
* Why admission refused this call, from the registry verdict. A blocked row
|
|
72
|
+
* that states only that something was refused leaves the operator, and the
|
|
73
|
+
* model reading the same transcript, to guess at the rule.
|
|
74
|
+
*/
|
|
75
|
+
blockReason?: string | undefined;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface ToolBodyRenderOptions {
|
|
79
|
+
/**
|
|
80
|
+
* Render the full tool result body with no middle-elision and no character
|
|
81
|
+
* truncation. The live view keeps bodies bounded so a single tool cannot
|
|
82
|
+
* flood the pane; `/export` sets this so the written transcript reproduces
|
|
83
|
+
* the complete tool output the model actually received.
|
|
84
|
+
*/
|
|
85
|
+
unbounded?: boolean;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** Row cap for a tool body: unbounded lifts both the row and char limits. */
|
|
89
|
+
function resultRowLimit(opts: ToolBodyRenderOptions): number {
|
|
90
|
+
return opts.unbounded === true ? Number.POSITIVE_INFINITY : FULL_RESULT_ROW_LIMIT;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function resultCharLimit(opts: ToolBodyRenderOptions): number {
|
|
94
|
+
return opts.unbounded === true ? Number.POSITIVE_INFINITY : FULL_RESULT_PREVIEW_LIMIT;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Counts UTF-16 code units; can split a surrogate pair on non-BMP input. Acceptable for ASCII paths/commands.
|
|
98
|
+
function truncate(value: string, limit: number): string {
|
|
99
|
+
if (value.length <= limit) return value;
|
|
100
|
+
const cut = Math.max(0, limit - 3);
|
|
101
|
+
return `${value.slice(0, cut)}...`;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
105
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const SECRET_KEY_RE =
|
|
109
|
+
/(?:api[-_]?key|access[-_]?key|auth(?:orization)?|credential|password|private[-_]?key|secret|token)/iu;
|
|
110
|
+
const ENV_KEY_RE = /^env(?:ironment)?$/iu;
|
|
111
|
+
const SECRET_STRING_RE = /(https?:\/\/[^\s/@]+:)[^\s/@]+@/giu;
|
|
112
|
+
const SECRET_URL_PARAM_RE =
|
|
113
|
+
/([?&](?:api[-_]?key|access[-_]?token|auth(?:orization)?|credential|password|secret|token)[^=\s]*=)[^&#\s]+/giu;
|
|
114
|
+
const SECRET_ASSIGNMENT_RE =
|
|
115
|
+
/(?<![A-Z0-9_])((?:[A-Z0-9_]*(?:ACCESS|API|AUTH|CREDENTIAL|KEY|PASS(?:WORD)?|PRIVATE|SECRET|TOKEN)[A-Z0-9_]*)=)[^\s;&|]+/giu;
|
|
116
|
+
const SECRET_FLAG_RE =
|
|
117
|
+
/(--?(?:[a-z0-9-]*(?:api[-_]?key|access[-_]?token|auth(?:orization)?|credential|password|secret|token)[a-z0-9-]*))(=|\s+)([^\s;&|]+)/giu;
|
|
118
|
+
|
|
119
|
+
function redactSecretString(value: string): string {
|
|
120
|
+
return value
|
|
121
|
+
.replace(SECRET_STRING_RE, "$1[redacted]@")
|
|
122
|
+
.replace(SECRET_URL_PARAM_RE, "$1[redacted]")
|
|
123
|
+
.replace(SECRET_ASSIGNMENT_RE, "$1[redacted]")
|
|
124
|
+
.replace(SECRET_FLAG_RE, "$1$2[redacted]");
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function redactEnvironmentValue(value: unknown, depth: number): unknown {
|
|
128
|
+
if (depth > 8) return "[redacted nested values]";
|
|
129
|
+
if (typeof value === "string") return "[redacted]";
|
|
130
|
+
if (Array.isArray(value)) return value.map((item) => redactEnvironmentValue(item, depth + 1));
|
|
131
|
+
if (!isPlainObject(value)) return value;
|
|
132
|
+
const out: Record<string, unknown> = {};
|
|
133
|
+
for (const [childKey, childValue] of Object.entries(value)) {
|
|
134
|
+
out[childKey] = redactEnvironmentValue(childValue, depth + 1);
|
|
135
|
+
}
|
|
136
|
+
return out;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** Project tool arguments for display only; execution and receipts retain the original values. */
|
|
140
|
+
export function redactToolArgs(value: unknown, key = "", depth = 0): unknown {
|
|
141
|
+
if (SECRET_KEY_RE.test(key)) return "[redacted]";
|
|
142
|
+
if (ENV_KEY_RE.test(key)) return redactEnvironmentValue(value, depth);
|
|
143
|
+
if (typeof value === "string") return redactSecretString(value);
|
|
144
|
+
if (depth > 8) return "[redacted nested values]";
|
|
145
|
+
if (Array.isArray(value)) return value.map((item) => redactToolArgs(item, key, depth + 1));
|
|
146
|
+
if (!isPlainObject(value)) return value;
|
|
147
|
+
const out: Record<string, unknown> = {};
|
|
148
|
+
for (const [childKey, childValue] of Object.entries(value)) {
|
|
149
|
+
out[childKey] = redactToolArgs(childValue, childKey, depth + 1);
|
|
150
|
+
}
|
|
151
|
+
return out;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function readStringField(args: unknown, key: string): string | null {
|
|
155
|
+
if (!isPlainObject(args)) return null;
|
|
156
|
+
const value = args[key];
|
|
157
|
+
return typeof value === "string" ? redactSecretString(value) : null;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function isEmptyArgs(args: unknown): boolean {
|
|
161
|
+
if (args === undefined || args === null) return true;
|
|
162
|
+
if (isPlainObject(args) && Object.keys(args).length === 0) return true;
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function jsonStringifySafe(value: unknown): string {
|
|
167
|
+
try {
|
|
168
|
+
const text = JSON.stringify(value);
|
|
169
|
+
return typeof text === "string" ? text : String(value);
|
|
170
|
+
} catch {
|
|
171
|
+
return String(value);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function unquoteShellScript(value: string): string {
|
|
176
|
+
const trimmed = value.trim();
|
|
177
|
+
if (trimmed.length < 2) return trimmed;
|
|
178
|
+
const quote = trimmed.charAt(0);
|
|
179
|
+
if ((quote !== "'" && quote !== '"') || trimmed.charAt(trimmed.length - 1) !== quote) return trimmed;
|
|
180
|
+
const inner = trimmed.slice(1, -1);
|
|
181
|
+
if (quote === "'") return inner.replace(/'\\''/g, "'");
|
|
182
|
+
return inner.replace(/\\"/g, '"').replace(/\\`/g, "`").replace(/\\\$/g, "$").replace(/\\\\/g, "\\");
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function stripShellWrapperForDisplay(command: string): string {
|
|
186
|
+
const trimmed = command.trim();
|
|
187
|
+
const match = /^(?:(?:\/(?:usr\/)?bin\/)?(?:bash|zsh|sh))\s+-lc\s+([\s\S]+)$/u.exec(trimmed);
|
|
188
|
+
if (!match?.[1]) return command;
|
|
189
|
+
return unquoteShellScript(match[1]);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function displayArg(toolName: string, value: string): string {
|
|
193
|
+
return toolName === "bash" ? stripShellWrapperForDisplay(value) : value;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Optional-duration guard around the single duration formatter. formatCompactMs
|
|
198
|
+
* is the one formatter for elapsed time, but these call sites carry a
|
|
199
|
+
* `number | undefined` that may be missing, non-finite, or negative and must
|
|
200
|
+
* then omit the ` · <dur>` segment entirely. Returns null in those cases and
|
|
201
|
+
* delegates every real value to formatCompactMs, so durations render as
|
|
202
|
+
* `860ms`, `4.2s`, `42s`, and `1m36s` with no zero padding on the seconds.
|
|
203
|
+
*/
|
|
204
|
+
function optionalCompactMs(durationMs: number | undefined): string | null {
|
|
205
|
+
if (durationMs === undefined || !Number.isFinite(durationMs) || durationMs < 0) return null;
|
|
206
|
+
return formatCompactMs(durationMs);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function bashExitCodeFromResult(result: unknown): string | null {
|
|
210
|
+
const unwrapped = unwrapResultEnvelope(result);
|
|
211
|
+
const text = typeof unwrapped === "string" ? unwrapped : jsonStringifySafe(unwrapped);
|
|
212
|
+
const match =
|
|
213
|
+
/\bcommand failed \(exit (?<paren>[^)]+)\)/iu.exec(text) ??
|
|
214
|
+
/\bcommand exited with code (?<code>[0-9?]+)/iu.exec(text) ??
|
|
215
|
+
/\bexit (?<short>[0-9?]+)\b/iu.exec(text);
|
|
216
|
+
return match?.groups?.paren ?? match?.groups?.code ?? match?.groups?.short ?? null;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Map of known tools to their canonical "primary" arg field. When the arg is
|
|
221
|
+
* a string the header summarises it directly and the args body is suppressed
|
|
222
|
+
* because echoing `{"path": "..."}` next to `tool: read(...)` is duplicate
|
|
223
|
+
* noise. Tools not in this map (or with an unexpected arg shape) fall back
|
|
224
|
+
* to a JSON-dump summary plus the full args body.
|
|
225
|
+
*/
|
|
226
|
+
const PRIMARY_ARG_FIELD: Record<string, string> = {
|
|
227
|
+
read: "path",
|
|
228
|
+
edit: "path",
|
|
229
|
+
write: "path",
|
|
230
|
+
ls: "path",
|
|
231
|
+
bash: "command",
|
|
232
|
+
grep: "pattern",
|
|
233
|
+
find: "pattern",
|
|
234
|
+
web_fetch: "url",
|
|
235
|
+
git: "op",
|
|
236
|
+
verify: "check",
|
|
237
|
+
code_nav: "query",
|
|
238
|
+
context: "scope",
|
|
239
|
+
artifact: "kind",
|
|
240
|
+
monitor: "run_id",
|
|
241
|
+
steer: "run_id",
|
|
242
|
+
tasks: "action",
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Returns the captured primary-arg string when the header successfully used a
|
|
247
|
+
* known tool's canonical arg, otherwise null. Drives the args-body suppression
|
|
248
|
+
* so `tool: read(README.md)` does not get followed by `{"path": "README.md"}`.
|
|
249
|
+
*/
|
|
250
|
+
function capturedPrimaryArg(toolName: string, args: unknown): string | null {
|
|
251
|
+
const field = PRIMARY_ARG_FIELD[toolName];
|
|
252
|
+
if (field === undefined) return null;
|
|
253
|
+
return readStringField(args, field);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Pick the most informative single-line summary of a tool's arguments for
|
|
258
|
+
* the header line. Known tools have a canonical "primary" arg (path,
|
|
259
|
+
* command, pattern, url); unknown tools or unexpected shapes fall back to a
|
|
260
|
+
* truncated JSON dump. Returns an empty string when args are absent so the
|
|
261
|
+
* header renders as `tool: <name>()`.
|
|
262
|
+
*/
|
|
263
|
+
function summarizeWebFetchArgs(args: unknown): string {
|
|
264
|
+
if (!isPlainObject(args)) return summarizeArgs("", args);
|
|
265
|
+
const compact: Record<string, unknown> = {};
|
|
266
|
+
for (const key of ["url", "format", "max_bytes", "timeout_ms", "method"] as const) {
|
|
267
|
+
if (args[key] !== undefined) compact[key] = args[key];
|
|
268
|
+
}
|
|
269
|
+
return truncate(jsonStringifySafe(Object.keys(compact).length > 0 ? compact : args), WEB_FETCH_ARG_PREVIEW_LIMIT);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function summarizeArgs(toolName: string, args: unknown): string {
|
|
273
|
+
if (isEmptyArgs(args)) return "";
|
|
274
|
+
const safeArgs = redactToolArgs(args);
|
|
275
|
+
if (toolName === "web_fetch") return summarizeWebFetchArgs(safeArgs);
|
|
276
|
+
const primary = capturedPrimaryArg(toolName, args);
|
|
277
|
+
if (primary !== null) return truncate(displayArg(toolName, primary), ARG_PREVIEW_LIMIT);
|
|
278
|
+
return truncate(jsonStringifySafe(safeArgs), ARG_PREVIEW_LIMIT);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Compact resource-read classification. Reads of skill/handbook/agent
|
|
283
|
+
* instruction files and docs pages collapse to one labeled line and never
|
|
284
|
+
* auto-expand; their bodies are reference material, not task output.
|
|
285
|
+
*/
|
|
286
|
+
export function classifyResourceRead(toolName: string, args: unknown): string | null {
|
|
287
|
+
if (toolName !== "read") return null;
|
|
288
|
+
const path = readStringField(args, "path");
|
|
289
|
+
if (path === null) return null;
|
|
290
|
+
const normalized = path.replace(/\\/g, "/");
|
|
291
|
+
const base = normalized.split("/").pop() ?? "";
|
|
292
|
+
if (base === "SKILL.md") return "skill";
|
|
293
|
+
if (base === "CLIO-CODER.md") return "handbook";
|
|
294
|
+
if (base === "AGENTS.md") return "agents";
|
|
295
|
+
if (/(^|\/)docs\//.test(normalized)) return "docs";
|
|
296
|
+
return null;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
function detailsOf(result: unknown): Record<string, unknown> | null {
|
|
300
|
+
if (!isPlainObject(result)) return null;
|
|
301
|
+
return isPlainObject(result.details) ? result.details : null;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
function observationOf(finished: ToolExecutionFinished): Record<string, unknown> | null {
|
|
305
|
+
const fromDetails = detailsOf(finished.result)?.observation;
|
|
306
|
+
if (isPlainObject(fromDetails)) return fromDetails;
|
|
307
|
+
const fromSummary = finished.resultSummary?.observation;
|
|
308
|
+
return isPlainObject(fromSummary) ? fromSummary : null;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
function numberField(record: Record<string, unknown> | null, key: string): number | null {
|
|
312
|
+
const value = record?.[key];
|
|
313
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
function stringField(record: Record<string, unknown> | null, key: string): string | null {
|
|
317
|
+
const value = record?.[key];
|
|
318
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
function formatBytes(bytes: number): string {
|
|
322
|
+
if (bytes < 1024) return `${bytes}B`;
|
|
323
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;
|
|
324
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
function countSummary(observation: Record<string, unknown>): string | null {
|
|
328
|
+
const unit = stringField(observation, "unit") ?? "results";
|
|
329
|
+
const shown = numberField(observation, "shownCount");
|
|
330
|
+
if (shown === null) return null;
|
|
331
|
+
const total = numberField(observation, "totalCount");
|
|
332
|
+
if (total === null) return `${shown}+ ${unit}`;
|
|
333
|
+
if (total === shown) return `${shown} ${unit}`;
|
|
334
|
+
return `${shown}/${total} ${unit}`;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Outcome facts for the collapsed ledger line, derived from the observation
|
|
339
|
+
* envelope (OBSERVE plane), the exec record (git/verify), or the dispatch
|
|
340
|
+
* receipt counts. Returns null when the result carries no recognizable facts.
|
|
341
|
+
*/
|
|
342
|
+
function outcomeSummary(finished: ToolExecutionFinished): string | null {
|
|
343
|
+
const observation = observationOf(finished);
|
|
344
|
+
if (observation !== null) {
|
|
345
|
+
if (finished.toolName === "read") {
|
|
346
|
+
const shown = numberField(observation, "shownCount");
|
|
347
|
+
const total = numberField(observation, "totalCount");
|
|
348
|
+
if (shown !== null && total !== null) {
|
|
349
|
+
const offsetRaw = isPlainObject(finished.args) ? finished.args.offset : undefined;
|
|
350
|
+
const start = typeof offsetRaw === "number" && offsetRaw > 0 ? Math.floor(offsetRaw) : 1;
|
|
351
|
+
return shown > 0 ? `lines ${start}-${start + shown - 1} of ${total}` : `0 of ${total} lines`;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
return countSummary(observation);
|
|
355
|
+
}
|
|
356
|
+
const details = detailsOf(finished.result);
|
|
357
|
+
if (finished.toolName === "git" || finished.toolName === "verify") {
|
|
358
|
+
const exitCode = numberField(details, "exitCode");
|
|
359
|
+
if (exitCode !== null) return `exit ${exitCode}`;
|
|
360
|
+
const status = stringField(details, "status");
|
|
361
|
+
if (status !== null) return status;
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
364
|
+
if (finished.toolName === "dispatch") {
|
|
365
|
+
const receipts = numberField(details, "receiptCount");
|
|
366
|
+
const failed = numberField(details, "failedCount") ?? 0;
|
|
367
|
+
if (receipts !== null) return `${receipts} task${receipts === 1 ? "" : "s"} -> ${receipts - failed} ok`;
|
|
368
|
+
return null;
|
|
369
|
+
}
|
|
370
|
+
if (finished.toolName === "tasks") {
|
|
371
|
+
const rawCounts = details?.counts;
|
|
372
|
+
const counts = isPlainObject(rawCounts) ? rawCounts : null;
|
|
373
|
+
const completed = numberField(counts, "completed");
|
|
374
|
+
const total = numberField(counts, "total");
|
|
375
|
+
if (completed !== null && total !== null) {
|
|
376
|
+
const blocked = numberField(counts, "blocked") ?? 0;
|
|
377
|
+
return `${completed}/${total} done${blocked > 0 ? ` · ${blocked} blocked` : ""}`;
|
|
378
|
+
}
|
|
379
|
+
return null;
|
|
380
|
+
}
|
|
381
|
+
return null;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
function offloadPathOf(finished: ToolExecutionFinished): string | null {
|
|
385
|
+
const observation = observationOf(finished);
|
|
386
|
+
const fromObservation = stringField(observation, "offloadPath");
|
|
387
|
+
if (fromObservation !== null) return fromObservation;
|
|
388
|
+
const summary = finished.resultSummary ?? null;
|
|
389
|
+
const fromSummary = stringField(summary, "offloadPath");
|
|
390
|
+
if (fromSummary !== null) return fromSummary;
|
|
391
|
+
const resultSize = detailsOf(finished.result)?.resultSize;
|
|
392
|
+
return isPlainObject(resultSize) ? stringField(resultSize, "offloadPath") : null;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
function shownBytesOf(finished: ToolExecutionFinished): number | null {
|
|
396
|
+
const observation = observationOf(finished);
|
|
397
|
+
const fromObservation = numberField(observation, "shownBytes");
|
|
398
|
+
if (fromObservation !== null) return fromObservation;
|
|
399
|
+
return numberField(finished.resultSummary ?? null, "bytes");
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* The dim ledger tail appended to a finished collapsed subline: outcome facts,
|
|
404
|
+
* then byte size (duration rides on the status glyph), then the offload path
|
|
405
|
+
* for truncated calls. One line of plain text carries signature and outcome
|
|
406
|
+
* when copied.
|
|
407
|
+
*/
|
|
408
|
+
function ledgerTail(finished: ToolExecutionFinished): { facts: string; offload: string } {
|
|
409
|
+
const parts: string[] = [];
|
|
410
|
+
const outcome = outcomeSummary(finished);
|
|
411
|
+
if (outcome !== null) parts.push(outcome);
|
|
412
|
+
const bytes = isNonExecutedOutcome(finished.outcome) ? null : shownBytesOf(finished);
|
|
413
|
+
if (bytes !== null && bytes > 0) parts.push(formatBytes(bytes));
|
|
414
|
+
const offloadPath = offloadPathOf(finished);
|
|
415
|
+
return {
|
|
416
|
+
facts: parts.length > 0 ? dim(` · ${parts.join(" · ")}`) : "",
|
|
417
|
+
offload: offloadPath !== null ? dim(` · full: ${offloadPath}`) : "",
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Marker for a call parked at admission awaiting operator approval. Rendered
|
|
423
|
+
* in place of the elapsed counter so a parked call never reads as executing
|
|
424
|
+
* work; the ⏸ glyph matches the footer's blocked phase.
|
|
425
|
+
*/
|
|
426
|
+
const AWAITING_APPROVAL_TAIL = ` ${yellow(GLYPH.phaseBlocked)}${dim(" awaiting approval")}`;
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* Subline for an in-flight call whose body is parked at the permission gate.
|
|
430
|
+
* No elapsed counter (nothing is running) and no status glyph (nothing has
|
|
431
|
+
* finished): the awaiting-approval tail is the segment's whole state.
|
|
432
|
+
*/
|
|
433
|
+
export function renderToolAwaitingApproval(call: ToolExecutionStart, width: number): string[] {
|
|
434
|
+
const parts = sublineParts({ toolCallId: call.toolCallId, toolName: call.toolName, args: call.args }, undefined, {});
|
|
435
|
+
return wrapSublineWithTail(parts.lead, AWAITING_APPROVAL_TAIL, width);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Header status: `undefined` when the call is still in flight (no glyph),
|
|
440
|
+
* `"ok"` for success (green check), `"error"` for failure (red cross). The
|
|
441
|
+
* glyph hangs off the right of the header line so the tool name + args read
|
|
442
|
+
* left-to-right without extra punctuation.
|
|
443
|
+
*/
|
|
444
|
+
type HeaderStatus = "ok" | "error" | undefined;
|
|
445
|
+
|
|
446
|
+
/** Keeps a refusal reason to one scannable clause on the status tail. */
|
|
447
|
+
const BLOCK_REASON_LIMIT = 72;
|
|
448
|
+
|
|
449
|
+
interface StatusMeta {
|
|
450
|
+
durationMs?: number | undefined;
|
|
451
|
+
exitCode?: string | null;
|
|
452
|
+
outcome?: ToolExecutionFinished["outcome"];
|
|
453
|
+
/** Refusal reason, rendered only alongside a non-executed outcome. */
|
|
454
|
+
blockReason?: string | undefined;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
function statusGlyph(status: HeaderStatus, meta: StatusMeta = {}): string {
|
|
458
|
+
if (status === undefined) return "";
|
|
459
|
+
const duration = optionalCompactMs(meta.durationMs);
|
|
460
|
+
const durationSuffix = duration ? dim(` · ${duration}`) : "";
|
|
461
|
+
if (status === "ok") return ` ${green(STATUS_OK_GLYPH)}${durationSuffix}`;
|
|
462
|
+
const exitSuffix = meta.exitCode ? dim(` (exit ${meta.exitCode})`) : "";
|
|
463
|
+
const outcomeSuffix = meta.outcome ? dim(` ${meta.outcome}`) : "";
|
|
464
|
+
// A refusal that names no rule tells the operator only that something was
|
|
465
|
+
// stopped. The reason rides the same tail as the outcome word so the
|
|
466
|
+
// collapsed subline and the expanded header state it identically.
|
|
467
|
+
const reason = meta.outcome !== undefined ? meta.blockReason?.trim() : undefined;
|
|
468
|
+
const reasonSuffix = reason ? dim(` · ${truncate(reason, BLOCK_REASON_LIMIT)}`) : "";
|
|
469
|
+
return ` ${red(STATUS_ERROR_GLYPH)}${outcomeSuffix}${reasonSuffix}${exitSuffix}${durationSuffix}`;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
function headerLine(toolName: string, args: unknown, status: HeaderStatus, meta: StatusMeta = {}): string {
|
|
473
|
+
const summary = summarizeArgs(toolName, args);
|
|
474
|
+
const head = `${dim(HEADER_PREFIX_PLAIN)}${cyanBold(toolName)}${dim("(")}${cyan(summary)}${dim(")")}`;
|
|
475
|
+
return `${head}${statusGlyph(status, meta)}`;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
function sublineLead(token: string, rest: string): string {
|
|
479
|
+
return `${cyanBold(token)}${rest}`;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
function styleSublineBody(body: string): string {
|
|
483
|
+
const match = /^(?<lead>[^ (]+)(?<rest>.*)$/u.exec(body);
|
|
484
|
+
if (match?.groups?.lead === undefined || match.groups.rest === undefined) return body;
|
|
485
|
+
return sublineLead(match.groups.lead, match.groups.rest);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
function buildUnknownToolBody(toolName: string, args: unknown): string {
|
|
489
|
+
return `${toolName}(${summarizeArgs(toolName, args)})`;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
function buildFieldSublineBody(
|
|
493
|
+
args: unknown,
|
|
494
|
+
key: string,
|
|
495
|
+
lead: string,
|
|
496
|
+
options: { wrapInBackticks?: boolean } = {},
|
|
497
|
+
): string | null {
|
|
498
|
+
const value = readStringField(args, key);
|
|
499
|
+
if (value === null) return null;
|
|
500
|
+
const preview = truncate(key === "command" ? stripShellWrapperForDisplay(value) : value, ARG_PREVIEW_LIMIT);
|
|
501
|
+
if (options.wrapInBackticks) return `${lead}\`${preview}\``;
|
|
502
|
+
return `${lead}${preview}`;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
function dispatchSublineBody(args: unknown): string | null {
|
|
506
|
+
if (!isPlainObject(args)) return null;
|
|
507
|
+
if (args.list === true) return "listing fleet agents";
|
|
508
|
+
const sharedAgent =
|
|
509
|
+
(typeof args.agent === "string" && args.agent.trim()) ||
|
|
510
|
+
(typeof args.agent_id === "string" && args.agent_id.trim()) ||
|
|
511
|
+
"coder";
|
|
512
|
+
let rawTasks: unknown = args.tasks;
|
|
513
|
+
if (typeof rawTasks === "string") {
|
|
514
|
+
const trimmed = rawTasks.trim();
|
|
515
|
+
if (trimmed.startsWith("[") || trimmed.startsWith("{")) {
|
|
516
|
+
try {
|
|
517
|
+
rawTasks = JSON.parse(trimmed) as unknown;
|
|
518
|
+
} catch {
|
|
519
|
+
// Keep the string as one plain task; dispatch itself reports malformed JSON.
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
const tasks = Array.isArray(rawTasks) ? rawTasks : rawTasks === undefined ? [] : [rawTasks];
|
|
524
|
+
if (tasks.length === 0) return null;
|
|
525
|
+
const first = tasks[0];
|
|
526
|
+
const record = isPlainObject(first) ? first : null;
|
|
527
|
+
const agent =
|
|
528
|
+
(record && typeof record.agent === "string" && record.agent.trim()) ||
|
|
529
|
+
(record && typeof record.agent_id === "string" && record.agent_id.trim()) ||
|
|
530
|
+
sharedAgent;
|
|
531
|
+
const taskText = typeof first === "string" ? first : record && typeof record.task === "string" ? record.task : "";
|
|
532
|
+
const taskPreview = truncate(sanitizeCallTargetText(taskText), ARG_PREVIEW_LIMIT);
|
|
533
|
+
const more = tasks.length > 1 ? ` +${tasks.length - 1} more` : "";
|
|
534
|
+
if (taskPreview.length === 0) return `dispatching ${tasks.length} task${tasks.length === 1 ? "" : "s"}${more}`;
|
|
535
|
+
return `dispatching ${agent}: ${taskPreview}${more}`;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
const SUBLINE_BODY_BUILDERS: Readonly<Record<string, (args: unknown) => string | null>> = {
|
|
539
|
+
read: (args) => buildFieldSublineBody(args, "path", "reading "),
|
|
540
|
+
edit: (args) => buildFieldSublineBody(args, "path", "editing "),
|
|
541
|
+
write: (args) => buildFieldSublineBody(args, "path", "writing "),
|
|
542
|
+
ls: (args) => buildFieldSublineBody(args, "path", "listing "),
|
|
543
|
+
bash: (args) => buildFieldSublineBody(args, "command", "running ", { wrapInBackticks: true }),
|
|
544
|
+
grep: (args) => buildFieldSublineBody(args, "pattern", "searching for ", { wrapInBackticks: true }),
|
|
545
|
+
find: (args) => buildFieldSublineBody(args, "pattern", "finding ", { wrapInBackticks: true }),
|
|
546
|
+
git: (args) => buildFieldSublineBody(args, "op", "git "),
|
|
547
|
+
verify: (args) => buildFieldSublineBody(args, "check", "verifying "),
|
|
548
|
+
code_nav: (args) => {
|
|
549
|
+
const mode = readStringField(args, "mode");
|
|
550
|
+
const query = readStringField(args, "query")?.trim() ?? "";
|
|
551
|
+
const queryPart = query.length > 0 ? ` \`${truncate(query, ARG_PREVIEW_LIMIT)}\`` : "";
|
|
552
|
+
if (mode !== null && mode.length > 0) return `navigating ${mode}${queryPart}`;
|
|
553
|
+
return queryPart.length > 0 ? `navigating${queryPart}` : null;
|
|
554
|
+
},
|
|
555
|
+
context: (args) => {
|
|
556
|
+
const scope = readStringField(args, "scope");
|
|
557
|
+
if (scope === null || scope.length === 0) return null;
|
|
558
|
+
const query = readStringField(args, "query")?.trim() ?? "";
|
|
559
|
+
const name = readStringField(args, "name")?.trim() ?? "";
|
|
560
|
+
if (scope === "docs" && query.length > 0) return `context docs \`${truncate(query, ARG_PREVIEW_LIMIT)}\``;
|
|
561
|
+
if (scope === "skills" && name.length > 0) return `context skills ${truncate(name, ARG_PREVIEW_LIMIT)}`;
|
|
562
|
+
return `context ${scope}`;
|
|
563
|
+
},
|
|
564
|
+
artifact: (args) => buildFieldSublineBody(args, "kind", "writing "),
|
|
565
|
+
monitor: (args) => buildFieldSublineBody(args, "run_id", "monitoring "),
|
|
566
|
+
steer: (args) => buildFieldSublineBody(args, "run_id", "steering "),
|
|
567
|
+
tasks: (args) => {
|
|
568
|
+
const action = readStringField(args, "action");
|
|
569
|
+
if (action === null) return null;
|
|
570
|
+
if (action === "plan") {
|
|
571
|
+
const title = readStringField(args, "title");
|
|
572
|
+
return title === null ? "tasks plan" : `tasks plan ${truncate(`"${title}"`, ARG_PREVIEW_LIMIT)}`;
|
|
573
|
+
}
|
|
574
|
+
const id = readStringField(args, "id");
|
|
575
|
+
return id === null ? `tasks ${action}` : `tasks ${action} ${id}`;
|
|
576
|
+
},
|
|
577
|
+
dispatch: dispatchSublineBody,
|
|
578
|
+
};
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* Per-tool subline templates. Maps a tool name to a function that builds the
|
|
582
|
+
* verb-led subline body without the leading glyph and without the trailing
|
|
583
|
+
* status glyph. Unknown tools fall back to the existing `<name>(<arg>)` form.
|
|
584
|
+
*/
|
|
585
|
+
function webFetchMeta(result: unknown): string | null {
|
|
586
|
+
if (!isPlainObject(result) || !isPlainObject(result.details)) return null;
|
|
587
|
+
const status = typeof result.details.status === "number" ? String(result.details.status) : null;
|
|
588
|
+
const format = typeof result.details.format === "string" ? result.details.format : null;
|
|
589
|
+
const bytesRead = typeof result.details.bytesRead === "number" ? result.details.bytesRead : null;
|
|
590
|
+
const truncated = result.details.truncated === true ? "truncated" : null;
|
|
591
|
+
const bytes = bytesRead === null ? null : bytesRead >= 1024 ? `${(bytesRead / 1024).toFixed(1)}KB` : `${bytesRead}B`;
|
|
592
|
+
const parts = [status, format, bytes, truncated].filter(
|
|
593
|
+
(part): part is string => typeof part === "string" && part.length > 0,
|
|
594
|
+
);
|
|
595
|
+
return parts.length > 0 ? parts.join(" · ") : null;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
/**
|
|
599
|
+
* A call the permission gate blocked never executed, so the collapsed row must
|
|
600
|
+
* not claim it did. `ran \`id\` · 667B ✗ blocked` read as a command that ran and
|
|
601
|
+
* produced 667 bytes, while the expanded header for the same node correctly said
|
|
602
|
+
* `bash(id) ✗ blocked`. Blocked rows use that same call-signature form, and the
|
|
603
|
+
* ledger byte count is suppressed because those bytes are the denial text, not
|
|
604
|
+
* output.
|
|
605
|
+
*/
|
|
606
|
+
function isNonExecutedOutcome(outcome: ToolExecutionFinished["outcome"]): boolean {
|
|
607
|
+
return outcome === "blocked";
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
function buildSublineBody(
|
|
611
|
+
toolName: string,
|
|
612
|
+
args: unknown,
|
|
613
|
+
status: HeaderStatus,
|
|
614
|
+
result?: unknown,
|
|
615
|
+
outcome?: ToolExecutionFinished["outcome"],
|
|
616
|
+
): string {
|
|
617
|
+
if (isNonExecutedOutcome(outcome)) return buildUnknownToolBody(toolName, args);
|
|
618
|
+
if (toolName === "web_fetch") {
|
|
619
|
+
const meta = status === undefined ? null : webFetchMeta(result);
|
|
620
|
+
return `${buildUnknownToolBody(toolName, args)}${meta ? dim(` · ${meta}`) : ""}`;
|
|
621
|
+
}
|
|
622
|
+
if (toolName === "bash") {
|
|
623
|
+
const lead = status === undefined ? "running " : "ran ";
|
|
624
|
+
return (
|
|
625
|
+
buildFieldSublineBody(args, "command", lead, { wrapInBackticks: true }) ?? buildUnknownToolBody(toolName, args)
|
|
626
|
+
);
|
|
627
|
+
}
|
|
628
|
+
const body = SUBLINE_BODY_BUILDERS[toolName]?.(args);
|
|
629
|
+
if (body !== null && body !== undefined) return body;
|
|
630
|
+
return buildUnknownToolBody(toolName, args);
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
interface SublineParts {
|
|
634
|
+
/** Verb, object, and ledger facts. Breakable across wraps. */
|
|
635
|
+
lead: string;
|
|
636
|
+
/**
|
|
637
|
+
* Status glyph, duration, and any offload path, composed as one unit. The
|
|
638
|
+
* caller appends the expand hint here so the whole tail stays atomic: a wrap
|
|
639
|
+
* may fall before the status glyph but never between the glyph, the
|
|
640
|
+
* duration, and the hint. Begins with a joining space so it attaches to the
|
|
641
|
+
* lead's last line when they share a row. Empty for in-flight calls, which
|
|
642
|
+
* carry no status glyph.
|
|
643
|
+
*/
|
|
644
|
+
tail: string;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
function sublineParts(
|
|
648
|
+
call: ToolExecutionStart | ToolExecutionFinished,
|
|
649
|
+
status: HeaderStatus,
|
|
650
|
+
meta: StatusMeta,
|
|
651
|
+
): SublineParts {
|
|
652
|
+
const finished = "result" in call ? call : null;
|
|
653
|
+
const body = styleSublineBody(buildSublineBody(call.toolName, call.args, status, finished?.result, finished?.outcome));
|
|
654
|
+
const resourceLabel = classifyResourceRead(call.toolName, call.args);
|
|
655
|
+
const resource = resourceLabel !== null ? dim(` · ${resourceLabel}`) : "";
|
|
656
|
+
if (finished !== null) {
|
|
657
|
+
const ledger = ledgerTail(finished);
|
|
658
|
+
return {
|
|
659
|
+
lead: `${dim(HEADER_PREFIX_PLAIN)}${body}${resource}${ledger.facts}`,
|
|
660
|
+
tail: `${statusGlyph(status, meta)}${ledger.offload}`,
|
|
661
|
+
};
|
|
662
|
+
}
|
|
663
|
+
const elapsed = optionalCompactMs("elapsedMs" in call ? call.elapsedMs : undefined);
|
|
664
|
+
const running = elapsed !== null ? dim(` · ${elapsed}`) : "";
|
|
665
|
+
return { lead: `${dim(HEADER_PREFIX_PLAIN)}${body}${resource}${running}`, tail: "" };
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
/**
|
|
669
|
+
* Wrap a collapsed subline while keeping its status tail atomic. The lead wraps
|
|
670
|
+
* normally; the tail (status glyph, duration, offload, and the optional expand
|
|
671
|
+
* hint) is placed as a single unit. When the whole line fits it renders on one
|
|
672
|
+
* row; otherwise the tail joins the lead's last wrapped line if it fits there,
|
|
673
|
+
* and only falls to its own row when it cannot, so the status glyph and
|
|
674
|
+
* duration are never separated by a wrap.
|
|
675
|
+
*/
|
|
676
|
+
function wrapSublineWithTail(lead: string, tail: string, width: number): string[] {
|
|
677
|
+
if (tail.length === 0) return wrap(lead, width);
|
|
678
|
+
if (visibleWidth(`${lead}${tail}`) <= width) return [`${lead}${tail}`];
|
|
679
|
+
const leadLines = wrap(lead, width);
|
|
680
|
+
const last = leadLines[leadLines.length - 1];
|
|
681
|
+
if (last !== undefined && visibleWidth(`${last}${tail}`) <= width) {
|
|
682
|
+
leadLines[leadLines.length - 1] = `${last}${tail}`;
|
|
683
|
+
return leadLines;
|
|
684
|
+
}
|
|
685
|
+
// The tail cannot sit beside the lead: give it its own row, dropping the
|
|
686
|
+
// joining leading space so it starts flush at the left.
|
|
687
|
+
return [...leadLines, ...wrap(tail.replace(/^ +/u, ""), width)];
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
function wrap(line: string, width: number): string[] {
|
|
691
|
+
return wrapTextWithAnsi(line, width);
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
/**
|
|
695
|
+
* Apply the body rail to a line and wrap it. The rail (`│ `) is dim by
|
|
696
|
+
* default and red on error so the tool block reads as a single visual unit
|
|
697
|
+
* even when its result spans many lines. Uses the hoisted `RAIL_DIM` /
|
|
698
|
+
* `RAIL_ERROR` constants so we do not allocate a fresh styled prefix per
|
|
699
|
+
* wrapped line.
|
|
700
|
+
*/
|
|
701
|
+
function indentAndWrap(line: string, width: number, isError: boolean): string[] {
|
|
702
|
+
const rail = isError ? RAIL_ERROR : RAIL_DIM;
|
|
703
|
+
const bodyWidth = Math.max(1, width - BODY_INDENT_VISIBLE_WIDTH);
|
|
704
|
+
const out: string[] = [];
|
|
705
|
+
for (const wrapped of wrap(line, bodyWidth)) {
|
|
706
|
+
out.push(`${rail}${wrapped}`);
|
|
707
|
+
}
|
|
708
|
+
return out;
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
/**
|
|
712
|
+
* Render the pretty-printed JSON args body. Splits on `\n` first and then
|
|
713
|
+
* applies a line cap so the cut never lands inside an open string or before
|
|
714
|
+
* a closing brace; the previous codepoint-level `truncate` could leave a
|
|
715
|
+
* malformed JSON snippet that broke copy-paste. Mirrors the line-cap strategy
|
|
716
|
+
* `renderResultBlock` already uses for tool output.
|
|
717
|
+
*/
|
|
718
|
+
function renderArgsBody(args: unknown, width: number, isError: boolean): string[] {
|
|
719
|
+
if (isEmptyArgs(args)) return [];
|
|
720
|
+
const out: string[] = [];
|
|
721
|
+
const bodyWidth = Math.max(1, width - BODY_INDENT_VISIBLE_WIDTH);
|
|
722
|
+
const lines = tryRenderJson(redactToolArgs(args), bodyWidth, { lineLimit: ARGS_BODY_LINE_LIMIT });
|
|
723
|
+
if (!lines) return [];
|
|
724
|
+
for (const raw of lines) {
|
|
725
|
+
out.push(...indentAndWrap(raw, width, isError));
|
|
726
|
+
}
|
|
727
|
+
return out;
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
/**
|
|
731
|
+
* pi-agent-core wraps tool results in `{ content: [{ type: "text", text }, ...] }`
|
|
732
|
+
* envelopes. Rendering that JSON verbatim hides the actual tool output behind
|
|
733
|
+
* a sea of escaped quotes. When the envelope shape matches, concatenate the
|
|
734
|
+
* text segments and treat the join as the real result; otherwise return the
|
|
735
|
+
* value untouched so callers stringify it normally.
|
|
736
|
+
*/
|
|
737
|
+
export function unwrapResultEnvelope(result: unknown): unknown {
|
|
738
|
+
if (typeof result === "string" || result === null || result === undefined) return result;
|
|
739
|
+
const blocks = Array.isArray(result)
|
|
740
|
+
? result
|
|
741
|
+
: isPlainObject(result) && Array.isArray(result.content)
|
|
742
|
+
? result.content
|
|
743
|
+
: null;
|
|
744
|
+
if (blocks === null) return result;
|
|
745
|
+
const parts: string[] = [];
|
|
746
|
+
for (const block of blocks) {
|
|
747
|
+
if (!isPlainObject(block)) return result;
|
|
748
|
+
if (block.type !== "text" || typeof block.text !== "string") return result;
|
|
749
|
+
parts.push(block.text);
|
|
750
|
+
}
|
|
751
|
+
if (parts.length === 0) return result;
|
|
752
|
+
return parts.join("");
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
export function previewResult(result: unknown): string {
|
|
756
|
+
if (typeof result === "string") return truncate(result, RESULT_PREVIEW_LIMIT);
|
|
757
|
+
return truncate(jsonStringifySafe(result), RESULT_PREVIEW_LIMIT);
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
function isEmptyResult(result: unknown): boolean {
|
|
761
|
+
if (result === null || result === undefined) return true;
|
|
762
|
+
if (typeof result === "string" && result.length === 0) return true;
|
|
763
|
+
return false;
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
function resultText(result: unknown, limit = FULL_RESULT_PREVIEW_LIMIT): string {
|
|
767
|
+
if (typeof result === "string") return truncate(result, limit);
|
|
768
|
+
return truncate(jsonStringifySafe(result), limit);
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
function truncateRowsMiddle(rows: ReadonlyArray<string>, rowLimit: number, isError: boolean): string[] {
|
|
772
|
+
if (rows.length <= rowLimit) return [...rows];
|
|
773
|
+
if (rowLimit <= 1) return [`${isError ? RAIL_ERROR : RAIL_DIM}${dim(`... ${rows.length} lines hidden`)}`];
|
|
774
|
+
const available = rowLimit - 1;
|
|
775
|
+
const head = Math.floor(available / 2);
|
|
776
|
+
const tail = available - head;
|
|
777
|
+
const hidden = Math.max(0, rows.length - head - tail);
|
|
778
|
+
return [
|
|
779
|
+
...rows.slice(0, head),
|
|
780
|
+
`${isError ? RAIL_ERROR : RAIL_DIM}${dim(`... ${hidden} lines hidden`)}`,
|
|
781
|
+
...rows.slice(-tail),
|
|
782
|
+
];
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
function renderOutputRows(text: string, width: number, isError: boolean, rowLimit: number): string[] {
|
|
786
|
+
const rows: string[] = [];
|
|
787
|
+
for (const raw of text.split("\n")) {
|
|
788
|
+
rows.push(...indentAndWrap(raw, width, isError));
|
|
789
|
+
}
|
|
790
|
+
return truncateRowsMiddle(rows, rowLimit, isError);
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
function renderStructuredOutputRows(
|
|
794
|
+
value: unknown,
|
|
795
|
+
width: number,
|
|
796
|
+
isError: boolean,
|
|
797
|
+
rowLimit: number,
|
|
798
|
+
): string[] | null {
|
|
799
|
+
const bodyWidth = Math.max(1, width - BODY_INDENT_VISIBLE_WIDTH);
|
|
800
|
+
const unwrapped = unwrapResultEnvelope(value);
|
|
801
|
+
const structured =
|
|
802
|
+
typeof unwrapped === "string"
|
|
803
|
+
? (tryRenderJson(unwrapped, bodyWidth, { lineLimit: rowLimit }) ??
|
|
804
|
+
tryRenderXml(unwrapped, bodyWidth, { lineLimit: rowLimit }))
|
|
805
|
+
: tryRenderJson(unwrapped, bodyWidth, { lineLimit: rowLimit });
|
|
806
|
+
if (!structured) return null;
|
|
807
|
+
const out: string[] = [];
|
|
808
|
+
for (const row of structured) out.push(...indentAndWrap(row, width, isError));
|
|
809
|
+
return out;
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
function highlightBashCommand(command: string): string {
|
|
813
|
+
const tokens = command.match(/'[^']*'|"[^"]*"|\|\||&&|[|;()<>]|[^\s|;&()<>]+|\s+/gu) ?? [command];
|
|
814
|
+
return tokens
|
|
815
|
+
.map((token) => {
|
|
816
|
+
if (/^\s+$/u.test(token)) return token;
|
|
817
|
+
if (/^'[^']*'$|^"[^"]*"$/u.test(token)) return green(token);
|
|
818
|
+
if (/^(?:\|\||&&|[|;()<>])$/u.test(token)) return dim(token);
|
|
819
|
+
if (/^-{1,2}[\w-]+/u.test(token)) return yellow(token);
|
|
820
|
+
return token;
|
|
821
|
+
})
|
|
822
|
+
.join("");
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
interface EditDiffArgs {
|
|
826
|
+
path?: string;
|
|
827
|
+
old_string: string;
|
|
828
|
+
new_string: string;
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
/**
|
|
832
|
+
* Defensive shape check: edit-tool args must carry both `old_string` and
|
|
833
|
+
* `new_string` strings before we can render a diff. `path` is optional; the
|
|
834
|
+
* diff renderer falls back to `"file"` when absent. Anything else falls
|
|
835
|
+
* through to the standard result block so the dispatch is opportunistic and
|
|
836
|
+
* never throws.
|
|
837
|
+
*/
|
|
838
|
+
function asEditDiffArgs(args: unknown): EditDiffArgs | null {
|
|
839
|
+
if (!isPlainObject(args)) return null;
|
|
840
|
+
const oldString = args.old_string;
|
|
841
|
+
const newString = args.new_string;
|
|
842
|
+
if (typeof oldString !== "string" || typeof newString !== "string") return null;
|
|
843
|
+
const out: EditDiffArgs = { old_string: oldString, new_string: newString };
|
|
844
|
+
if (typeof args.path === "string") out.path = args.path;
|
|
845
|
+
return out;
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
// The `diff` library appends a `` sentinel row when a
|
|
849
|
+
// side of the comparison lacks a trailing newline. It is transcript noise, so
|
|
850
|
+
// the edit diff block drops it. The marker text carries no ANSI, so a substring
|
|
851
|
+
// check against the styled row is reliable and keeps this module free of raw
|
|
852
|
+
// escape literals.
|
|
853
|
+
const NO_NEWLINE_MARKER = "\";
|
|
854
|
+
|
|
855
|
+
function isNoNewlineMarkerRow(row: string): boolean {
|
|
856
|
+
return row.includes(NO_NEWLINE_MARKER);
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
function renderEditDiffBlock(args: EditDiffArgs, width: number): string[] {
|
|
860
|
+
const bodyWidth = Math.max(1, width - BODY_INDENT_VISIBLE_WIDTH);
|
|
861
|
+
const input: DiffRenderInput = { oldText: args.old_string, newText: args.new_string };
|
|
862
|
+
if (args.path !== undefined) input.filename = args.path;
|
|
863
|
+
const out: string[] = [];
|
|
864
|
+
for (const line of renderUnifiedDiff(input, bodyWidth)) {
|
|
865
|
+
if (isNoNewlineMarkerRow(line)) continue;
|
|
866
|
+
out.push(`${RAIL_DIM}${line}`);
|
|
867
|
+
}
|
|
868
|
+
return out;
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
interface BashArgs {
|
|
872
|
+
command: string;
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
/**
|
|
876
|
+
* Defensive shape check: bash-tool args must carry a string `command` for the
|
|
877
|
+
* `$ <cmd>` echo line to render. Anything else falls through to the standard
|
|
878
|
+
* result block so the dispatch is opportunistic and never throws.
|
|
879
|
+
*/
|
|
880
|
+
function asBashArgs(args: unknown): BashArgs | null {
|
|
881
|
+
if (!isPlainObject(args)) return null;
|
|
882
|
+
const command = args.command;
|
|
883
|
+
if (typeof command !== "string") return null;
|
|
884
|
+
return { command: redactSecretString(command) };
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
/**
|
|
888
|
+
* Bash subrenderer: emits `$ <cmd>` (full command) on its own line under the
|
|
889
|
+
* rail, then the unwrapped output via the same chain as `renderResultBlock`.
|
|
890
|
+
* Mirrors pi-coding-agent's bash component shape so users see exactly what
|
|
891
|
+
* was executed before the output. Failures use the same command and output
|
|
892
|
+
* body while the caller selects the red rail and error status.
|
|
893
|
+
*/
|
|
894
|
+
function renderBashResultBlock(
|
|
895
|
+
args: BashArgs,
|
|
896
|
+
result: unknown,
|
|
897
|
+
width: number,
|
|
898
|
+
isError: boolean,
|
|
899
|
+
opts: ToolBodyRenderOptions = {},
|
|
900
|
+
): string[] {
|
|
901
|
+
const out: string[] = [];
|
|
902
|
+
const commandLine = `${cyanBold("$")} ${highlightBashCommand(stripShellWrapperForDisplay(args.command))}`;
|
|
903
|
+
out.push(...indentAndWrap(commandLine, width, isError));
|
|
904
|
+
const unwrapped = unwrapResultEnvelope(result);
|
|
905
|
+
if (isEmptyResult(unwrapped)) {
|
|
906
|
+
out.push(...indentAndWrap(dim("(no output)"), width, isError));
|
|
907
|
+
return out;
|
|
908
|
+
}
|
|
909
|
+
out.push(...renderOutputRows(resultText(unwrapped, resultCharLimit(opts)), width, isError, resultRowLimit(opts)));
|
|
910
|
+
return out;
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
function renderResultBlock(
|
|
914
|
+
result: unknown,
|
|
915
|
+
isError: boolean,
|
|
916
|
+
width: number,
|
|
917
|
+
opts: ToolBodyRenderOptions = {},
|
|
918
|
+
): string[] {
|
|
919
|
+
const unwrapped = unwrapResultEnvelope(result);
|
|
920
|
+
if (isEmptyResult(unwrapped)) {
|
|
921
|
+
return indentAndWrap(dim("(no output)"), width, isError);
|
|
922
|
+
}
|
|
923
|
+
const structured = renderStructuredOutputRows(unwrapped, width, isError, resultRowLimit(opts));
|
|
924
|
+
if (structured) return structured;
|
|
925
|
+
return renderOutputRows(resultText(unwrapped, resultCharLimit(opts)), width, isError, resultRowLimit(opts));
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
/**
|
|
929
|
+
* Header-only render for a tool call that has not yet finished. Used by the
|
|
930
|
+
* live chat panel between `tool_execution_start` and `tool_execution_end`.
|
|
931
|
+
* No status glyph: the absence of the glyph signals "still running".
|
|
932
|
+
*/
|
|
933
|
+
export function renderToolCallHeader(call: ToolExecutionStart, width: number): string[] {
|
|
934
|
+
return wrap(headerLine(call.toolName, call.args, undefined), width);
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
/** Running-only footer used when an operator pauses live output; execution continues. */
|
|
938
|
+
export function renderToolRunningStatus(call: ToolExecutionStart, width: number): string[] {
|
|
939
|
+
const elapsed = optionalCompactMs(call.elapsedMs);
|
|
940
|
+
return [
|
|
941
|
+
...renderToolCallHeader(call, width),
|
|
942
|
+
...indentAndWrap(
|
|
943
|
+
dim(elapsed ? `(running... ${elapsed}; live output hidden)` : "(running; live output hidden)"),
|
|
944
|
+
width,
|
|
945
|
+
false,
|
|
946
|
+
),
|
|
947
|
+
];
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
function sublineStatus(call: ToolExecutionStart | ToolExecutionFinished): HeaderStatus {
|
|
951
|
+
// Discriminate on `result` rather than `isError`: only `ToolExecutionFinished`
|
|
952
|
+
// carries a `result` field, so a `ToolExecutionStart` with a stray
|
|
953
|
+
// `isError: false` (e.g. from a future event-shape change) cannot trip the
|
|
954
|
+
// finished path. `result` is the type's load-bearing field.
|
|
955
|
+
if (!("result" in call)) return undefined;
|
|
956
|
+
return call.isError ? "error" : "ok";
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
/**
|
|
960
|
+
* One-line subline form of a tool call. Format:
|
|
961
|
+
* ▸ <body><status>
|
|
962
|
+
* `status` is "" for in-flight, " ✓" green for success, " ✗" red for error.
|
|
963
|
+
* Output is width-wrapped via wrapTextWithAnsi.
|
|
964
|
+
*
|
|
965
|
+
* When `expandKey` is supplied AND the call has finished, a dim ` (<key>)`
|
|
966
|
+
* discoverability hint rides at the very end of the atomic status tail so users
|
|
967
|
+
* see how to expand the collapsed block. Composing the full line (facts, status
|
|
968
|
+
* glyph, duration, offload, and hint) before wrapping keeps the status glyph
|
|
969
|
+
* and duration together on one row. The hint is suppressed for in-flight calls
|
|
970
|
+
* (still running, no useful body to expand yet) and when `expandKey` is
|
|
971
|
+
* empty/undefined (no key bound, hint would be misleading). The renderer never
|
|
972
|
+
* imports the keybindings manager directly; the caller resolves the key string
|
|
973
|
+
* and passes it in to keep this module pure.
|
|
974
|
+
*/
|
|
975
|
+
export function renderToolSubline(
|
|
976
|
+
call: ToolExecutionStart | ToolExecutionFinished,
|
|
977
|
+
width: number,
|
|
978
|
+
expandKey?: string,
|
|
979
|
+
): string[] {
|
|
980
|
+
const status = sublineStatus(call);
|
|
981
|
+
const meta: StatusMeta =
|
|
982
|
+
"result" in call
|
|
983
|
+
? {
|
|
984
|
+
durationMs: call.durationMs,
|
|
985
|
+
exitCode: call.toolName === "bash" && call.isError ? bashExitCodeFromResult(call.result) : null,
|
|
986
|
+
outcome: call.outcome,
|
|
987
|
+
blockReason: call.blockReason,
|
|
988
|
+
}
|
|
989
|
+
: {};
|
|
990
|
+
const parts = sublineParts(call, status, meta);
|
|
991
|
+
const showHint = status !== undefined && expandKey !== undefined && expandKey.length > 0;
|
|
992
|
+
const tail = showHint ? `${parts.tail}${dim(` (${expandKey})`)}` : parts.tail;
|
|
993
|
+
return wrapSublineWithTail(parts.lead, tail, width);
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
/**
|
|
997
|
+
* Full render: header + args body (if non-empty) + result block. Used by
|
|
998
|
+
* the live chat panel on `tool_execution_end` and by the replay path when a
|
|
999
|
+
* tool result can be paired with its prior call's args. Header carries a
|
|
1000
|
+
* green check on success and a red cross on error so the user can scan tool
|
|
1001
|
+
* outcomes without reading the body.
|
|
1002
|
+
*/
|
|
1003
|
+
export function renderToolExecution(
|
|
1004
|
+
finished: ToolExecutionFinished,
|
|
1005
|
+
width: number,
|
|
1006
|
+
opts: ToolBodyRenderOptions = {},
|
|
1007
|
+
): string[] {
|
|
1008
|
+
const status: HeaderStatus = finished.isError ? "error" : "ok";
|
|
1009
|
+
const statusMeta: StatusMeta = {
|
|
1010
|
+
durationMs: finished.durationMs,
|
|
1011
|
+
exitCode: finished.toolName === "bash" && finished.isError ? bashExitCodeFromResult(finished.result) : null,
|
|
1012
|
+
outcome: finished.outcome,
|
|
1013
|
+
blockReason: finished.blockReason,
|
|
1014
|
+
};
|
|
1015
|
+
const out: string[] = [];
|
|
1016
|
+
out.push(...wrap(headerLine(finished.toolName, finished.args, status, statusMeta), width));
|
|
1017
|
+
|
|
1018
|
+
// Edit-tool dispatch: when the tool succeeded and `args` carries the
|
|
1019
|
+
// expected `{ old_string, new_string }` strings, swap the args body and
|
|
1020
|
+
// result block for a unified diff. The header still renders so the user
|
|
1021
|
+
// sees `▸ edit(<path>)`, and the args body is suppressed because echoing
|
|
1022
|
+
// both strings would just duplicate what the diff already shows.
|
|
1023
|
+
if (finished.toolName === "edit" && finished.isError === false) {
|
|
1024
|
+
const editArgs = asEditDiffArgs(redactToolArgs(finished.args));
|
|
1025
|
+
if (editArgs !== null) {
|
|
1026
|
+
out.push(...renderEditDiffBlock(editArgs, width));
|
|
1027
|
+
return out;
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
// Bash-tool dispatch: when `args.command` is a string, prefix the result
|
|
1032
|
+
// body with `$ <cmd>` on its own line so the user sees the display command
|
|
1033
|
+
// above its output. Failures use the red rail and expose the parsed exit
|
|
1034
|
+
// code in the header when the result includes one.
|
|
1035
|
+
if (finished.toolName === "bash") {
|
|
1036
|
+
const bashArgs = asBashArgs(redactToolArgs(finished.args));
|
|
1037
|
+
if (bashArgs !== null) {
|
|
1038
|
+
out.push(...renderBashResultBlock(bashArgs, finished.result, width, finished.isError, opts));
|
|
1039
|
+
return out;
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
// Suppress the args body when the header already encodes the salient arg
|
|
1044
|
+
// (e.g. `▸ read(README.md)` already shows the path; rendering
|
|
1045
|
+
// `{"path": "README.md"}` underneath is duplicate noise). For tools without
|
|
1046
|
+
// a known primary arg the body still renders so users see what the model
|
|
1047
|
+
// actually invoked.
|
|
1048
|
+
if (capturedPrimaryArg(finished.toolName, finished.args) === null) {
|
|
1049
|
+
out.push(...renderArgsBody(finished.args, width, finished.isError));
|
|
1050
|
+
}
|
|
1051
|
+
out.push(...renderResultBlock(finished.result, finished.isError, width, opts));
|
|
1052
|
+
return out;
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
/**
|
|
1056
|
+
* Result-only render for replayed tool results that arrived without a
|
|
1057
|
+
* matching prior tool-call entry (orphan results in the session log).
|
|
1058
|
+
* Identical to `renderToolExecution` minus the args body.
|
|
1059
|
+
*/
|
|
1060
|
+
export function renderToolResultOnly(
|
|
1061
|
+
finished: Omit<ToolExecutionFinished, "args">,
|
|
1062
|
+
width: number,
|
|
1063
|
+
opts: ToolBodyRenderOptions = {},
|
|
1064
|
+
): string[] {
|
|
1065
|
+
const status: HeaderStatus = finished.isError ? "error" : "ok";
|
|
1066
|
+
const statusMeta: StatusMeta = {
|
|
1067
|
+
durationMs: finished.durationMs,
|
|
1068
|
+
exitCode: finished.toolName === "bash" && finished.isError ? bashExitCodeFromResult(finished.result) : null,
|
|
1069
|
+
outcome: finished.outcome,
|
|
1070
|
+
blockReason: finished.blockReason,
|
|
1071
|
+
};
|
|
1072
|
+
const out: string[] = [];
|
|
1073
|
+
out.push(...wrap(headerLine(finished.toolName, undefined, status, statusMeta), width));
|
|
1074
|
+
out.push(...renderResultBlock(finished.result, finished.isError, width, opts));
|
|
1075
|
+
return out;
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
/**
|
|
1079
|
+
* Streaming render for an in-flight tool call whose expanded block should
|
|
1080
|
+
* surface the latest partial output. Used by the chat panel between
|
|
1081
|
+
* `tool_execution_start` and `tool_execution_end` when the user has expanded
|
|
1082
|
+
* the tool segment. The header carries no status glyph (still running), the
|
|
1083
|
+
* args body is suppressed when the header captures the primary arg, the
|
|
1084
|
+
* partial output renders under the rail capped at `RESULT_LINE_LIMIT` lines,
|
|
1085
|
+
* and a dim `(running...)` marker on the trailing line communicates that the
|
|
1086
|
+
* block is still being written. An empty `partialOutput` renders
|
|
1087
|
+
* `(no output yet)` so the user can distinguish a slow start from a stalled
|
|
1088
|
+
* call.
|
|
1089
|
+
*/
|
|
1090
|
+
export function renderToolStreamingExecution(call: ToolExecutionStart, width: number, partialOutput: string): string[] {
|
|
1091
|
+
const out: string[] = [];
|
|
1092
|
+
out.push(...wrap(headerLine(call.toolName, call.args, undefined), width));
|
|
1093
|
+
if (capturedPrimaryArg(call.toolName, call.args) === null) {
|
|
1094
|
+
out.push(...renderArgsBody(call.args, width, false));
|
|
1095
|
+
}
|
|
1096
|
+
if (partialOutput.length === 0) {
|
|
1097
|
+
out.push(...indentAndWrap(dim("(no output yet)"), width, false));
|
|
1098
|
+
} else {
|
|
1099
|
+
out.push(...renderOutputRows(partialOutput, width, false, STREAMING_RESULT_ROW_LIMIT));
|
|
1100
|
+
}
|
|
1101
|
+
const elapsed = optionalCompactMs(call.elapsedMs);
|
|
1102
|
+
out.push(...indentAndWrap(dim(elapsed !== null ? `(running... ${elapsed})` : "(running...)"), width, false));
|
|
1103
|
+
return out;
|
|
1104
|
+
}
|