@iowarp/clio-coder 0.3.1 → 0.3.3
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 +233 -373
- package/CONTRIBUTING.md +23 -23
- package/README.md +284 -613
- package/dist/{acp-FPR54DGL.js → acp-P2AQILE2.js} +43 -53
- package/dist/{agents-OGPIHPJH.js → agents-72W3BI7I.js} +43 -26
- package/dist/assets/codewiki.json +1 -1
- package/dist/{auth-IC3K6NIZ.js → auth-5TWEIYDN.js} +20 -12
- package/dist/chunk-2DJ2KNFG.js +2095 -0
- package/dist/{chunk-IS3ONKU3.js → chunk-2IR2NMPA.js} +6 -4
- package/dist/chunk-2SFS6XQE.js +122 -0
- package/dist/{chunk-PV4JUBVJ.js → chunk-2TLUCQVG.js} +40 -21
- package/dist/chunk-2VTFPG5O.js +48 -0
- package/dist/chunk-4BJ5BYCE.js +61 -0
- package/dist/{chunk-474KN5II.js → chunk-4BPJXDWC.js} +111 -181
- package/dist/chunk-4VP4KH3K.js +962 -0
- package/dist/chunk-4XUGQOHA.js +797 -0
- package/dist/chunk-4ZG3XFUR.js +77 -0
- package/dist/chunk-5B2AEOW5.js +5407 -0
- package/dist/{chunk-K2ITRMHZ.js → chunk-5TSRNF4G.js} +6 -138
- package/dist/{chunk-4QKXUHSR.js → chunk-5UFT4SUX.js} +70 -20
- package/dist/{chunk-OLBBMFRD.js → chunk-5UUP6MWO.js} +24 -62
- package/dist/chunk-65DEGPJ6.js +52 -0
- package/dist/chunk-6EJMN2Y3.js +17 -0
- package/dist/chunk-6N5PTWMY.js +136 -0
- package/dist/chunk-6SGHMWE3.js +277 -0
- package/dist/chunk-6XLNIQDB.js +27 -0
- package/dist/chunk-7CR24IG7.js +242 -0
- package/dist/chunk-7MNJORFF.js +22 -0
- package/dist/{chunk-KY56HMHH.js → chunk-A3CYT5EX.js} +125 -31
- package/dist/chunk-AGYYIBLL.js +1069 -0
- package/dist/{chunk-GB6QRBXN.js → chunk-APJ265NV.js} +54 -1187
- package/dist/{chunk-673JJUWJ.js → chunk-BMEMKKIT.js} +2 -2
- package/dist/chunk-CBCAPZAA.js +229 -0
- package/dist/chunk-CMZWFGD2.js +352 -0
- package/dist/chunk-COU2UHX6.js +400 -0
- package/dist/chunk-DSELYM6W.js +1077 -0
- package/dist/chunk-DUYJ5IO6.js +644 -0
- package/dist/chunk-ECH6PKUQ.js +39 -0
- package/dist/chunk-ED4KHGC3.js +143 -0
- package/dist/chunk-EKMEHE4H.js +340 -0
- package/dist/chunk-FCSXB6T2.js +338 -0
- package/dist/chunk-FJ3H4MN5.js +48 -0
- package/dist/{chunk-RPTR2H26.js → chunk-FNTMWMX5.js} +21 -15
- package/dist/chunk-FQ4SKYE4.js +29 -0
- package/dist/chunk-G4BMMOKF.js +182 -0
- package/dist/{chunk-ZPY3JZ5E.js → chunk-GGXXDWE4.js} +183 -1233
- package/dist/chunk-HC4CLZ2Y.js +68 -0
- package/dist/{chunk-LU4TK2PR.js → chunk-HFSBBKSQ.js} +5 -56
- package/dist/{chunk-PIUMUEMV.js → chunk-HKIYEGME.js} +10 -6
- package/dist/chunk-I4HZDVNP.js +73 -0
- package/dist/chunk-IKCO5N3L.js +162 -0
- package/dist/chunk-IR4CFBFN.js +56 -0
- package/dist/{chunk-R5KLMSBV.js → chunk-J5Q24KAG.js} +2 -2
- package/dist/chunk-J7CWMCQD.js +255 -0
- package/dist/{chunk-K5XEMXTI.js → chunk-JVCV3ICN.js} +1 -1
- package/dist/chunk-KZWTDYJF.js +217 -0
- package/dist/chunk-LBMZMYH2.js +285 -0
- package/dist/{chunk-G34LV2PF.js → chunk-LM5TQCJZ.js} +84 -170
- package/dist/chunk-LW6DSM3M.js +5135 -0
- package/dist/chunk-LWLEKMDQ.js +3482 -0
- package/dist/{chunk-H6F6BYOH.js → chunk-LZSJBIVT.js} +7003 -7434
- package/dist/{chunk-HQQID6OA.js → chunk-M6SHUN7Q.js} +5 -5
- package/dist/{chunk-FST4FYJB.js → chunk-MFFY33HR.js} +99 -140
- package/dist/{chunk-BSU2YIWB.js → chunk-MVVUPGPW.js} +131 -136
- package/dist/chunk-OAO4GE4M.js +619 -0
- package/dist/{chunk-Q3RUPKEJ.js → chunk-OC7FIQPC.js} +58 -189
- package/dist/chunk-OKGUZO2U.js +34 -0
- package/dist/{chunk-GAEBEQVI.js → chunk-OOJYHWRB.js} +32 -346
- package/dist/{chunk-Q5WJOSJ7.js → chunk-OQ33BKR3.js} +2 -1
- package/dist/chunk-OQE5J4C6.js +73 -0
- package/dist/{chunk-KKNLWXI6.js → chunk-ORBHGJC5.js} +8 -8
- package/dist/{chunk-MAR7Y6HW.js → chunk-PAJK6MAQ.js} +23 -16
- package/dist/{chunk-M5T5VO65.js → chunk-PIWWS5BL.js} +837 -635
- package/dist/chunk-POHLU5DW.js +1186 -0
- package/dist/chunk-QKMUKYO7.js +4961 -0
- package/dist/chunk-SRDMMSEP.js +16405 -0
- package/dist/chunk-SST6Z5JA.js +80 -0
- package/dist/chunk-STBPMHSX.js +2456 -0
- package/dist/chunk-T6YILFSB.js +80 -0
- package/dist/chunk-TZK7PACC.js +174 -0
- package/dist/chunk-TZTZS7QK.js +227 -0
- package/dist/{chunk-ASND7OZK.js → chunk-UFIIWP2H.js} +13 -13
- package/dist/chunk-UOV2BYIW.js +107 -0
- package/dist/{chunk-PFEFKVGL.js → chunk-V6RTAOC2.js} +13 -11
- package/dist/chunk-VAKQQHWR.js +434 -0
- package/dist/chunk-VG7TBQIY.js +128 -0
- package/dist/chunk-VJWL6YS5.js +244 -0
- package/dist/{chunk-EYOKLTMF.js → chunk-VPAYEGVX.js} +17 -3
- package/dist/chunk-WEH5XRJQ.js +32 -0
- package/dist/chunk-X4RCMKVQ.js +641 -0
- package/dist/{chunk-TEKV33Q5.js → chunk-X6IAEBZR.js} +65 -33
- package/dist/chunk-XBXAASKX.js +18 -0
- package/dist/chunk-XN3L4EYL.js +46 -0
- package/dist/{chunk-RDLVBZEO.js → chunk-YCWGATWI.js} +6 -4
- package/dist/chunk-YHZX5GEU.js +193 -0
- package/dist/chunk-YXLYO42X.js +91 -0
- package/dist/{chunk-NMOX6HFD.js → chunk-ZDOOVTXZ.js} +29 -77
- package/dist/chunk-ZI647VB5.js +37 -0
- package/dist/{chunk-C4PTHK7P.js → chunk-ZWLZP4ZT.js} +5 -5
- package/dist/chunk-ZWMF7253.js +1882 -0
- package/dist/cli/index.js +62 -54
- package/dist/clio-JOU4FXVA.js +25 -0
- package/dist/code-nav-7AX6FYE6.js +600 -0
- package/dist/codewiki/build-worker.js +66 -0
- package/dist/compile-cache-CVJMMODC.js +18 -0
- package/dist/{components-DMAOEKFB.js → components-KELWS457.js} +11 -6
- package/dist/{config-IRUQ7SE4.js → config-XCDVKR23.js} +92 -55
- package/dist/configure-4GAP54ZW.js +42 -0
- package/dist/{context-5RADCKTR.js → context-4UOGGLQ5.js} +71 -35
- package/dist/context-5VKGUVJJ.js +866 -0
- package/dist/{context-3KWFLHJG.js → context-77FM5DV5.js} +15 -13
- package/dist/{context-clear-7TSNPAAI.js → context-clear-XXJRLCJJ.js} +54 -28
- package/dist/{context-index-W4RLWOQH.js → context-index-BZ4UYMTC.js} +30 -24
- package/dist/dispatch-runner-QPRDDBDX.js +1997 -0
- package/dist/{docs-5AWSPS37.js → docs-2C2LTVT2.js} +23 -10
- package/dist/{doctor-UC5NAJYQ.js → doctor-HR46URBJ.js} +27 -17
- package/dist/{eval-U6TJHRLX.js → eval-XSSNATB4.js} +29 -16
- package/dist/{evidence-YEGUW4L3.js → evidence-6HG2PY2B.js} +46 -26
- package/dist/{evolve-TXARCTPG.js → evolve-K7YU3NCY.js} +45 -25
- package/dist/{extensions-OZFJ3A3G.js → extensions-QVDOHDGJ.js} +16 -7
- package/dist/{fleet-6G3DHNYE.js → fleet-VY3HHKN6.js} +163 -54
- package/dist/{fleet-preflight-DSNT37JK.js → fleet-preflight-DDN536IT.js} +7 -4
- package/dist/{init-KZ5QTF6M.js → init-JYGXI3FK.js} +69 -32
- package/dist/{memory-73ESV5YC.js → memory-WFZMGYHX.js} +48 -27
- package/dist/{models-A4PVNWJK.js → models-I5QWSEOM.js} +39 -25
- package/dist/monitor-GE4ID3IA.js +661 -0
- package/dist/{chunk-FCIH3BIZ.js → orchestrator-EM5MC3HM.js} +15979 -12407
- package/dist/{paths-C4H6IV77.js → paths-UXLN5YYZ.js} +10 -5
- package/dist/{preload-6WVMHX3A.js → preload-P6DGH2PZ.js} +2 -2
- package/dist/{reset-BGW6OGMV.js → reset-L2FQEE3E.js} +16 -10
- package/dist/{run-YTPEYQOH.js → run-ZU3QMZPZ.js} +101 -61
- package/dist/{share-YIFFV4NQ.js → share-S5BZQC5I.js} +15 -8
- package/dist/{skills-2V6RA3OQ.js → skills-X5VXCRNQ.js} +34 -14
- package/dist/{skills-eval-S2TVJO4F.js → skills-eval-WKIHWTHR.js} +70 -34
- package/dist/steer-GGWFUJUD.js +77 -0
- package/dist/{targets-TYXLPB23.js → targets-SNCPI2NR.js} +43 -27
- package/dist/terminal-lease-BNAHVHBS.js +395 -0
- package/dist/{trace-GGOJ6Q6Z.js → trace-PNCASAXC.js} +41 -16
- package/dist/{chunk-N6F52NLF.js → tree-sitter-HGKH6LG4.js} +28 -2306
- package/dist/{uninstall-LLLT4F4W.js → uninstall-FZCQCDKC.js} +10 -5
- package/dist/{upgrade-33G2LMM5.js → upgrade-JQHHPQ4K.js} +45 -25
- package/dist/{usage-ZAFSXKKG.js → usage-OR4O5SMZ.js} +62 -31
- package/dist/verify-375KUB3Y.js +716 -0
- package/dist/web-fetch-2YHJ3KTG.js +638 -0
- package/dist/{wiki-generate-NUQCVOQ3.js → wiki-generate-UEXP2ARI.js} +74 -34
- package/dist/worker/entry.js +221 -36
- package/dist/workspace-G4ZWUIPR.js +22 -0
- package/docs/README.md +22 -17
- package/docs/acp.md +168 -16
- package/docs/alcf-provider.md +1 -1
- package/docs/architecture.md +136 -7
- package/docs/artifact-versions.md +1 -1
- package/docs/built-in-agents.md +1 -1
- package/docs/capacity-and-scheduling.md +1 -1
- package/docs/commands-and-modes.md +114 -71
- package/docs/config-knobs-audit.md +1 -3
- package/docs/configuration-and-targets.md +174 -46
- package/docs/context-engine.md +29 -6
- package/docs/development-pipeline.md +26 -1
- package/docs/dispatch-architecture-rationale.md +1 -1
- package/docs/documentation-coverage.md +2 -2
- package/docs/documentation-guide.md +1 -1
- package/docs/environment-variables.md +13 -5
- package/docs/eval-runner.md +1 -1
- package/docs/evals-internal.md +1 -1
- package/docs/evidence-and-memory.md +6 -2
- package/docs/evolution.md +2 -2
- package/docs/exit-codes-and-output.md +15 -9
- package/docs/extensions-and-sharing.md +9 -9
- package/docs/fleet-dispatch.md +7 -5
- package/docs/git-commit-provenance.md +120 -0
- package/docs/glossary.md +1 -1
- package/docs/installation-and-lifecycle.md +34 -27
- package/docs/middleware-and-components.md +1 -1
- package/docs/model-catalog.md +45 -14
- package/docs/observability.md +8 -5
- package/docs/performance-methodology.md +491 -0
- package/docs/pi-boundary.md +72 -0
- package/docs/proactive-memory.md +3 -3
- package/docs/prompt-envelope-and-tools.md +24 -3
- package/docs/provider-adapter-cookbook.md +57 -4
- package/docs/release-cut-checklist.md +129 -115
- package/docs/safety-model.md +9 -5
- package/docs/scientific-validation.md +3 -3
- package/docs/session-lifecycle.md +55 -12
- package/docs/skills-marketplace.md +12 -8
- package/docs/time-conventions.md +1 -1
- package/docs/tool-usage.md +3 -3
- package/docs/trace-store.md +1 -1
- package/docs/troubleshooting.md +10 -7
- package/docs/tui-design.md +47 -10
- package/docs/worker-dispatch-mechanics.md +1 -1
- package/package.json +19 -22
- package/skills/coding/ast-grep/SKILL.md +136 -0
- package/skills/coding/ast-grep/evals.md +56 -0
- package/skills/coding/ast-grep/references/rule_reference.md +297 -0
- package/skills/coding/coding-standards/SKILL.md +113 -0
- package/skills/coding/coding-standards/evals.md +34 -0
- package/skills/coding/prototype/SKILL.md +86 -0
- package/skills/coding/prototype/evals.md +42 -0
- package/skills/coding/prototype/references/LOGIC.md +67 -0
- package/skills/coding/prototype/references/UI.md +112 -0
- package/skills/coding/tdd/SKILL.md +101 -0
- package/skills/coding/tdd/evals.md +41 -0
- package/skills/coding/tdd/references/mocking.md +59 -0
- package/skills/coding/tdd/references/tests.md +77 -0
- package/skills/context/context-handoff/SKILL.md +126 -0
- package/skills/context/context-handoff/evals.md +57 -0
- package/skills/context/context-handoff/scripts/new-handoff.sh +26 -0
- package/skills/context/context-prime/SKILL.md +95 -0
- package/skills/context/context-prime/evals.md +54 -0
- package/skills/meta/clio-dev/SKILL.md +91 -0
- package/skills/meta/clio-dev/evals.md +45 -0
- package/skills/meta/clio-test/SKILL.md +130 -0
- package/skills/meta/clio-test/evals.md +43 -0
- package/skills/meta/clio-test/references/harness.md +97 -0
- package/skills/meta/clio-test/references/test-map.md +59 -0
- package/skills/meta/credentials/SKILL.md +125 -0
- package/skills/meta/credentials/evals.md +104 -0
- package/skills/meta/find-skills/SKILL.md +72 -0
- package/skills/meta/find-skills/evals.md +47 -0
- package/skills/meta/herdr/SKILL.md +127 -0
- package/skills/meta/herdr/evals.md +38 -0
- package/skills/meta/skill-craft/SKILL.md +102 -0
- package/skills/meta/skill-craft/evals.md +41 -0
- package/skills/planning/architecture/SKILL.md +129 -0
- package/skills/planning/architecture/evals.md +36 -0
- package/skills/planning/backlog/SKILL.md +90 -0
- package/skills/planning/backlog/evals.md +43 -0
- package/skills/planning/prd/SKILL.md +82 -0
- package/skills/planning/prd/evals.md +49 -0
- package/skills/planning/product-intent/SKILL.md +112 -0
- package/skills/planning/product-intent/evals.md +36 -0
- package/skills/planning/tech-spec/SKILL.md +115 -0
- package/skills/planning/tech-spec/evals.md +47 -0
- package/skills/registry.yaml +136 -0
- package/skills/research/arxiv-literature/SKILL.md +104 -0
- package/skills/research/arxiv-literature/evals.md +58 -0
- package/skills/research/experiment-protocol/SKILL.md +122 -0
- package/skills/research/experiment-protocol/evals.md +91 -0
- package/skills/research/scientific-debugging/SKILL.md +119 -0
- package/skills/research/scientific-debugging/evals.md +138 -0
- package/skills/research/scientific-modernization/SKILL.md +138 -0
- package/skills/research/scientific-modernization/evals.md +84 -0
- package/skills/workflow/design-council/SKILL.md +139 -0
- package/skills/workflow/design-council/evals.md +97 -0
- package/skills/workflow/grill-me/SKILL.md +186 -0
- package/skills/workflow/grill-me/evals.md +78 -0
- package/skills/workflow/workflow-distiller/SKILL.md +136 -0
- package/skills/workflow/workflow-distiller/evals.md +107 -0
- package/src/cli/acp.ts +31 -4
- package/src/cli/clio.ts +68 -6
- package/src/cli/config-inspect.ts +28 -22
- package/src/cli/configure.ts +47 -9
- package/src/cli/context-clear.ts +2 -2
- package/src/cli/context-index.ts +21 -23
- package/src/cli/context.ts +13 -8
- package/src/cli/default-target.ts +9 -17
- package/src/cli/docs.ts +11 -5
- package/src/cli/evidence.ts +4 -1
- package/src/cli/extensions.ts +10 -1
- package/src/cli/fleet.ts +47 -6
- package/src/cli/index.ts +55 -26
- package/src/cli/memory.ts +3 -1
- package/src/cli/models.ts +1 -1
- package/src/cli/modes/json-stream.ts +37 -1
- package/src/cli/modes/print.ts +24 -9
- package/src/cli/run.ts +2 -2
- package/src/cli/skills-eval.ts +23 -8
- package/src/cli/skills.ts +19 -4
- package/src/cli/targets.ts +4 -0
- package/src/cli/text-layout.ts +15 -5
- package/src/cli/trace.ts +62 -14
- package/src/cli/upgrade.ts +18 -2
- package/src/cli/usage.ts +10 -3
- package/src/cli/wiki-generate.ts +2 -1
- package/src/core/agent-environment.ts +7 -0
- package/src/core/bash-exec.ts +72 -1
- package/src/core/boot-trace.ts +9 -4
- package/src/core/bus-events.ts +20 -4
- package/src/core/commit-attribution.ts +157 -0
- package/src/core/compile-cache.ts +159 -0
- package/src/core/config.ts +131 -2
- package/src/core/defaults.ts +39 -5
- package/src/core/domain-loader.ts +12 -5
- package/src/core/git-commit-attribution.ts +387 -0
- package/src/core/incomplete-installation.ts +45 -0
- package/src/core/response-schema.ts +1 -1
- package/src/core/safe-exec.ts +13 -1
- package/src/core/settings-layers.ts +155 -21
- package/src/core/skill-activation.ts +1 -1
- package/src/core/startup-timer.ts +3 -3
- package/src/core/state-file-lock.ts +13 -1
- package/src/core/termination.ts +78 -5
- package/src/domains/config/classify.ts +15 -3
- package/src/domains/config/extension.ts +19 -13
- package/src/domains/config/index.ts +10 -0
- package/src/domains/config/keybindings.ts +45 -9
- package/src/domains/context/bootstrap-prompt.ts +1 -1
- package/src/domains/context/bootstrap.ts +111 -18
- package/src/domains/context/clear.ts +16 -11
- package/src/domains/context/clio-md.ts +111 -9
- package/src/domains/context/codewiki/artifact.ts +400 -0
- package/src/domains/context/codewiki/build-worker-protocol.ts +24 -0
- package/src/domains/context/codewiki/build-worker.ts +54 -0
- package/src/domains/context/codewiki/coordinator.ts +182 -0
- package/src/domains/context/codewiki/indexer.ts +59 -144
- package/src/domains/context/codewiki/paths.ts +67 -0
- package/src/domains/context/codewiki/schema.ts +80 -0
- package/src/domains/context/codewiki/tree-sitter.ts +1 -1
- package/src/domains/context/contract.ts +11 -5
- package/src/domains/context/extension.ts +94 -143
- package/src/domains/context/fingerprint.ts +3 -1
- package/src/domains/context/index.ts +12 -22
- package/src/domains/context/project-metadata.ts +19 -0
- package/src/domains/context/prompt-context.ts +9 -10
- package/src/domains/context/refresh.ts +29 -21
- package/src/domains/context/runtime.ts +17 -0
- package/src/domains/context/wiki/generate.ts +39 -34
- package/src/domains/context/wiki/plan.ts +1 -1
- package/src/domains/context/wiki/prompts.ts +21 -8
- package/src/domains/dispatch/code-step.ts +20 -1
- package/src/domains/dispatch/extension.ts +158 -21
- package/src/domains/dispatch/failure-classification.ts +6 -0
- package/src/domains/dispatch/fleet-commit-attribution.ts +56 -0
- package/src/domains/dispatch/orphan-recovery.ts +50 -8
- package/src/domains/dispatch/receipt-integrity.ts +5 -0
- package/src/domains/dispatch/state.ts +31 -6
- package/src/domains/dispatch/transport.ts +2 -1
- package/src/domains/dispatch/types.ts +14 -0
- package/src/domains/dispatch/worker-spawn.ts +21 -2
- package/src/domains/eval/metrics/context.ts +1 -1
- package/src/domains/eval/types.ts +0 -1
- package/src/domains/evidence/build.ts +41 -1
- package/src/domains/lifecycle/migrations/2026-08-18-lmstudio-runtime-id.ts +52 -0
- package/src/domains/lifecycle/migrations/index.ts +24 -4
- package/src/domains/middleware/hooks-io.ts +12 -0
- package/src/domains/middleware/skills-reminder.ts +30 -15
- package/src/domains/prompts/compiler.ts +142 -84
- package/src/domains/prompts/contract.ts +18 -2
- package/src/domains/prompts/extension.ts +39 -7
- package/src/domains/prompts/fragment-loader.ts +0 -1
- package/src/domains/prompts/fragments/identity/clio.md +2 -4
- package/src/domains/prompts/fragments/identity/docs-routing.md +10 -0
- package/src/domains/prompts/fragments/identity/self-awareness.md +1 -45
- package/src/domains/prompts/fragments/operating/contract.md +4 -50
- package/src/domains/prompts/fragments/operating/delegation.md +42 -0
- package/src/domains/prompts/fragments/operating/skills.md +26 -0
- package/src/domains/prompts/fragments/operating/worker.md +16 -0
- package/src/domains/prompts/fragments/safety/auto-edit.md +5 -5
- package/src/domains/prompts/fragments/safety/full-auto.md +3 -3
- package/src/domains/prompts/fragments/safety/read-only.md +4 -4
- package/src/domains/prompts/fragments/safety/suggest.md +2 -2
- package/src/domains/prompts/fragments/wiki/page.md +10 -0
- package/src/domains/prompts/fragments/wiki/plan.md +10 -0
- package/src/domains/prompts/preload.ts +3 -3
- package/src/domains/providers/auth/api-key.ts +1 -1
- package/src/domains/providers/auth/backend-file.ts +20 -10
- package/src/domains/providers/auth/backend-memory.ts +59 -4
- package/src/domains/providers/auth/boot-status.ts +65 -0
- package/src/domains/providers/auth/oauth.ts +2 -1
- package/src/domains/providers/auth/storage.ts +97 -38
- package/src/domains/providers/capabilities.ts +12 -4
- package/src/domains/providers/contract.ts +15 -4
- package/src/domains/providers/extension.ts +18 -6
- package/src/domains/providers/model-runtime-capabilities.ts +15 -4
- package/src/domains/providers/models/local-models/clio-local-coding-targets.yaml +118 -35
- package/src/domains/providers/plugins.ts +5 -3
- package/src/domains/providers/probe/fingerprint.ts +25 -5
- package/src/domains/providers/registry.ts +31 -10
- package/src/domains/providers/runtimes/boot-manifest.ts +55 -0
- package/src/domains/providers/runtimes/builtins.ts +2 -2
- package/src/domains/providers/runtimes/common/lmstudio-http.ts +423 -0
- package/src/domains/providers/runtimes/common/local-synth.ts +6 -7
- package/src/domains/providers/runtimes/local-native/lmstudio.ts +241 -0
- package/src/domains/providers/support.ts +6 -3
- package/src/domains/providers/types/local-model-quirks.ts +7 -9
- package/src/domains/providers/types/runtime-descriptor.ts +12 -1
- package/src/domains/providers/types/target-descriptor.ts +22 -0
- package/src/domains/resources/contract.ts +0 -1
- package/src/domains/resources/extension.ts +1 -3
- package/src/domains/resources/loader.ts +3 -4
- package/src/domains/resources/prompts/loader.ts +16 -2
- package/src/domains/resources/prompts/substitute.ts +1 -65
- package/src/domains/resources/skills/content-hash.ts +2 -0
- package/src/domains/resources/skills/install.ts +17 -0
- package/src/domains/resources/skills/loader.ts +17 -10
- package/src/domains/resources/skills/marketplace.ts +55 -9
- package/src/domains/safety/action-classifier.ts +4 -2
- package/src/domains/safety/audit.ts +8 -2
- package/src/domains/safety/extension.ts +1 -1
- package/src/domains/session/compaction/branch-summary.ts +3 -2
- package/src/domains/session/compaction/cut-point.ts +2 -1
- package/src/domains/session/compaction/tokens.ts +2 -1
- package/src/domains/session/context-ledger.ts +14 -0
- package/src/domains/session/contract.ts +15 -0
- package/src/domains/session/decision-board.ts +190 -0
- package/src/domains/session/entries.ts +66 -3
- package/src/domains/session/extension.ts +93 -12
- package/src/domains/session/retry.ts +10 -18
- package/src/domains/session/session-artifacts.ts +107 -0
- package/src/domains/session/task-board.ts +207 -13
- package/src/domains/session/tree/active-path.ts +44 -5
- package/src/domains/session/tree/fork.ts +26 -27
- package/src/domains/session/tree/preview.ts +2 -2
- package/src/domains/session/workspace/git-probe.ts +17 -11
- package/src/domains/user-tasks/store.ts +297 -0
- package/src/engine/acp/errors.ts +96 -0
- package/src/engine/acp/server.ts +1728 -146
- package/src/engine/acp/transport.ts +135 -14
- package/src/engine/acp/types.ts +26 -0
- package/src/engine/agent.ts +3 -3
- package/src/engine/ai.ts +32 -27
- package/src/engine/alcf-oauth.ts +26 -19
- package/src/engine/api-registry.ts +223 -0
- package/src/engine/apis/index.ts +3 -7
- package/src/engine/apis/llamacpp-residency.ts +49 -9
- package/src/engine/apis/lmstudio-residency.ts +5 -21
- package/src/engine/apis/lmstudio.ts +243 -0
- package/src/engine/apis/ollama-native.ts +24 -3
- package/src/engine/apis/openai-completions.ts +170 -91
- package/src/engine/apis/residency.ts +139 -3
- package/src/engine/apis/types.ts +16 -0
- package/src/engine/env-api-keys.ts +98 -0
- package/src/engine/gemma-channel-filter.ts +223 -0
- package/src/engine/instrumented-tui.ts +192 -0
- package/src/engine/messages.ts +14 -0
- package/src/engine/models.ts +42 -0
- package/src/engine/oauth.ts +16 -12
- package/src/engine/prompt-templates.ts +1 -0
- package/src/engine/provider-payload.ts +16 -59
- package/src/engine/strip-tokenizer-sentinels.ts +1 -1
- package/src/engine/truncate.ts +9 -0
- package/src/engine/tui.ts +17 -9
- package/src/engine/types.ts +3 -6
- package/src/engine/worker-runtime-capabilities.ts +5 -0
- package/src/engine/worker-runtime.ts +1 -1
- package/src/engine/worker-tools.ts +9 -4
- package/src/entry/boot-options.ts +50 -0
- package/src/entry/orchestrator.ts +288 -150
- package/src/interactive/application-controller.ts +89 -2
- package/src/interactive/chat-loop.ts +266 -41
- package/src/interactive/chat-panel.ts +715 -278
- package/src/interactive/chat-renderer.ts +306 -85
- package/src/interactive/clio-editor.ts +3 -8
- package/src/interactive/command-fallbacks.ts +2 -2
- package/src/interactive/context-overlay.ts +27 -1
- package/src/interactive/editor-submit.ts +253 -24
- package/src/interactive/export-html/ansi-to-html.ts +161 -0
- package/src/interactive/export-html/index.ts +51 -0
- package/src/interactive/export-html/template.ts +45 -0
- package/src/interactive/export-html/tool-renderer.ts +54 -0
- package/src/interactive/footer/dashboard.ts +4 -0
- package/src/interactive/footer/notifications.ts +1 -1
- package/src/interactive/footer/widgets.ts +42 -22
- package/src/interactive/footer-panel.ts +8 -3
- package/src/interactive/format-time.ts +14 -2
- package/src/interactive/interactive-application.ts +203 -17
- package/src/interactive/interactive-event-projection.ts +18 -1
- package/src/interactive/interactive-input-runtime.ts +50 -4
- package/src/interactive/interactive-presentation.ts +151 -19
- package/src/interactive/interactive-shell.ts +268 -14
- package/src/interactive/interactive-slash-runtime.ts +184 -117
- package/src/interactive/interactive-tickers.ts +38 -7
- package/src/interactive/keybinding-manager.ts +1 -1
- package/src/interactive/layout.ts +40 -3
- package/src/interactive/overlay-frame.ts +1 -1
- package/src/interactive/overlay-general-openers.ts +58 -1
- package/src/interactive/overlay-key-routing.ts +3 -0
- package/src/interactive/overlay-lifecycle.ts +13 -0
- package/src/interactive/overlay-permission-lifecycle.ts +2 -1
- package/src/interactive/overlay-session-lifecycle.ts +69 -12
- package/src/interactive/overlays/ask-user.ts +146 -24
- package/src/interactive/overlays/decisions.ts +300 -0
- package/src/interactive/overlays/help-reference.ts +15 -10
- package/src/interactive/overlays/model-selector.ts +34 -16
- package/src/interactive/overlays/session-selector.ts +18 -0
- package/src/interactive/overlays/settings.ts +105 -17
- package/src/interactive/overlays/skills-hub.ts +4 -4
- package/src/interactive/overlays/tree-selector.ts +41 -6
- package/src/interactive/render-trace.ts +499 -90
- package/src/interactive/renderers/compaction-summary.ts +2 -2
- package/src/interactive/renderers/diff.ts +115 -104
- package/src/interactive/renderers/mermaid.ts +53 -0
- package/src/interactive/renderers/tool-execution.ts +516 -168
- package/src/interactive/renderers/worker-entry.ts +20 -4
- package/src/interactive/session-switch-settlement.ts +10 -0
- package/src/interactive/slash-autocomplete.ts +6 -114
- package/src/interactive/slash-commands.ts +135 -47
- package/src/interactive/slash-spec.ts +9 -38
- package/src/interactive/status/controller.ts +5 -1
- package/src/interactive/status/index.ts +12 -1
- package/src/interactive/status/reasoning.ts +87 -0
- package/src/interactive/status/summary.ts +13 -2
- package/src/interactive/stdout-backpressure.ts +99 -0
- package/src/interactive/stream-pacer.ts +530 -0
- package/src/interactive/stream-pacing-policy.ts +66 -0
- package/src/interactive/tasks-overlay.ts +368 -14
- package/src/interactive/terminal-lease.ts +485 -0
- package/src/interactive/theme/tokens.ts +1 -1
- package/src/interactive/transcript-detail.ts +120 -0
- package/src/interactive/turn-context.ts +4 -3
- package/src/interactive/turn-persistence.ts +30 -13
- package/src/interactive/turn-queues.ts +12 -0
- package/src/interactive/turn-recovery.ts +25 -8
- package/src/interactive/turn-runtime.ts +79 -12
- package/src/interactive/turn-state.ts +10 -0
- package/src/interactive/view/artifacts.ts +114 -4
- package/src/interactive/view/view-overlay.ts +3 -0
- package/src/interactive/welcome-dashboard.ts +17 -16
- package/src/interactive/worker-receipts.ts +52 -3
- package/src/interactive/worker-stream.ts +5 -1
- package/src/tools/agent-tools.ts +23 -3
- package/src/tools/artifact.ts +2 -2
- package/src/tools/ask-user.ts +23 -13
- package/src/tools/bash.ts +30 -2
- package/src/tools/bootstrap.ts +34 -431
- package/src/tools/builtin-tool-catalog.ts +271 -0
- package/src/tools/codewiki/code-nav-surface.ts +29 -0
- package/src/tools/codewiki/code-nav.ts +8 -22
- package/src/tools/codewiki/shared.ts +41 -38
- package/src/tools/context/docs-engine.ts +14 -3
- package/src/tools/context/index.ts +107 -28
- package/src/tools/context/surface.ts +19 -0
- package/src/tools/core-bootstrap.ts +168 -0
- package/src/tools/credential-present.ts +5 -5
- package/src/tools/dispatch-admission.ts +533 -0
- package/src/tools/dispatch-background.ts +54 -0
- package/src/tools/dispatch-event-text.ts +6 -0
- package/src/tools/dispatch-plan.ts +9 -4
- package/src/tools/dispatch-run-events.ts +238 -0
- package/src/tools/dispatch-runner.ts +2370 -0
- package/src/tools/dispatch-scout-admission.ts +295 -0
- package/src/tools/dispatch-types.ts +77 -0
- package/src/tools/dispatch.ts +67 -3161
- package/src/tools/find.ts +4 -2
- package/src/tools/grep.ts +2 -2
- package/src/tools/lazy-tool.ts +60 -0
- package/src/tools/ledger.ts +3 -3
- package/src/tools/monitor-surface.ts +36 -0
- package/src/tools/monitor.ts +2 -32
- package/src/tools/observers.ts +2 -2
- package/src/tools/presentation.ts +107 -0
- package/src/tools/registry.ts +45 -27
- package/src/tools/safe-exec.ts +2 -2
- package/src/tools/steer-surface.ts +17 -0
- package/src/tools/steer.ts +2 -13
- package/src/tools/tasks.ts +108 -11
- package/src/tools/truncate.ts +25 -184
- package/src/tools/verify/frontend.ts +3 -1
- package/src/tools/verify/index.ts +3 -38
- package/src/tools/verify/surface.ts +46 -0
- package/src/tools/web-fetch-surface.ts +23 -0
- package/src/tools/web-fetch.ts +2 -20
- package/src/tools/write.ts +7 -2
- package/src/worker/entry.ts +39 -2
- package/src/worker/spec-contract.ts +26 -5
- package/dist/chunk-7SS2CTV2.js +0 -61361
- package/dist/chunk-DKGKUHFA.js +0 -924
- package/dist/chunk-GEP36Y4X.js +0 -12796
- package/dist/chunk-XYWBQRDM.js +0 -137
- package/dist/clio-BZVGEUFJ.js +0 -58
- package/dist/configure-S7S6F6CL.js +0 -32
- package/docs/html/agents_blueprint.html +0 -936
- package/docs/html/alcf_blueprint.html +0 -324
- package/docs/html/architecture_blueprint.html +0 -850
- package/docs/html/commands_blueprint.html +0 -939
- package/docs/html/config_knobs_audit_blueprint.html +0 -178
- package/docs/html/configuration_blueprint.html +0 -1080
- package/docs/html/context_blueprint.html +0 -603
- package/docs/html/documentation_blueprint.html +0 -832
- package/docs/html/environment_blueprint.html +0 -404
- package/docs/html/eval_blueprint.html +0 -743
- package/docs/html/evals_internal_blueprint.html +0 -190
- package/docs/html/evolution_blueprint.html +0 -674
- package/docs/html/extensions_blueprint.html +0 -2065
- package/docs/html/fleet_dispatch_blueprint.html +0 -286
- package/docs/html/index.html +0 -919
- package/docs/html/lifecycle_blueprint.html +0 -723
- package/docs/html/memory_blueprint.html +0 -699
- package/docs/html/middleware_blueprint.html +0 -664
- package/docs/html/models_blueprint.html +0 -2366
- package/docs/html/observability_blueprint.html +0 -683
- package/docs/html/provider_adapter_blueprint.html +0 -245
- package/docs/html/safety_blueprint.html +0 -1386
- package/docs/html/shared.css +0 -571
- package/docs/html/shared.js +0 -143
- package/docs/html/skills_blueprint.html +0 -671
- package/docs/html/soak_blueprint.html +0 -182
- package/docs/html/tool_usage_blueprint.html +0 -350
- package/docs/html/tools_blueprint.html +0 -2249
- package/docs/html/trace_blueprint.html +0 -235
- package/docs/html/tui_design_blueprint.html +0 -374
- package/docs/html/validation_blueprint.html +0 -961
- package/docs/html/worker_dispatch_blueprint.html +0 -231
- package/src/core/release.ts +0 -2
- package/src/domains/providers/runtimes/common/lmstudio-logger.ts +0 -32
- package/src/domains/providers/runtimes/local-native/lmstudio-native.ts +0 -491
- package/src/engine/apis/lmstudio-native.ts +0 -1438
- package/src/engine/apis/thinking-replay.ts +0 -11
- package/src/tools/string-enum.ts +0 -15
package/src/tools/tasks.ts
CHANGED
|
@@ -7,8 +7,9 @@ import {
|
|
|
7
7
|
type TaskBoardTask,
|
|
8
8
|
taskBoardCounts,
|
|
9
9
|
} from "../domains/session/task-board.js";
|
|
10
|
+
import type { UserTask, UserTasksStore } from "../domains/user-tasks/store.js";
|
|
11
|
+
import { StringEnum } from "../engine/ai.js";
|
|
10
12
|
import type { ToolResult, ToolSpec } from "./registry.js";
|
|
11
|
-
import { stringEnum } from "./string-enum.js";
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* The tasks tool: the session task board. The agent declares what it is
|
|
@@ -23,7 +24,7 @@ import { stringEnum } from "./string-enum.js";
|
|
|
23
24
|
* track it across turns.
|
|
24
25
|
*/
|
|
25
26
|
|
|
26
|
-
const TASKS_ACTIONS = ["plan", "add", "start", "done", "block", "drop", "list"] as const;
|
|
27
|
+
const TASKS_ACTIONS = ["plan", "add", "pick", "start", "done", "block", "drop", "list"] as const;
|
|
27
28
|
type TasksAction = (typeof TASKS_ACTIONS)[number];
|
|
28
29
|
|
|
29
30
|
/** Plain-text status markers for model-facing output; the TUI owns glyphs. */
|
|
@@ -37,9 +38,20 @@ const STATUS_MARK: Record<TaskBoardTask["status"], string> = {
|
|
|
37
38
|
|
|
38
39
|
export interface TasksToolDeps {
|
|
39
40
|
board: TaskBoardStore;
|
|
41
|
+
userTasks?: UserTasksStore;
|
|
42
|
+
getSessionId?: () => string | null;
|
|
40
43
|
}
|
|
41
44
|
|
|
42
|
-
function
|
|
45
|
+
function waitingTrailer(tasks: ReadonlyArray<UserTask>): string[] {
|
|
46
|
+
return tasks
|
|
47
|
+
.filter((task) => task.status === "open" || task.status === "handed")
|
|
48
|
+
.map(
|
|
49
|
+
(task) =>
|
|
50
|
+
`operator tasks waiting: ${task.id} ${JSON.stringify(task.title)} — pick up with action="pick" id="${task.id}"`,
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function renderTaskBoardText(board: TaskBoardSnapshot, userTasks: ReadonlyArray<UserTask> = []): string {
|
|
43
55
|
const counts = taskBoardCounts(board);
|
|
44
56
|
const lines: string[] = [`board "${board.title}" ${counts.completed}/${counts.total} done`];
|
|
45
57
|
for (const task of board.tasks) {
|
|
@@ -52,6 +64,7 @@ function renderTaskBoardText(board: TaskBoardSnapshot): string {
|
|
|
52
64
|
if (counts.open > 0 && counts.active === 0) {
|
|
53
65
|
lines.push(`next: start a task with action="start" before working it`);
|
|
54
66
|
}
|
|
67
|
+
lines.push(...waitingTrailer(userTasks));
|
|
55
68
|
return lines.join("\n");
|
|
56
69
|
}
|
|
57
70
|
|
|
@@ -60,6 +73,7 @@ function boardDetails(action: TasksAction, board: TaskBoardSnapshot | null): Rec
|
|
|
60
73
|
const counts = taskBoardCounts(board);
|
|
61
74
|
return {
|
|
62
75
|
action,
|
|
76
|
+
boardId: board.boardId,
|
|
63
77
|
title: board.title,
|
|
64
78
|
counts,
|
|
65
79
|
tasks: board.tasks.map((task) => ({ ...task })),
|
|
@@ -87,6 +101,8 @@ function mutationFromArgs(action: TasksAction, args: Record<string, unknown>): T
|
|
|
87
101
|
}
|
|
88
102
|
case "add":
|
|
89
103
|
return { op: "add", tasks: taskTitlesArg(args) };
|
|
104
|
+
case "pick":
|
|
105
|
+
return { error: "pick is resolved from the durable operator task inbox" };
|
|
90
106
|
case "start":
|
|
91
107
|
case "done":
|
|
92
108
|
case "block":
|
|
@@ -105,18 +121,32 @@ function mutationFromArgs(action: TasksAction, args: Record<string, unknown>): T
|
|
|
105
121
|
}
|
|
106
122
|
|
|
107
123
|
export function createTasksTool(deps: TasksToolDeps): ToolSpec {
|
|
124
|
+
const reconcileUserTasks = (): ReadonlyArray<UserTask> => {
|
|
125
|
+
if (!deps.userTasks) return [];
|
|
126
|
+
const sessionId = deps.getSessionId?.();
|
|
127
|
+
if (!sessionId) return deps.userTasks.snapshot();
|
|
128
|
+
const links =
|
|
129
|
+
deps.board
|
|
130
|
+
.snapshot()
|
|
131
|
+
?.tasks.flatMap((task) =>
|
|
132
|
+
task.userTaskId ? [{ userTaskId: task.userTaskId, boardTaskId: task.id, status: task.status }] : [],
|
|
133
|
+
) ?? [];
|
|
134
|
+
return deps.userTasks.reconcile(links, sessionId);
|
|
135
|
+
};
|
|
136
|
+
|
|
108
137
|
return {
|
|
109
138
|
name: ToolNames.Tasks,
|
|
110
139
|
description:
|
|
111
140
|
"Session task board. plan declares a titled board (replaces any prior board); add appends tasks; " +
|
|
112
|
-
"
|
|
141
|
+
"pick moves one operator task uN onto the board; start marks one task active (the current focus); " +
|
|
142
|
+
"done completes a started task and requires note as the " +
|
|
113
143
|
"evidence the work actually finished; block parks it with a required reason; drop cancels it; list shows the board. " +
|
|
114
144
|
"Work that did not happen is blocked or dropped, never done.",
|
|
115
145
|
parameters: Type.Object({
|
|
116
|
-
action:
|
|
146
|
+
action: StringEnum(TASKS_ACTIONS, { description: "Board action." }),
|
|
117
147
|
title: Type.Optional(Type.String({ description: "Board title (plan)." })),
|
|
118
148
|
tasks: Type.Optional(Type.Array(Type.String(), { description: "Task titles (plan, add)." })),
|
|
119
|
-
id: Type.Optional(Type.String({ description: 'Task id like "t2"
|
|
149
|
+
id: Type.Optional(Type.String({ description: 'Task id like "t2", or operator id "u2" for pick.' })),
|
|
120
150
|
note: Type.Optional(
|
|
121
151
|
Type.String({ description: "Evidence of completion (required for done) or the reason (block, drop)." }),
|
|
122
152
|
),
|
|
@@ -127,8 +157,11 @@ export function createTasksTool(deps: TasksToolDeps): ToolSpec {
|
|
|
127
157
|
const prepared = { ...args };
|
|
128
158
|
// Weak-model shapes: a numeric or bare-number id becomes "tN", and a
|
|
129
159
|
// JSON-string tasks array is parsed back into a real array.
|
|
130
|
-
|
|
131
|
-
if (typeof prepared.id === "
|
|
160
|
+
const idPrefix = prepared.action === "pick" ? "u" : "t";
|
|
161
|
+
if (typeof prepared.id === "number" && Number.isFinite(prepared.id)) prepared.id = `${idPrefix}${prepared.id}`;
|
|
162
|
+
if (typeof prepared.id === "string" && /^\d+$/.test(prepared.id.trim())) {
|
|
163
|
+
prepared.id = `${idPrefix}${prepared.id.trim()}`;
|
|
164
|
+
}
|
|
132
165
|
if (typeof prepared.tasks === "string" && prepared.tasks.trim().startsWith("[")) {
|
|
133
166
|
try {
|
|
134
167
|
const parsed = JSON.parse(prepared.tasks);
|
|
@@ -145,23 +178,87 @@ export function createTasksTool(deps: TasksToolDeps): ToolSpec {
|
|
|
145
178
|
return { kind: "error", message: `tasks: action must be one of ${TASKS_ACTIONS.join(", ")}; got '${action}'` };
|
|
146
179
|
}
|
|
147
180
|
const typedAction = action as TasksAction;
|
|
181
|
+
let userTasks: ReadonlyArray<UserTask>;
|
|
182
|
+
try {
|
|
183
|
+
userTasks = reconcileUserTasks();
|
|
184
|
+
} catch (error) {
|
|
185
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
186
|
+
return { kind: "error", message: `tasks: could not reconcile the operator task inbox: ${message}` };
|
|
187
|
+
}
|
|
148
188
|
if (typedAction === "list") {
|
|
149
189
|
const board = deps.board.snapshot();
|
|
150
190
|
if (!board) {
|
|
191
|
+
const output = ['no task board yet; declare one with action="plan"', ...waitingTrailer(userTasks)].join("\n");
|
|
151
192
|
return {
|
|
152
193
|
kind: "ok",
|
|
153
|
-
output
|
|
194
|
+
output,
|
|
154
195
|
details: boardDetails("list", null),
|
|
155
196
|
};
|
|
156
197
|
}
|
|
157
|
-
return { kind: "ok", output: renderTaskBoardText(board), details: boardDetails("list", board) };
|
|
198
|
+
return { kind: "ok", output: renderTaskBoardText(board, userTasks), details: boardDetails("list", board) };
|
|
158
199
|
}
|
|
200
|
+
if (typedAction === "pick") {
|
|
201
|
+
if (!deps.userTasks) return { kind: "error", message: "tasks: operator task inbox is unavailable" };
|
|
202
|
+
const sessionId = deps.getSessionId?.();
|
|
203
|
+
if (!sessionId) return { kind: "error", message: "tasks: pick requires an active session" };
|
|
204
|
+
const id = stringArg(args, "id");
|
|
205
|
+
if (!id || !/^u[1-9]\d*$/.test(id)) {
|
|
206
|
+
return { kind: "error", message: 'tasks: pick requires an operator task id (e.g. id="u3")' };
|
|
207
|
+
}
|
|
208
|
+
const userTask = userTasks.find((task) => task.id === id);
|
|
209
|
+
if (!userTask) return { kind: "error", message: `tasks: operator task ${id} was not found` };
|
|
210
|
+
if (userTask.status !== "open" && userTask.status !== "handed") {
|
|
211
|
+
return { kind: "error", message: `tasks: operator task ${id} is ${userTask.status}; it cannot be picked` };
|
|
212
|
+
}
|
|
213
|
+
const result = deps.board.apply({ op: "pick", title: userTask.title, userTaskId: userTask.id });
|
|
214
|
+
if (!result.ok) return { kind: "error", message: `tasks: ${result.message}` };
|
|
215
|
+
const picked = result.board.tasks.find((task) => task.userTaskId === userTask.id && task.status === "pending");
|
|
216
|
+
if (!picked) return { kind: "error", message: `tasks: durable pickup for ${id} did not produce a board row` };
|
|
217
|
+
try {
|
|
218
|
+
deps.userTasks.recordPicked(userTask.id, sessionId, picked.id);
|
|
219
|
+
userTasks = deps.userTasks.snapshot();
|
|
220
|
+
} catch (error) {
|
|
221
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
222
|
+
return {
|
|
223
|
+
kind: "error",
|
|
224
|
+
message: `tasks: ${picked.id} durably picked up ${id}, but the operator inbox update failed: ${message}`,
|
|
225
|
+
details: boardDetails("pick", result.board),
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
return {
|
|
229
|
+
kind: "ok",
|
|
230
|
+
output: renderTaskBoardText(result.board, userTasks),
|
|
231
|
+
details: boardDetails("pick", result.board),
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
const before = deps.board.snapshot();
|
|
159
235
|
const mutation = mutationFromArgs(typedAction, args);
|
|
160
236
|
if ("error" in mutation) return { kind: "error", message: mutation.error };
|
|
237
|
+
const completedUserTask =
|
|
238
|
+
typedAction === "done" && mutation.op === "done"
|
|
239
|
+
? before?.tasks.find((task) => task.id === mutation.id && task.userTaskId)
|
|
240
|
+
: undefined;
|
|
241
|
+
const completionSessionId = completedUserTask?.userTaskId && deps.userTasks ? deps.getSessionId?.() : undefined;
|
|
242
|
+
if (completedUserTask?.userTaskId && deps.userTasks && !completionSessionId) {
|
|
243
|
+
return { kind: "error", message: "tasks: durable completion requires an active session" };
|
|
244
|
+
}
|
|
161
245
|
const result = deps.board.apply(mutation);
|
|
162
246
|
if (!result.ok) return { kind: "error", message: `tasks: ${result.message}` };
|
|
247
|
+
if (completedUserTask?.userTaskId && deps.userTasks && completionSessionId) {
|
|
248
|
+
try {
|
|
249
|
+
deps.userTasks.recordDone(completedUserTask.userTaskId, completionSessionId, completedUserTask.id);
|
|
250
|
+
userTasks = deps.userTasks.snapshot();
|
|
251
|
+
} catch (error) {
|
|
252
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
253
|
+
return {
|
|
254
|
+
kind: "error",
|
|
255
|
+
message: `tasks: ${completedUserTask.id} completed durably, but operator task ${completedUserTask.userTaskId} could not be updated: ${message}`,
|
|
256
|
+
details: boardDetails("done", result.board),
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
}
|
|
163
260
|
const noteLines = result.notes.map((note) => `note: ${note}`);
|
|
164
|
-
const output = [...noteLines, renderTaskBoardText(result.board)].join("\n");
|
|
261
|
+
const output = [...noteLines, renderTaskBoardText(result.board, userTasks)].join("\n");
|
|
165
262
|
return { kind: "ok", output, details: boardDetails(typedAction, result.board) };
|
|
166
263
|
},
|
|
167
264
|
};
|
package/src/tools/truncate.ts
CHANGED
|
@@ -1,38 +1,25 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import {
|
|
2
|
+
formatSize,
|
|
3
|
+
GREP_MAX_LINE_LENGTH,
|
|
4
|
+
type TruncationOptions,
|
|
5
|
+
type TruncationResult,
|
|
6
|
+
truncateLine,
|
|
7
|
+
truncateHead as truncatePiHead,
|
|
8
|
+
truncateTail as truncatePiTail,
|
|
9
|
+
} from "../engine/truncate.js";
|
|
10
|
+
|
|
11
|
+
// Per-observation source cap. Pi defaults to 50 KiB; Clio deliberately keeps
|
|
12
|
+
// one result proportional to its per-turn observation budget at 16 KiB. The
|
|
13
|
+
// wrappers below retain only that product-level delta while Pi owns UTF-8-safe
|
|
14
|
+
// head/tail truncation, line limits, grep-line clipping, and size formatting.
|
|
8
15
|
export const DEFAULT_MAX_LINES = 2000;
|
|
9
16
|
export const DEFAULT_MAX_BYTES = 16 * 1024;
|
|
10
|
-
export
|
|
17
|
+
export type { TruncationResult };
|
|
18
|
+
export { formatSize, GREP_MAX_LINE_LENGTH, truncateLine };
|
|
11
19
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
truncatedBy: "lines" | "bytes" | null;
|
|
16
|
-
totalLines: number;
|
|
17
|
-
totalBytes: number;
|
|
18
|
-
outputLines: number;
|
|
19
|
-
outputBytes: number;
|
|
20
|
-
lastLinePartial: boolean;
|
|
21
|
-
firstLineExceedsLimit: boolean;
|
|
22
|
-
maxLines: number;
|
|
23
|
-
maxBytes: number;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export interface TruncationOptions {
|
|
27
|
-
maxLines?: number;
|
|
28
|
-
maxBytes?: number;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// Count lines without a trailing-newline phantom entry. `"a\nb\n".split("\n")`
|
|
32
|
-
// yields `["a","b",""]` (3 entries) for a 2-line file; dropping the final empty
|
|
33
|
-
// element restores an honest count so continuation notices ("N more lines") do
|
|
34
|
-
// not over-report by one on newline-terminated files. Ported from pi's
|
|
35
|
-
// truncate.ts:47.
|
|
20
|
+
// Count lines without a trailing-newline phantom entry. Pi uses the same
|
|
21
|
+
// counting rule internally but does not export it; Clio's read continuation
|
|
22
|
+
// notices need the total before selecting a slice.
|
|
36
23
|
export function splitLinesForCounting(content: string): string[] {
|
|
37
24
|
if (content.length === 0) return [];
|
|
38
25
|
const lines = content.split("\n");
|
|
@@ -40,163 +27,17 @@ export function splitLinesForCounting(content: string): string[] {
|
|
|
40
27
|
return lines;
|
|
41
28
|
}
|
|
42
29
|
|
|
43
|
-
|
|
44
|
-
if (bytes < 1024) return `${bytes}B`;
|
|
45
|
-
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;
|
|
46
|
-
return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export function truncateHead(content: string, options: TruncationOptions = {}): TruncationResult {
|
|
50
|
-
const maxLines = options.maxLines ?? DEFAULT_MAX_LINES;
|
|
51
|
-
const maxBytes = options.maxBytes ?? DEFAULT_MAX_BYTES;
|
|
52
|
-
const totalBytes = Buffer.byteLength(content, "utf8");
|
|
53
|
-
const lines = splitLinesForCounting(content);
|
|
54
|
-
const totalLines = lines.length;
|
|
55
|
-
|
|
56
|
-
if (totalLines <= maxLines && totalBytes <= maxBytes) {
|
|
57
|
-
return {
|
|
58
|
-
content,
|
|
59
|
-
truncated: false,
|
|
60
|
-
truncatedBy: null,
|
|
61
|
-
totalLines,
|
|
62
|
-
totalBytes,
|
|
63
|
-
outputLines: totalLines,
|
|
64
|
-
outputBytes: totalBytes,
|
|
65
|
-
lastLinePartial: false,
|
|
66
|
-
firstLineExceedsLimit: false,
|
|
67
|
-
maxLines,
|
|
68
|
-
maxBytes,
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const firstLineBytes = Buffer.byteLength(lines[0] ?? "", "utf8");
|
|
73
|
-
if (firstLineBytes > maxBytes) {
|
|
74
|
-
return {
|
|
75
|
-
content: "",
|
|
76
|
-
truncated: true,
|
|
77
|
-
truncatedBy: "bytes",
|
|
78
|
-
totalLines,
|
|
79
|
-
totalBytes,
|
|
80
|
-
outputLines: 0,
|
|
81
|
-
outputBytes: 0,
|
|
82
|
-
lastLinePartial: false,
|
|
83
|
-
firstLineExceedsLimit: true,
|
|
84
|
-
maxLines,
|
|
85
|
-
maxBytes,
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const out: string[] = [];
|
|
90
|
-
let outputBytes = 0;
|
|
91
|
-
let truncatedBy: "lines" | "bytes" = "lines";
|
|
92
|
-
for (let i = 0; i < lines.length && i < maxLines; i += 1) {
|
|
93
|
-
const line = lines[i] ?? "";
|
|
94
|
-
const lineBytes = Buffer.byteLength(line, "utf8") + (i > 0 ? 1 : 0);
|
|
95
|
-
if (outputBytes + lineBytes > maxBytes) {
|
|
96
|
-
truncatedBy = "bytes";
|
|
97
|
-
break;
|
|
98
|
-
}
|
|
99
|
-
out.push(line);
|
|
100
|
-
outputBytes += lineBytes;
|
|
101
|
-
}
|
|
102
|
-
if (out.length >= maxLines && outputBytes <= maxBytes) truncatedBy = "lines";
|
|
103
|
-
const output = out.join("\n");
|
|
30
|
+
function withClioDefaults(options: TruncationOptions): Required<TruncationOptions> {
|
|
104
31
|
return {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
truncatedBy,
|
|
108
|
-
totalLines,
|
|
109
|
-
totalBytes,
|
|
110
|
-
outputLines: out.length,
|
|
111
|
-
outputBytes: Buffer.byteLength(output, "utf8"),
|
|
112
|
-
lastLinePartial: false,
|
|
113
|
-
firstLineExceedsLimit: false,
|
|
114
|
-
maxLines,
|
|
115
|
-
maxBytes,
|
|
32
|
+
maxLines: options.maxLines ?? DEFAULT_MAX_LINES,
|
|
33
|
+
maxBytes: options.maxBytes ?? DEFAULT_MAX_BYTES,
|
|
116
34
|
};
|
|
117
35
|
}
|
|
118
36
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
function truncateStringToBytesFromEnd(str: string, maxBytes: number): string {
|
|
122
|
-
const buf = Buffer.from(str, "utf8");
|
|
123
|
-
if (buf.length <= maxBytes) return str;
|
|
124
|
-
let start = buf.length - maxBytes;
|
|
125
|
-
while (start < buf.length && ((buf[start] ?? 0) & 0xc0) === 0x80) start += 1;
|
|
126
|
-
return buf.subarray(start).toString("utf8");
|
|
37
|
+
export function truncateHead(content: string, options: TruncationOptions = {}): TruncationResult {
|
|
38
|
+
return truncatePiHead(content, withClioDefaults(options));
|
|
127
39
|
}
|
|
128
40
|
|
|
129
|
-
// Keep the LAST N lines / bytes (whichever cap is hit first). Suitable for
|
|
130
|
-
// shell/build/test output where the failing assertion, compiler error, and
|
|
131
|
-
// exit summary live at the end. Ported from pi's truncate.ts:168, including the
|
|
132
|
-
// partial-last-line edge case: when the final line alone exceeds maxBytes, the
|
|
133
|
-
// end of that line is kept and lastLinePartial is set.
|
|
134
41
|
export function truncateTail(content: string, options: TruncationOptions = {}): TruncationResult {
|
|
135
|
-
|
|
136
|
-
const maxBytes = options.maxBytes ?? DEFAULT_MAX_BYTES;
|
|
137
|
-
const totalBytes = Buffer.byteLength(content, "utf8");
|
|
138
|
-
const lines = splitLinesForCounting(content);
|
|
139
|
-
const totalLines = lines.length;
|
|
140
|
-
|
|
141
|
-
if (totalLines <= maxLines && totalBytes <= maxBytes) {
|
|
142
|
-
return {
|
|
143
|
-
content,
|
|
144
|
-
truncated: false,
|
|
145
|
-
truncatedBy: null,
|
|
146
|
-
totalLines,
|
|
147
|
-
totalBytes,
|
|
148
|
-
outputLines: totalLines,
|
|
149
|
-
outputBytes: totalBytes,
|
|
150
|
-
lastLinePartial: false,
|
|
151
|
-
firstLineExceedsLimit: false,
|
|
152
|
-
maxLines,
|
|
153
|
-
maxBytes,
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
const out: string[] = [];
|
|
158
|
-
let outputBytes = 0;
|
|
159
|
-
let truncatedBy: "lines" | "bytes" = "lines";
|
|
160
|
-
let lastLinePartial = false;
|
|
161
|
-
for (let i = lines.length - 1; i >= 0 && out.length < maxLines; i -= 1) {
|
|
162
|
-
const line = lines[i] ?? "";
|
|
163
|
-
const lineBytes = Buffer.byteLength(line, "utf8") + (out.length > 0 ? 1 : 0);
|
|
164
|
-
if (outputBytes + lineBytes > maxBytes) {
|
|
165
|
-
truncatedBy = "bytes";
|
|
166
|
-
// The final line alone overflows the budget: keep its tail so the
|
|
167
|
-
// last bytes (the exit summary) are still shown, flagged partial.
|
|
168
|
-
if (out.length === 0) {
|
|
169
|
-
const truncatedLine = truncateStringToBytesFromEnd(line, maxBytes);
|
|
170
|
-
out.unshift(truncatedLine);
|
|
171
|
-
outputBytes = Buffer.byteLength(truncatedLine, "utf8");
|
|
172
|
-
lastLinePartial = true;
|
|
173
|
-
}
|
|
174
|
-
break;
|
|
175
|
-
}
|
|
176
|
-
out.unshift(line);
|
|
177
|
-
outputBytes += lineBytes;
|
|
178
|
-
}
|
|
179
|
-
if (out.length >= maxLines && outputBytes <= maxBytes) truncatedBy = "lines";
|
|
180
|
-
const output = out.join("\n");
|
|
181
|
-
return {
|
|
182
|
-
content: output,
|
|
183
|
-
truncated: true,
|
|
184
|
-
truncatedBy,
|
|
185
|
-
totalLines,
|
|
186
|
-
totalBytes,
|
|
187
|
-
outputLines: out.length,
|
|
188
|
-
outputBytes: Buffer.byteLength(output, "utf8"),
|
|
189
|
-
lastLinePartial,
|
|
190
|
-
firstLineExceedsLimit: false,
|
|
191
|
-
maxLines,
|
|
192
|
-
maxBytes,
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
export function truncateLine(
|
|
197
|
-
line: string,
|
|
198
|
-
maxChars: number = GREP_MAX_LINE_LENGTH,
|
|
199
|
-
): { text: string; wasTruncated: boolean } {
|
|
200
|
-
if (line.length <= maxChars) return { text: line, wasTruncated: false };
|
|
201
|
-
return { text: `${line.slice(0, maxChars)}... [truncated]`, wasTruncated: true };
|
|
42
|
+
return truncatePiTail(content, withClioDefaults(options));
|
|
202
43
|
}
|
|
@@ -9,8 +9,10 @@ import { resolveReadPath } from "../path-utils.js";
|
|
|
9
9
|
import type { ToolResult, ToolResultDetails } from "../registry.js";
|
|
10
10
|
import { maxOutputArg, timeoutArg } from "../safe-exec.js";
|
|
11
11
|
import { truncateUtf8 } from "../truncate-utf8.js";
|
|
12
|
+
import { BROWSER_MODES } from "./surface.js";
|
|
13
|
+
|
|
14
|
+
export { BROWSER_MODES } from "./surface.js";
|
|
12
15
|
|
|
13
|
-
export const BROWSER_MODES = ["auto", "required", "off"] as const;
|
|
14
16
|
type BrowserMode = (typeof BROWSER_MODES)[number];
|
|
15
17
|
|
|
16
18
|
type CheckStatus = "pass" | "warn" | "fail" | "skip";
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import { Type } from "typebox";
|
|
2
|
-
import { ToolNames } from "../../core/tool-names.js";
|
|
3
1
|
import { isVerificationScriptName } from "../../core/verification-scripts.js";
|
|
4
2
|
import type { ToolResult, ToolSpec } from "../registry.js";
|
|
5
|
-
import {
|
|
6
|
-
import { BROWSER_MODES, runFrontendCheck } from "./frontend.js";
|
|
3
|
+
import { runFrontendCheck } from "./frontend.js";
|
|
7
4
|
import { listChecks, runScriptCheck, VERIFICATION_SCRIPT_FAMILY_HINT } from "./scripts.js";
|
|
5
|
+
import { prepareVerifyArguments, verifyToolSurface } from "./surface.js";
|
|
8
6
|
|
|
9
7
|
/**
|
|
10
8
|
* The verify tool: one EXECUTE entry point for declared verification.
|
|
@@ -13,41 +11,8 @@ import { listChecks, runScriptCheck, VERIFICATION_SCRIPT_FAMILY_HINT } from "./s
|
|
|
13
11
|
* path=<file>) validates an HTML/CSS/JS artifact without shell access.
|
|
14
12
|
*/
|
|
15
13
|
|
|
16
|
-
/** Tolerate the weak-model shape of `args` sent as a JSON string. */
|
|
17
|
-
function prepareVerifyArguments(args: Record<string, unknown>): Record<string, unknown> {
|
|
18
|
-
if (!args || typeof args !== "object" || Array.isArray(args)) return args;
|
|
19
|
-
const next: Record<string, unknown> = { ...args };
|
|
20
|
-
if (typeof next.args === "string") {
|
|
21
|
-
try {
|
|
22
|
-
const parsed = JSON.parse(next.args) as unknown;
|
|
23
|
-
if (Array.isArray(parsed)) next.args = parsed;
|
|
24
|
-
} catch {
|
|
25
|
-
// Leave the malformed string; runScriptCheck ignores non-arrays.
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
return next;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
14
|
export const verifyTool: ToolSpec = {
|
|
32
|
-
|
|
33
|
-
description:
|
|
34
|
-
'Run a declared verification check: no arguments lists checks, check=<package.json script> runs it, check="frontend" with path validates an HTML/CSS/JS artifact.',
|
|
35
|
-
parameters: Type.Object({
|
|
36
|
-
check: Type.Optional(
|
|
37
|
-
Type.String({
|
|
38
|
-
description: `Declared script name (${VERIFICATION_SCRIPT_FAMILY_HINT}) or "frontend". Omit to list available checks.`,
|
|
39
|
-
}),
|
|
40
|
-
),
|
|
41
|
-
path: Type.Optional(Type.String({ description: "check=frontend: artifact file under the workspace root." })),
|
|
42
|
-
args: Type.Optional(Type.Array(Type.String(), { description: "Extra arguments passed after --." })),
|
|
43
|
-
browser: Type.Optional(stringEnum(BROWSER_MODES, "check=frontend: headless browser mode (default auto).")),
|
|
44
|
-
cwd: Type.Optional(Type.String({ description: "Working directory." })),
|
|
45
|
-
timeout_ms: Type.Optional(Type.Number({ description: "Timeout in ms (default 120000)." })),
|
|
46
|
-
max_output_bytes: Type.Optional(Type.Number({ description: "Output cap in bytes (default 600000)." })),
|
|
47
|
-
}),
|
|
48
|
-
baseActionClass: "execute",
|
|
49
|
-
executionMode: "sequential",
|
|
50
|
-
prepareArguments: prepareVerifyArguments,
|
|
15
|
+
...verifyToolSurface,
|
|
51
16
|
async run(rawArgs, options): Promise<ToolResult> {
|
|
52
17
|
const args = prepareVerifyArguments(rawArgs);
|
|
53
18
|
const check = typeof args.check === "string" ? args.check.trim() : "";
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Type } from "typebox";
|
|
2
|
+
import { ToolNames } from "../../core/tool-names.js";
|
|
3
|
+
import { VERIFICATION_SCRIPT_FAMILY_HINT } from "../../core/verification-scripts.js";
|
|
4
|
+
import { StringEnum } from "../../engine/ai.js";
|
|
5
|
+
import type { ToolSurface } from "../lazy-tool.js";
|
|
6
|
+
|
|
7
|
+
export const BROWSER_MODES = ["auto", "required", "off"] as const;
|
|
8
|
+
|
|
9
|
+
/** Tolerate the weak-model shape of `args` sent as a JSON string. */
|
|
10
|
+
export function prepareVerifyArguments(args: Record<string, unknown>): Record<string, unknown> {
|
|
11
|
+
if (!args || typeof args !== "object" || Array.isArray(args)) return args;
|
|
12
|
+
const next: Record<string, unknown> = { ...args };
|
|
13
|
+
if (typeof next.args === "string") {
|
|
14
|
+
try {
|
|
15
|
+
const parsed = JSON.parse(next.args) as unknown;
|
|
16
|
+
if (Array.isArray(parsed)) next.args = parsed;
|
|
17
|
+
} catch {
|
|
18
|
+
// Leave the malformed string; runScriptCheck ignores non-arrays.
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return next;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const verifyToolSurface = {
|
|
25
|
+
name: ToolNames.Verify,
|
|
26
|
+
description:
|
|
27
|
+
'Run a declared verification check: no arguments lists checks, check=<package.json script> runs it, check="frontend" with path validates an HTML/CSS/JS artifact.',
|
|
28
|
+
parameters: Type.Object({
|
|
29
|
+
check: Type.Optional(
|
|
30
|
+
Type.String({
|
|
31
|
+
description: `Declared script name (${VERIFICATION_SCRIPT_FAMILY_HINT}) or "frontend". Omit to list available checks.`,
|
|
32
|
+
}),
|
|
33
|
+
),
|
|
34
|
+
path: Type.Optional(Type.String({ description: "check=frontend: artifact file under the workspace root." })),
|
|
35
|
+
args: Type.Optional(Type.Array(Type.String(), { description: "Extra arguments passed after --." })),
|
|
36
|
+
browser: Type.Optional(
|
|
37
|
+
StringEnum(BROWSER_MODES, { description: "check=frontend: headless browser mode (default auto)." }),
|
|
38
|
+
),
|
|
39
|
+
cwd: Type.Optional(Type.String({ description: "Working directory." })),
|
|
40
|
+
timeout_ms: Type.Optional(Type.Number({ description: "Timeout in ms (default 120000)." })),
|
|
41
|
+
max_output_bytes: Type.Optional(Type.Number({ description: "Output cap in bytes (default 600000)." })),
|
|
42
|
+
}),
|
|
43
|
+
baseActionClass: "execute",
|
|
44
|
+
executionMode: "sequential",
|
|
45
|
+
prepareArguments: prepareVerifyArguments,
|
|
46
|
+
} satisfies ToolSurface;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Type } from "typebox";
|
|
2
|
+
import { ToolNames } from "../core/tool-names.js";
|
|
3
|
+
import type { ToolSurface } from "./lazy-tool.js";
|
|
4
|
+
|
|
5
|
+
export const webFetchToolSurface = {
|
|
6
|
+
name: ToolNames.WebFetch,
|
|
7
|
+
description: "Fetch an http(s) URL; HTML is cleaned and converted to Markdown. Non-2xx responses are errors.",
|
|
8
|
+
parameters: Type.Object({
|
|
9
|
+
url: Type.String({ description: "Fully-qualified http(s) URL." }),
|
|
10
|
+
method: Type.Optional(Type.String({ description: "HTTP method (default GET)." })),
|
|
11
|
+
headers: Type.Optional(Type.Record(Type.String(), Type.String(), { description: "Request headers." })),
|
|
12
|
+
body: Type.Optional(Type.String({ description: "Request body (POST/PUT)." })),
|
|
13
|
+
timeout_ms: Type.Optional(Type.Number({ description: "Timeout ms (default 30000)." })),
|
|
14
|
+
max_bytes: Type.Optional(Type.Number({ description: "Max bytes returned (default 600000)." })),
|
|
15
|
+
format: Type.Optional(
|
|
16
|
+
Type.String({
|
|
17
|
+
description: "auto (default: HTML is cleaned to Markdown, other content passes through) or raw (no conversion).",
|
|
18
|
+
}),
|
|
19
|
+
),
|
|
20
|
+
}),
|
|
21
|
+
baseActionClass: "read",
|
|
22
|
+
executionMode: "parallel",
|
|
23
|
+
} satisfies ToolSurface;
|
package/src/tools/web-fetch.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import { Type } from "typebox";
|
|
2
|
-
import { fetch } from "undici";
|
|
3
|
-
import { ToolNames } from "../core/tool-names.js";
|
|
4
1
|
import type { ToolResult, ToolSpec } from "./registry.js";
|
|
5
2
|
import { truncateUtf8 } from "./truncate-utf8.js";
|
|
3
|
+
import { webFetchToolSurface } from "./web-fetch-surface.js";
|
|
6
4
|
|
|
7
5
|
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
8
6
|
const DEFAULT_MAX_BYTES = 600_000;
|
|
@@ -627,23 +625,7 @@ function formatOutput(args: {
|
|
|
627
625
|
}
|
|
628
626
|
|
|
629
627
|
export const webFetchTool: ToolSpec = {
|
|
630
|
-
|
|
631
|
-
description: "Fetch an http(s) URL; HTML is cleaned and converted to Markdown. Non-2xx responses are errors.",
|
|
632
|
-
parameters: Type.Object({
|
|
633
|
-
url: Type.String({ description: "Fully-qualified http(s) URL." }),
|
|
634
|
-
method: Type.Optional(Type.String({ description: "HTTP method (default GET)." })),
|
|
635
|
-
headers: Type.Optional(Type.Record(Type.String(), Type.String(), { description: "Request headers." })),
|
|
636
|
-
body: Type.Optional(Type.String({ description: "Request body (POST/PUT)." })),
|
|
637
|
-
timeout_ms: Type.Optional(Type.Number({ description: "Timeout ms (default 30000)." })),
|
|
638
|
-
max_bytes: Type.Optional(Type.Number({ description: "Max bytes returned (default 600000)." })),
|
|
639
|
-
format: Type.Optional(
|
|
640
|
-
Type.String({
|
|
641
|
-
description: "auto (default: HTML is cleaned to Markdown, other content passes through) or raw (no conversion).",
|
|
642
|
-
}),
|
|
643
|
-
),
|
|
644
|
-
}),
|
|
645
|
-
baseActionClass: "read",
|
|
646
|
-
executionMode: "parallel",
|
|
628
|
+
...webFetchToolSurface,
|
|
647
629
|
async run(args, options): Promise<ToolResult> {
|
|
648
630
|
const urlArg = typeof args.url === "string" ? args.url : null;
|
|
649
631
|
if (!urlArg) return { kind: "error", message: "web_fetch: missing url argument" };
|
package/src/tools/write.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
|
2
2
|
import { dirname } from "node:path";
|
|
3
3
|
import { Type } from "typebox";
|
|
4
4
|
import { ToolNames } from "../core/tool-names.js";
|
|
5
|
+
import { generateDiffString } from "./edit-diff.js";
|
|
5
6
|
import { withFileMutationQueue } from "./file-mutation-queue.js";
|
|
6
7
|
import { resolveToCwd } from "./path-utils.js";
|
|
7
8
|
import type { ToolResult, ToolSpec } from "./registry.js";
|
|
@@ -25,16 +26,20 @@ export const writeTool: ToolSpec = {
|
|
|
25
26
|
const filePath = resolveToCwd(pathArg);
|
|
26
27
|
try {
|
|
27
28
|
let previousEndedWithNewline = false;
|
|
29
|
+
let previousContent = "";
|
|
28
30
|
await withFileMutationQueue(filePath, async () => {
|
|
29
31
|
try {
|
|
30
|
-
|
|
32
|
+
previousContent = readFileSync(filePath, "utf8");
|
|
33
|
+
previousEndedWithNewline = previousContent.endsWith("\n");
|
|
31
34
|
} catch {
|
|
35
|
+
previousContent = "";
|
|
32
36
|
previousEndedWithNewline = false;
|
|
33
37
|
}
|
|
34
38
|
mkdirSync(dirname(filePath), { recursive: true });
|
|
35
39
|
writeFileSync(filePath, content, "utf8");
|
|
36
40
|
});
|
|
37
41
|
const bytes = Buffer.byteLength(content, "utf8");
|
|
42
|
+
const diff = generateDiffString(previousContent, content).diff;
|
|
38
43
|
let output = `wrote ${bytes}B to ${pathArg}`;
|
|
39
44
|
if (previousEndedWithNewline && !content.endsWith("\n")) {
|
|
40
45
|
output += `\nnote: ${pathArg} no longer ends with a newline; the previous content did`;
|
|
@@ -43,7 +48,7 @@ export const writeTool: ToolSpec = {
|
|
|
43
48
|
// before it falls back to the length of the returned text. A write's
|
|
44
49
|
// text is a confirmation sentence, so without this the ledger printed
|
|
45
50
|
// the sentence's length as the file size.
|
|
46
|
-
return { kind: "ok", output, details: { paths: [filePath], observation: { shownBytes: bytes } } };
|
|
51
|
+
return { kind: "ok", output, details: { diff, paths: [filePath], observation: { shownBytes: bytes } } };
|
|
47
52
|
} catch (err) {
|
|
48
53
|
const msg = err instanceof Error ? err.message : String(err);
|
|
49
54
|
return { kind: "error", message: `write: ${msg}` };
|