@kr78/pi-coding-agent 17.2.10
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 +14861 -0
- package/README.md +35 -0
- package/dist/CHANGELOG-chtdxh1z.md +14861 -0
- package/dist/cli.js +20483 -0
- package/dist/template-c2hyaytt.js +1653 -0
- package/dist/template-f8wx9vfn.css +1355 -0
- package/dist/template-qat058wr.html +55 -0
- package/dist/tool-views.generated-jdfmzwmn.js +35 -0
- package/examples/README.md +21 -0
- package/examples/custom-tools/README.md +104 -0
- package/examples/custom-tools/hello/index.ts +20 -0
- package/examples/extensions/README.md +142 -0
- package/examples/extensions/api-demo.ts +78 -0
- package/examples/extensions/chalk-logger.ts +25 -0
- package/examples/extensions/hello.ts +31 -0
- package/examples/extensions/pirate.ts +43 -0
- package/examples/extensions/plan-mode.ts +549 -0
- package/examples/extensions/reload-runtime.ts +38 -0
- package/examples/extensions/thinking-note.ts +13 -0
- package/examples/extensions/tools.ts +145 -0
- package/examples/extensions/with-deps/index.ts +36 -0
- package/examples/extensions/with-deps/package-lock.json +31 -0
- package/examples/extensions/with-deps/package.json +17 -0
- package/examples/hooks/README.md +56 -0
- package/examples/hooks/auto-commit-on-exit.ts +48 -0
- package/examples/hooks/confirm-destructive.ts +58 -0
- package/examples/hooks/custom-compaction.ts +115 -0
- package/examples/hooks/dirty-repo-guard.ts +51 -0
- package/examples/hooks/file-trigger.ts +40 -0
- package/examples/hooks/git-checkpoint.ts +52 -0
- package/examples/hooks/handoff.ts +149 -0
- package/examples/hooks/permission-gate.ts +33 -0
- package/examples/hooks/protected-paths.ts +29 -0
- package/examples/hooks/qna.ts +118 -0
- package/examples/hooks/status-line.ts +39 -0
- package/examples/sdk/01-minimal.ts +21 -0
- package/examples/sdk/02-custom-model.ts +49 -0
- package/examples/sdk/03-custom-prompt.ts +46 -0
- package/examples/sdk/04-skills.ts +43 -0
- package/examples/sdk/06-extensions.ts +82 -0
- package/examples/sdk/06-hooks.ts +61 -0
- package/examples/sdk/07-context-files.ts +35 -0
- package/examples/sdk/08-prompt-templates.ts +41 -0
- package/examples/sdk/08-slash-commands.ts +46 -0
- package/examples/sdk/09-api-keys-and-oauth.ts +54 -0
- package/examples/sdk/11-sessions.ts +47 -0
- package/examples/sdk/12-redis-sessions.ts +54 -0
- package/examples/sdk/13-sql-sessions.ts +61 -0
- package/examples/sdk/README.md +169 -0
- package/package.json +587 -0
- package/scripts/bench-guard.ts +71 -0
- package/scripts/bench-title-models.ts +332 -0
- package/scripts/build-binary.ts +117 -0
- package/scripts/bundle-dist.ts +123 -0
- package/scripts/compile-binary.ts +69 -0
- package/scripts/embed-mupdf-wasm.ts +67 -0
- package/scripts/format-prompts.ts +68 -0
- package/scripts/generate-aria-snapshot.ts +134 -0
- package/scripts/generate-docs-index.ts +58 -0
- package/scripts/generate-share-viewer.ts +34 -0
- package/scripts/legacy-pi-virtual-module.ts +205 -0
- package/scripts/measure-prompt-tokens.ts +63 -0
- package/scripts/omp +51 -0
- package/scripts/omp.ts +19 -0
- package/scripts/security-compare.ts +40 -0
- package/src/advisor/advise-tool.ts +234 -0
- package/src/advisor/config.ts +341 -0
- package/src/advisor/emission-guard.ts +172 -0
- package/src/advisor/index.ts +6 -0
- package/src/advisor/runtime.ts +1412 -0
- package/src/advisor/transcript-recorder.ts +215 -0
- package/src/advisor/watchdog.ts +135 -0
- package/src/async/index.ts +1 -0
- package/src/async/job-manager.ts +847 -0
- package/src/auto-thinking/classifier.ts +220 -0
- package/src/autolearn/controller.ts +152 -0
- package/src/autolearn/managed-skills.ts +255 -0
- package/src/autoresearch/command-resume.md +14 -0
- package/src/autoresearch/dashboard.ts +436 -0
- package/src/autoresearch/git.ts +331 -0
- package/src/autoresearch/helpers.ts +218 -0
- package/src/autoresearch/index.ts +541 -0
- package/src/autoresearch/prompt-setup.md +43 -0
- package/src/autoresearch/prompt.md +103 -0
- package/src/autoresearch/resume-message.md +10 -0
- package/src/autoresearch/state.ts +273 -0
- package/src/autoresearch/storage.ts +700 -0
- package/src/autoresearch/tools/init-experiment.ts +268 -0
- package/src/autoresearch/tools/log-experiment.ts +520 -0
- package/src/autoresearch/tools/run-experiment.ts +407 -0
- package/src/autoresearch/tools/update-notes.ts +109 -0
- package/src/autoresearch/types.ts +168 -0
- package/src/capability/context-file.ts +44 -0
- package/src/capability/extension-module.ts +34 -0
- package/src/capability/extension.ts +47 -0
- package/src/capability/fs.ts +117 -0
- package/src/capability/hook.ts +40 -0
- package/src/capability/index.ts +467 -0
- package/src/capability/instruction.ts +37 -0
- package/src/capability/mcp.ts +115 -0
- package/src/capability/prompt.ts +35 -0
- package/src/capability/rule-buckets.ts +66 -0
- package/src/capability/rule.ts +298 -0
- package/src/capability/settings.ts +34 -0
- package/src/capability/skill.ts +69 -0
- package/src/capability/slash-command.ts +40 -0
- package/src/capability/ssh.ts +41 -0
- package/src/capability/system-prompt.ts +34 -0
- package/src/capability/tool.ts +38 -0
- package/src/capability/types.ts +187 -0
- package/src/cleanse/agent.ts +226 -0
- package/src/cleanse/balance.ts +79 -0
- package/src/cleanse/checkers.ts +996 -0
- package/src/cleanse/index.ts +190 -0
- package/src/cleanse/loop.ts +51 -0
- package/src/cleanse/parsers.ts +726 -0
- package/src/cleanse/progress.ts +50 -0
- package/src/cleanse/prompts/assignment.md +47 -0
- package/src/cleanse/types.ts +72 -0
- package/src/cli/agents-cli.ts +138 -0
- package/src/cli/args.ts +368 -0
- package/src/cli/auth-broker-cli.ts +940 -0
- package/src/cli/auth-gateway-cli.ts +674 -0
- package/src/cli/bench-cli.ts +990 -0
- package/src/cli/browser-relay-cli.ts +119 -0
- package/src/cli/classify-install-target.ts +76 -0
- package/src/cli/claude-trace-cli.ts +795 -0
- package/src/cli/command-help.ts +107 -0
- package/src/cli/commands/init-xdg.ts +27 -0
- package/src/cli/completion-gen.ts +550 -0
- package/src/cli/config-cli.ts +459 -0
- package/src/cli/dry-balance-cli.ts +864 -0
- package/src/cli/extension-flags.ts +48 -0
- package/src/cli/file-processor.ts +132 -0
- package/src/cli/flag-tables.ts +367 -0
- package/src/cli/gallery-cli.ts +272 -0
- package/src/cli/gallery-fixtures/agentic.ts +420 -0
- package/src/cli/gallery-fixtures/codeintel.ts +187 -0
- package/src/cli/gallery-fixtures/edit.ts +254 -0
- package/src/cli/gallery-fixtures/fs.ts +245 -0
- package/src/cli/gallery-fixtures/index.ts +40 -0
- package/src/cli/gallery-fixtures/interaction.ts +46 -0
- package/src/cli/gallery-fixtures/memory.ts +81 -0
- package/src/cli/gallery-fixtures/misc.ts +177 -0
- package/src/cli/gallery-fixtures/search.ts +135 -0
- package/src/cli/gallery-fixtures/shell.ts +241 -0
- package/src/cli/gallery-fixtures/types.ts +57 -0
- package/src/cli/gallery-fixtures/web.ts +158 -0
- package/src/cli/gallery-screenshot.ts +279 -0
- package/src/cli/gc-cli.ts +1566 -0
- package/src/cli/grep-cli.ts +161 -0
- package/src/cli/grievances-cli.ts +256 -0
- package/src/cli/help-extra.ts +89 -0
- package/src/cli/initial-message.ts +58 -0
- package/src/cli/models-cli.ts +385 -0
- package/src/cli/plugin-cli.ts +996 -0
- package/src/cli/profile-alias.ts +369 -0
- package/src/cli/profile-bootstrap.ts +233 -0
- package/src/cli/read-cli.ts +99 -0
- package/src/cli/session-picker.ts +110 -0
- package/src/cli/setup-cli.ts +312 -0
- package/src/cli/setup-model-picker.ts +43 -0
- package/src/cli/shell-cli.ts +176 -0
- package/src/cli/ssh-cli.ts +179 -0
- package/src/cli/startup-cwd.ts +58 -0
- package/src/cli/stats-cli.ts +229 -0
- package/src/cli/thinking-levels.ts +7 -0
- package/src/cli/tiny-models-cli.ts +153 -0
- package/src/cli/ttsr-cli.ts +1013 -0
- package/src/cli/update-cli.ts +1184 -0
- package/src/cli/usage-cli.ts +1084 -0
- package/src/cli/usage-error.ts +7 -0
- package/src/cli/web-search-cli.ts +144 -0
- package/src/cli/worktree-cli.ts +311 -0
- package/src/cli-commands.ts +308 -0
- package/src/cli.ts +428 -0
- package/src/collab/crypto.ts +63 -0
- package/src/collab/display-name.ts +13 -0
- package/src/collab/guest.ts +764 -0
- package/src/collab/host.ts +692 -0
- package/src/collab/protocol.ts +296 -0
- package/src/collab/relay-client.ts +282 -0
- package/src/collab/replication-shrink.ts +111 -0
- package/src/commands/acp.ts +35 -0
- package/src/commands/agents.ts +58 -0
- package/src/commands/auth-broker.ts +100 -0
- package/src/commands/auth-gateway.ts +70 -0
- package/src/commands/bench.ts +64 -0
- package/src/commands/browser-relay.ts +53 -0
- package/src/commands/cleanse.ts +45 -0
- package/src/commands/commit.ts +47 -0
- package/src/commands/complete.ts +67 -0
- package/src/commands/completions.ts +61 -0
- package/src/commands/config.ts +52 -0
- package/src/commands/dry-balance.ts +43 -0
- package/src/commands/gallery.ts +61 -0
- package/src/commands/gc.ts +47 -0
- package/src/commands/grep.ts +49 -0
- package/src/commands/grievances.ts +52 -0
- package/src/commands/install.ts +107 -0
- package/src/commands/join.ts +40 -0
- package/src/commands/launch-help.ts +116 -0
- package/src/commands/launch.ts +34 -0
- package/src/commands/models.ts +61 -0
- package/src/commands/plugin.ts +79 -0
- package/src/commands/read.ts +39 -0
- package/src/commands/say.ts +146 -0
- package/src/commands/setup.ts +68 -0
- package/src/commands/share.ts +71 -0
- package/src/commands/shell.ts +30 -0
- package/src/commands/ssh.ts +61 -0
- package/src/commands/stats.ts +30 -0
- package/src/commands/tiny-models.ts +36 -0
- package/src/commands/token.ts +164 -0
- package/src/commands/ttsr.ts +125 -0
- package/src/commands/update.ts +34 -0
- package/src/commands/usage.ts +55 -0
- package/src/commands/web-search.ts +43 -0
- package/src/commands/worktree.ts +63 -0
- package/src/commit/agentic/agent.ts +322 -0
- package/src/commit/agentic/fallback.ts +96 -0
- package/src/commit/agentic/index.ts +383 -0
- package/src/commit/agentic/lock-files.ts +107 -0
- package/src/commit/agentic/prompts/analyze-file.md +22 -0
- package/src/commit/agentic/prompts/session-user.md +25 -0
- package/src/commit/agentic/prompts/split-confirm.md +1 -0
- package/src/commit/agentic/prompts/system.md +38 -0
- package/src/commit/agentic/state.ts +60 -0
- package/src/commit/agentic/tools/analyze-file.ts +148 -0
- package/src/commit/agentic/tools/git-file-diff.ts +191 -0
- package/src/commit/agentic/tools/git-hunk.ts +52 -0
- package/src/commit/agentic/tools/git-overview.ts +62 -0
- package/src/commit/agentic/tools/index.ts +54 -0
- package/src/commit/agentic/tools/propose-changelog.ts +147 -0
- package/src/commit/agentic/tools/propose-commit.ts +109 -0
- package/src/commit/agentic/tools/recent-commits.ts +81 -0
- package/src/commit/agentic/tools/schemas.ts +11 -0
- package/src/commit/agentic/tools/split-commit.ts +241 -0
- package/src/commit/agentic/topo-sort.ts +44 -0
- package/src/commit/agentic/trivial.ts +51 -0
- package/src/commit/agentic/validation.ts +183 -0
- package/src/commit/analysis/conventional.ts +64 -0
- package/src/commit/analysis/index.ts +4 -0
- package/src/commit/analysis/scope.ts +242 -0
- package/src/commit/analysis/summary.ts +107 -0
- package/src/commit/analysis/validation.ts +66 -0
- package/src/commit/changelog/detect.ts +40 -0
- package/src/commit/changelog/generate.ts +101 -0
- package/src/commit/changelog/index.ts +234 -0
- package/src/commit/changelog/parse.ts +44 -0
- package/src/commit/cli.ts +85 -0
- package/src/commit/git/diff.ts +148 -0
- package/src/commit/index.ts +5 -0
- package/src/commit/map-reduce/index.ts +69 -0
- package/src/commit/map-reduce/map-phase.ts +193 -0
- package/src/commit/map-reduce/reduce-phase.ts +49 -0
- package/src/commit/map-reduce/utils.ts +9 -0
- package/src/commit/message.ts +11 -0
- package/src/commit/model-selection.ts +95 -0
- package/src/commit/pipeline.ts +244 -0
- package/src/commit/prompts/analysis-system.md +148 -0
- package/src/commit/prompts/analysis-user.md +38 -0
- package/src/commit/prompts/changelog-system.md +50 -0
- package/src/commit/prompts/changelog-user.md +18 -0
- package/src/commit/prompts/file-observer-system.md +24 -0
- package/src/commit/prompts/file-observer-user.md +8 -0
- package/src/commit/prompts/reduce-system.md +50 -0
- package/src/commit/prompts/reduce-user.md +17 -0
- package/src/commit/prompts/summary-retry.md +3 -0
- package/src/commit/prompts/summary-system.md +38 -0
- package/src/commit/prompts/summary-user.md +13 -0
- package/src/commit/prompts/types-description.md +2 -0
- package/src/commit/shared-llm.ts +70 -0
- package/src/commit/types.ts +118 -0
- package/src/commit/utils/exclusions.ts +42 -0
- package/src/commit/utils.ts +58 -0
- package/src/config/api-key-resolver.ts +81 -0
- package/src/config/append-only-context-mode.ts +76 -0
- package/src/config/config-file.ts +347 -0
- package/src/config/inline-tool-descriptors-mode.ts +26 -0
- package/src/config/keybindings.ts +703 -0
- package/src/config/mcp-schema.json +252 -0
- package/src/config/model-discovery.ts +1077 -0
- package/src/config/model-registry.ts +2822 -0
- package/src/config/model-resolver.ts +2115 -0
- package/src/config/model-roles.ts +113 -0
- package/src/config/models-config-schema-bundle.ts +315 -0
- package/src/config/models-config-schema.ts +14 -0
- package/src/config/models-config.ts +130 -0
- package/src/config/prompt-templates.ts +205 -0
- package/src/config/provider-globals.ts +25 -0
- package/src/config/resolve-config-value.ts +95 -0
- package/src/config/service-tier.ts +146 -0
- package/src/config/settings-schema.ts +5887 -0
- package/src/config/settings.ts +2394 -0
- package/src/config.ts +242 -0
- package/src/cursor-bridge-tools.ts +81 -0
- package/src/cursor.ts +960 -0
- package/src/dap/client.ts +1043 -0
- package/src/dap/config.ts +480 -0
- package/src/dap/defaults.json +212 -0
- package/src/dap/index.ts +4 -0
- package/src/dap/session.ts +1841 -0
- package/src/dap/types.ts +611 -0
- package/src/debug/index.ts +584 -0
- package/src/debug/log-formatting.ts +58 -0
- package/src/debug/log-viewer.ts +966 -0
- package/src/debug/profiler.ts +168 -0
- package/src/debug/protocol-probe.ts +267 -0
- package/src/debug/raw-sse-buffer.ts +421 -0
- package/src/debug/raw-sse.ts +312 -0
- package/src/debug/remote-debugger.ts +151 -0
- package/src/debug/report-bundle.ts +411 -0
- package/src/debug/system-info.ts +111 -0
- package/src/debug/terminal-info.ts +124 -0
- package/src/discovery/agent-plugin-format.ts +551 -0
- package/src/discovery/agent-plugins.ts +341 -0
- package/src/discovery/agents-md.ts +67 -0
- package/src/discovery/agents.ts +300 -0
- package/src/discovery/at-imports.ts +273 -0
- package/src/discovery/builtin-defaults.ts +39 -0
- package/src/discovery/builtin-rules/go-add-cleanup.md +33 -0
- package/src/discovery/builtin-rules/go-bench-loop.md +36 -0
- package/src/discovery/builtin-rules/go-exp-promoted.md +40 -0
- package/src/discovery/builtin-rules/go-ioutil.md +37 -0
- package/src/discovery/builtin-rules/go-join-hostport.md +30 -0
- package/src/discovery/builtin-rules/go-new-expr.md +44 -0
- package/src/discovery/builtin-rules/go-rand-v2.md +41 -0
- package/src/discovery/builtin-rules/go-range-int.md +45 -0
- package/src/discovery/builtin-rules/index.ts +74 -0
- package/src/discovery/builtin-rules/rs-box-leak.md +49 -0
- package/src/discovery/builtin-rules/rs-future-prelude.md +24 -0
- package/src/discovery/builtin-rules/rs-lazylock.md +52 -0
- package/src/discovery/builtin-rules/rs-match-ergonomics.md +68 -0
- package/src/discovery/builtin-rules/rs-parking-lot.md +45 -0
- package/src/discovery/builtin-rules/rs-result-type.md +20 -0
- package/src/discovery/builtin-rules/ts-bare-catch.md +39 -0
- package/src/discovery/builtin-rules/ts-import-type.md +43 -0
- package/src/discovery/builtin-rules/ts-no-any.md +66 -0
- package/src/discovery/builtin-rules/ts-no-deprecated-leftovers.md +45 -0
- package/src/discovery/builtin-rules/ts-no-dynamic-import.md +40 -0
- package/src/discovery/builtin-rules/ts-no-inline-cast-access.md +56 -0
- package/src/discovery/builtin-rules/ts-no-local-is-record.md +48 -0
- package/src/discovery/builtin-rules/ts-no-return-type.md +45 -0
- package/src/discovery/builtin-rules/ts-no-test-timers.md +55 -0
- package/src/discovery/builtin-rules/ts-no-tiny-functions.md +51 -0
- package/src/discovery/builtin-rules/ts-promise-with-resolvers.md +66 -0
- package/src/discovery/builtin-rules/ts-redundant-clear-guard.md +75 -0
- package/src/discovery/builtin-rules/ts-set-map.md +28 -0
- package/src/discovery/builtin.ts +945 -0
- package/src/discovery/claude-plugins.ts +640 -0
- package/src/discovery/claude.ts +591 -0
- package/src/discovery/cline.ts +83 -0
- package/src/discovery/codex.ts +553 -0
- package/src/discovery/contained-path.ts +78 -0
- package/src/discovery/cursor.ts +223 -0
- package/src/discovery/gemini.ts +386 -0
- package/src/discovery/github.ts +337 -0
- package/src/discovery/helpers.ts +1183 -0
- package/src/discovery/index.ts +82 -0
- package/src/discovery/mcp-json.ts +182 -0
- package/src/discovery/omp-extension-roots.ts +272 -0
- package/src/discovery/omp-plugins.ts +409 -0
- package/src/discovery/opencode.ts +441 -0
- package/src/discovery/plugin-dir-roots.ts +28 -0
- package/src/discovery/ssh.ts +153 -0
- package/src/discovery/substitute-plugin-root.ts +77 -0
- package/src/discovery/vscode.ts +106 -0
- package/src/discovery/windsurf.ts +149 -0
- package/src/edit/apply-patch/index.ts +87 -0
- package/src/edit/apply-patch/parser.ts +174 -0
- package/src/edit/diff.ts +1008 -0
- package/src/edit/edit-clipboard.ts +23 -0
- package/src/edit/file-snapshot-store.ts +148 -0
- package/src/edit/hashline/block-resolver.ts +33 -0
- package/src/edit/hashline/diff.ts +402 -0
- package/src/edit/hashline/execute.ts +313 -0
- package/src/edit/hashline/filesystem.ts +247 -0
- package/src/edit/hashline/index.ts +5 -0
- package/src/edit/hashline/noop-loop-guard.ts +99 -0
- package/src/edit/hashline/params.ts +12 -0
- package/src/edit/index.ts +699 -0
- package/src/edit/modes/apply-patch.lark +19 -0
- package/src/edit/modes/apply-patch.ts +53 -0
- package/src/edit/modes/patch.ts +1958 -0
- package/src/edit/modes/replace.ts +1191 -0
- package/src/edit/normalize.ts +345 -0
- package/src/edit/notebook.ts +242 -0
- package/src/edit/read-file.ts +25 -0
- package/src/edit/renderer.ts +998 -0
- package/src/edit/snapshot-details.ts +77 -0
- package/src/edit/streaming.ts +710 -0
- package/src/eval/agent-bridge.ts +224 -0
- package/src/eval/backend-helpers.ts +48 -0
- package/src/eval/backend.ts +71 -0
- package/src/eval/bridge-timeout.ts +65 -0
- package/src/eval/budget-bridge.ts +48 -0
- package/src/eval/completion-bridge.ts +212 -0
- package/src/eval/concurrency-bridge.ts +34 -0
- package/src/eval/executor-base.ts +562 -0
- package/src/eval/idle-timeout.ts +91 -0
- package/src/eval/index.ts +6 -0
- package/src/eval/jl/executor.ts +551 -0
- package/src/eval/jl/index.ts +54 -0
- package/src/eval/jl/kernel.ts +236 -0
- package/src/eval/jl/prelude.jl +736 -0
- package/src/eval/jl/prelude.ts +3 -0
- package/src/eval/jl/runner.jl +666 -0
- package/src/eval/jl/runtime.ts +118 -0
- package/src/eval/js/context-manager.ts +872 -0
- package/src/eval/js/executor.ts +178 -0
- package/src/eval/js/index.ts +41 -0
- package/src/eval/js/process-entry.ts +31 -0
- package/src/eval/js/shared/helpers.ts +170 -0
- package/src/eval/js/shared/indirect-eval.ts +30 -0
- package/src/eval/js/shared/local-module-loader.ts +364 -0
- package/src/eval/js/shared/prelude.ts +2 -0
- package/src/eval/js/shared/prelude.txt +294 -0
- package/src/eval/js/shared/rewrite-imports.ts +550 -0
- package/src/eval/js/shared/runtime.ts +590 -0
- package/src/eval/js/shared/types.ts +18 -0
- package/src/eval/js/tool-bridge.ts +163 -0
- package/src/eval/js/worker-core.ts +380 -0
- package/src/eval/js/worker-entry.ts +37 -0
- package/src/eval/js/worker-protocol.ts +47 -0
- package/src/eval/kernel-base.ts +569 -0
- package/src/eval/py/display.ts +71 -0
- package/src/eval/py/executor.ts +643 -0
- package/src/eval/py/index.ts +57 -0
- package/src/eval/py/kernel.ts +235 -0
- package/src/eval/py/prelude.py +673 -0
- package/src/eval/py/prelude.ts +3 -0
- package/src/eval/py/runner.py +1425 -0
- package/src/eval/py/runtime.ts +276 -0
- package/src/eval/py/spawn-options.ts +134 -0
- package/src/eval/py/tool-bridge.ts +201 -0
- package/src/eval/rb/executor.ts +511 -0
- package/src/eval/rb/index.ts +54 -0
- package/src/eval/rb/kernel.ts +231 -0
- package/src/eval/rb/prelude.rb +551 -0
- package/src/eval/rb/prelude.ts +3 -0
- package/src/eval/rb/runner.rb +581 -0
- package/src/eval/rb/runtime.ts +132 -0
- package/src/eval/runtime-env.ts +104 -0
- package/src/eval/session-id.ts +8 -0
- package/src/eval/types.ts +48 -0
- package/src/exa/index.ts +2 -0
- package/src/exa/mcp-client.ts +370 -0
- package/src/exa/types.ts +69 -0
- package/src/exec/bash-executor.ts +627 -0
- package/src/exec/direnv.ts +145 -0
- package/src/exec/exec.ts +53 -0
- package/src/exec/non-interactive-env.ts +118 -0
- package/src/export/custom-share.ts +65 -0
- package/src/export/html/args.ts +20 -0
- package/src/export/html/index.ts +320 -0
- package/src/export/html/share-loader.js +102 -0
- package/src/export/html/template.css +1355 -0
- package/src/export/html/template.html +55 -0
- package/src/export/html/template.js +1653 -0
- package/src/export/html/tool-views.generated.js +35 -0
- package/src/export/html/vendor/highlight.min.js +1213 -0
- package/src/export/html/vendor/marked.min.js +6 -0
- package/src/export/html/web-palette.ts +126 -0
- package/src/export/share.ts +686 -0
- package/src/export/ttsr.ts +590 -0
- package/src/extensibility/custom-commands/bundled/ci-green/index.ts +54 -0
- package/src/extensibility/custom-commands/bundled/review/index.ts +698 -0
- package/src/extensibility/custom-commands/index.ts +2 -0
- package/src/extensibility/custom-commands/loader.ts +242 -0
- package/src/extensibility/custom-commands/types.ts +119 -0
- package/src/extensibility/custom-tools/index.ts +7 -0
- package/src/extensibility/custom-tools/loader.ts +301 -0
- package/src/extensibility/custom-tools/types.ts +287 -0
- package/src/extensibility/custom-tools/wrapper.ts +50 -0
- package/src/extensibility/extensions/compact-handler.ts +40 -0
- package/src/extensibility/extensions/get-commands-handler.ts +78 -0
- package/src/extensibility/extensions/index.ts +16 -0
- package/src/extensibility/extensions/load-errors.ts +13 -0
- package/src/extensibility/extensions/loader.ts +663 -0
- package/src/extensibility/extensions/managed-timers.ts +83 -0
- package/src/extensibility/extensions/model-api.ts +39 -0
- package/src/extensibility/extensions/runner.ts +1396 -0
- package/src/extensibility/extensions/types.ts +1603 -0
- package/src/extensibility/extensions/wrapper.ts +395 -0
- package/src/extensibility/hooks/index.ts +6 -0
- package/src/extensibility/hooks/loader.ts +243 -0
- package/src/extensibility/hooks/runner.ts +425 -0
- package/src/extensibility/hooks/tool-wrapper.ts +124 -0
- package/src/extensibility/hooks/types.ts +612 -0
- package/src/extensibility/legacy-pi-ai-shim.ts +161 -0
- package/src/extensibility/legacy-pi-coding-agent-shim.ts +1460 -0
- package/src/extensibility/legacy-pi-tui-shim.ts +43 -0
- package/src/extensibility/legacy-typebox.ts +101 -0
- package/src/extensibility/plugins/bun-git-cache.ts +91 -0
- package/src/extensibility/plugins/doctor.ts +65 -0
- package/src/extensibility/plugins/git-url.ts +367 -0
- package/src/extensibility/plugins/index.ts +9 -0
- package/src/extensibility/plugins/installer.ts +201 -0
- package/src/extensibility/plugins/legacy-pi-compat.ts +2643 -0
- package/src/extensibility/plugins/legacy-pi-virtual-modules.d.ts +4 -0
- package/src/extensibility/plugins/loader.ts +535 -0
- package/src/extensibility/plugins/manager.ts +1142 -0
- package/src/extensibility/plugins/marketplace/cache.ts +136 -0
- package/src/extensibility/plugins/marketplace/fetcher.ts +316 -0
- package/src/extensibility/plugins/marketplace/index.ts +6 -0
- package/src/extensibility/plugins/marketplace/manager.ts +927 -0
- package/src/extensibility/plugins/marketplace/registry.ts +192 -0
- package/src/extensibility/plugins/marketplace/source-resolver.ts +147 -0
- package/src/extensibility/plugins/marketplace/types.ts +192 -0
- package/src/extensibility/plugins/marketplace-auto-update.ts +49 -0
- package/src/extensibility/plugins/parser.ts +107 -0
- package/src/extensibility/plugins/runtime-config.ts +9 -0
- package/src/extensibility/plugins/types.ts +194 -0
- package/src/extensibility/session-handler-types.ts +21 -0
- package/src/extensibility/shared-events.ts +401 -0
- package/src/extensibility/skills.ts +531 -0
- package/src/extensibility/slash-commands.ts +131 -0
- package/src/extensibility/tool-event-input.ts +80 -0
- package/src/extensibility/tool-proxy.ts +28 -0
- package/src/extensibility/utils.ts +192 -0
- package/src/goals/index.ts +3 -0
- package/src/goals/runtime.ts +521 -0
- package/src/goals/state.ts +37 -0
- package/src/goals/tools/goal-tool.ts +251 -0
- package/src/hindsight/backend.ts +354 -0
- package/src/hindsight/bank.ts +156 -0
- package/src/hindsight/client.ts +680 -0
- package/src/hindsight/config.ts +193 -0
- package/src/hindsight/content.ts +266 -0
- package/src/hindsight/index.ts +8 -0
- package/src/hindsight/mental-models.ts +429 -0
- package/src/hindsight/seeds.json +32 -0
- package/src/hindsight/state.ts +530 -0
- package/src/hindsight/transcript.ts +71 -0
- package/src/index.ts +66 -0
- package/src/internal-urls/agent-protocol.ts +180 -0
- package/src/internal-urls/artifact-protocol.ts +151 -0
- package/src/internal-urls/docs-index.ts +102 -0
- package/src/internal-urls/filesystem-resource.ts +34 -0
- package/src/internal-urls/history-protocol.ts +198 -0
- package/src/internal-urls/index.ts +28 -0
- package/src/internal-urls/issue-pr-protocol.ts +594 -0
- package/src/internal-urls/json-query.ts +126 -0
- package/src/internal-urls/local-protocol.ts +471 -0
- package/src/internal-urls/mcp-protocol.ts +168 -0
- package/src/internal-urls/memory-protocol.ts +380 -0
- package/src/internal-urls/omp-protocol.ts +94 -0
- package/src/internal-urls/parse.ts +103 -0
- package/src/internal-urls/registry-helpers.ts +132 -0
- package/src/internal-urls/router.ts +153 -0
- package/src/internal-urls/rule-protocol.ts +45 -0
- package/src/internal-urls/security-protocol.ts +261 -0
- package/src/internal-urls/skill-protocol.ts +131 -0
- package/src/internal-urls/ssh-protocol.ts +368 -0
- package/src/internal-urls/types.ts +196 -0
- package/src/internal-urls/vault-protocol.ts +940 -0
- package/src/internal-urls/xd-protocol.ts +46 -0
- package/src/irc/bus.ts +380 -0
- package/src/jsonrpc/message-framing.ts +142 -0
- package/src/launch/broker.ts +1368 -0
- package/src/launch/client.ts +521 -0
- package/src/launch/ensure.ts +73 -0
- package/src/launch/paths.ts +14 -0
- package/src/launch/presence.ts +82 -0
- package/src/launch/protocol.ts +448 -0
- package/src/launch/spawn-options.ts +17 -0
- package/src/launch/terminal-output-worker-client.ts +53 -0
- package/src/launch/terminal-output-worker-protocol.ts +11 -0
- package/src/launch/terminal-output-worker.ts +23 -0
- package/src/launch/terminal-output.ts +46 -0
- package/src/lib/xai-http.ts +150 -0
- package/src/live/attestation.ts +91 -0
- package/src/live/controller.ts +517 -0
- package/src/live/prompts/agent-final-message.md +3 -0
- package/src/live/prompts/live-instructions.md +23 -0
- package/src/live/protocol.ts +233 -0
- package/src/live/transport.ts +422 -0
- package/src/live/visualizer.ts +221 -0
- package/src/live/voices.ts +18 -0
- package/src/lsp/client.ts +1465 -0
- package/src/lsp/clients/biome-client.ts +263 -0
- package/src/lsp/clients/index.ts +50 -0
- package/src/lsp/clients/lsp-linter-client.ts +85 -0
- package/src/lsp/clients/swiftlint-client.ts +120 -0
- package/src/lsp/config.ts +549 -0
- package/src/lsp/defaults.json +499 -0
- package/src/lsp/deferred-diagnostics.ts +66 -0
- package/src/lsp/diagnostics-ledger.ts +51 -0
- package/src/lsp/edits.ts +288 -0
- package/src/lsp/format-options.ts +119 -0
- package/src/lsp/index.ts +2821 -0
- package/src/lsp/lspmux.ts +233 -0
- package/src/lsp/mux/daemon.ts +348 -0
- package/src/lsp/mux/protocol.ts +96 -0
- package/src/lsp/mux/server.ts +797 -0
- package/src/lsp/render.ts +668 -0
- package/src/lsp/startup-events.ts +13 -0
- package/src/lsp/types.ts +479 -0
- package/src/lsp/utils.ts +747 -0
- package/src/main.ts +1799 -0
- package/src/markit/NOTICE +32 -0
- package/src/markit/converters/docx.ts +56 -0
- package/src/markit/converters/epub.ts +136 -0
- package/src/markit/converters/pdf/columns.ts +103 -0
- package/src/markit/converters/pdf/extract.ts +598 -0
- package/src/markit/converters/pdf/grid.ts +780 -0
- package/src/markit/converters/pdf/headers.ts +106 -0
- package/src/markit/converters/pdf/index.ts +146 -0
- package/src/markit/converters/pdf/render.ts +501 -0
- package/src/markit/converters/pdf/types.ts +84 -0
- package/src/markit/converters/pptx.ts +325 -0
- package/src/markit/converters/xlsx.ts +173 -0
- package/src/markit/index.ts +2 -0
- package/src/markit/registry.ts +59 -0
- package/src/markit/types.ts +35 -0
- package/src/mcp/client.ts +511 -0
- package/src/mcp/config-writer.ts +377 -0
- package/src/mcp/config.ts +385 -0
- package/src/mcp/index.ts +29 -0
- package/src/mcp/json-rpc.ts +122 -0
- package/src/mcp/loader.ts +125 -0
- package/src/mcp/manager.ts +1524 -0
- package/src/mcp/oauth-credentials.ts +104 -0
- package/src/mcp/oauth-discovery.ts +587 -0
- package/src/mcp/oauth-flow.ts +830 -0
- package/src/mcp/render.ts +214 -0
- package/src/mcp/request-id.ts +24 -0
- package/src/mcp/smithery-auth.ts +108 -0
- package/src/mcp/smithery-connect.ts +154 -0
- package/src/mcp/smithery-registry.ts +500 -0
- package/src/mcp/startup-events.ts +116 -0
- package/src/mcp/timeout.ts +59 -0
- package/src/mcp/tool-bridge.ts +691 -0
- package/src/mcp/tool-cache.ts +117 -0
- package/src/mcp/transports/header-policy.ts +95 -0
- package/src/mcp/transports/http.ts +508 -0
- package/src/mcp/transports/index.ts +7 -0
- package/src/mcp/transports/sse.ts +372 -0
- package/src/mcp/transports/stdio.ts +905 -0
- package/src/mcp/types.ts +467 -0
- package/src/memories/index.ts +1434 -0
- package/src/memories/storage.ts +578 -0
- package/src/memory-backend/index.ts +19 -0
- package/src/memory-backend/local-backend.ts +47 -0
- package/src/memory-backend/messages.ts +19 -0
- package/src/memory-backend/off-backend.ts +25 -0
- package/src/memory-backend/resolve.ts +25 -0
- package/src/memory-backend/runtime.ts +66 -0
- package/src/memory-backend/tool-names.ts +2 -0
- package/src/memory-backend/types.ts +166 -0
- package/src/mnemopi/backend.ts +629 -0
- package/src/mnemopi/config.ts +267 -0
- package/src/mnemopi/embed-client.ts +293 -0
- package/src/mnemopi/embed-protocol.ts +35 -0
- package/src/mnemopi/embed-worker.ts +114 -0
- package/src/mnemopi/index.ts +3 -0
- package/src/mnemopi/state.ts +940 -0
- package/src/modes/acp/acp-agent.ts +2595 -0
- package/src/modes/acp/acp-client-bridge.ts +154 -0
- package/src/modes/acp/acp-event-mapper.ts +1084 -0
- package/src/modes/acp/acp-mode.ts +48 -0
- package/src/modes/acp/index.ts +2 -0
- package/src/modes/acp/terminal-auth.ts +37 -0
- package/src/modes/components/advisor-config.ts +635 -0
- package/src/modes/components/advisor-message.ts +109 -0
- package/src/modes/components/agent-dashboard.ts +1252 -0
- package/src/modes/components/agent-hub-projection.ts +248 -0
- package/src/modes/components/agent-hub-renderer.ts +194 -0
- package/src/modes/components/agent-hub.ts +1126 -0
- package/src/modes/components/agent-transcript-viewer.ts +647 -0
- package/src/modes/components/ask-dialog.ts +1017 -0
- package/src/modes/components/assistant-message.ts +978 -0
- package/src/modes/components/background-tan-message.ts +36 -0
- package/src/modes/components/bash-execution.ts +233 -0
- package/src/modes/components/bordered-loader.ts +41 -0
- package/src/modes/components/btw-panel.ts +161 -0
- package/src/modes/components/cache-invalidation-marker.ts +110 -0
- package/src/modes/components/chat-block.ts +111 -0
- package/src/modes/components/chat-transcript-builder.ts +518 -0
- package/src/modes/components/codex-reset-fireworks.ts +369 -0
- package/src/modes/components/collab-prompt-message.ts +32 -0
- package/src/modes/components/compaction-summary-message.ts +221 -0
- package/src/modes/components/copy-selector.ts +218 -0
- package/src/modes/components/countdown-timer.ts +75 -0
- package/src/modes/components/custom-editor.ts +1036 -0
- package/src/modes/components/custom-message.ts +70 -0
- package/src/modes/components/diff.ts +254 -0
- package/src/modes/components/dynamic-border.ts +37 -0
- package/src/modes/components/error-banner.ts +33 -0
- package/src/modes/components/eval-execution.ts +169 -0
- package/src/modes/components/execution-shared.ts +101 -0
- package/src/modes/components/extensions/extension-dashboard.ts +492 -0
- package/src/modes/components/extensions/extension-list.ts +507 -0
- package/src/modes/components/extensions/index.ts +9 -0
- package/src/modes/components/extensions/inspector-panel.ts +326 -0
- package/src/modes/components/extensions/state-manager.ts +648 -0
- package/src/modes/components/extensions/types.ts +186 -0
- package/src/modes/components/footer.ts +274 -0
- package/src/modes/components/history-search.ts +268 -0
- package/src/modes/components/hook-editor.ts +213 -0
- package/src/modes/components/hook-input.ts +87 -0
- package/src/modes/components/hook-message.ts +67 -0
- package/src/modes/components/hook-selector.ts +691 -0
- package/src/modes/components/index.ts +42 -0
- package/src/modes/components/keybinding-hints.ts +56 -0
- package/src/modes/components/late-diagnostics-message.ts +60 -0
- package/src/modes/components/login-dialog.ts +197 -0
- package/src/modes/components/logout-account-selector.ts +130 -0
- package/src/modes/components/mcp-add-wizard.ts +1413 -0
- package/src/modes/components/message-frame.ts +98 -0
- package/src/modes/components/model-browser.ts +888 -0
- package/src/modes/components/model-hub.ts +2014 -0
- package/src/modes/components/model-picker.ts +237 -0
- package/src/modes/components/move-overlay.ts +293 -0
- package/src/modes/components/oauth-selector.ts +474 -0
- package/src/modes/components/omfg-panel.ts +141 -0
- package/src/modes/components/overlay-box.ts +109 -0
- package/src/modes/components/pause-screen.ts +208 -0
- package/src/modes/components/plan-review-overlay.ts +1226 -0
- package/src/modes/components/plan-toc.ts +138 -0
- package/src/modes/components/plugin-selector.ts +100 -0
- package/src/modes/components/plugin-settings.ts +745 -0
- package/src/modes/components/queue-mode-selector.ts +61 -0
- package/src/modes/components/read-tool-group.ts +856 -0
- package/src/modes/components/reset-usage-selector.ts +161 -0
- package/src/modes/components/segment-track.ts +89 -0
- package/src/modes/components/select-list-mouse-routing.ts +35 -0
- package/src/modes/components/selector-helpers.ts +129 -0
- package/src/modes/components/session-account-selector.ts +62 -0
- package/src/modes/components/session-selector.ts +1035 -0
- package/src/modes/components/settings-defs.ts +267 -0
- package/src/modes/components/settings-selector.ts +1445 -0
- package/src/modes/components/show-images-selector.ts +50 -0
- package/src/modes/components/skill-message.ts +110 -0
- package/src/modes/components/snapcompact-shape-preview-doc.md +14 -0
- package/src/modes/components/snapcompact-shape-preview.ts +192 -0
- package/src/modes/components/status-line/component.ts +1843 -0
- package/src/modes/components/status-line/context-thresholds.ts +86 -0
- package/src/modes/components/status-line/git-utils.ts +42 -0
- package/src/modes/components/status-line/index.ts +5 -0
- package/src/modes/components/status-line/presets.ts +106 -0
- package/src/modes/components/status-line/segments.ts +710 -0
- package/src/modes/components/status-line/separators.ts +55 -0
- package/src/modes/components/status-line/types.ts +159 -0
- package/src/modes/components/stripped-tool-calls-placeholder.ts +35 -0
- package/src/modes/components/theme-selector.ts +68 -0
- package/src/modes/components/thinking-selector.ts +57 -0
- package/src/modes/components/tiny-title-download-progress.ts +90 -0
- package/src/modes/components/tips.txt +26 -0
- package/src/modes/components/todo-reminder.ts +43 -0
- package/src/modes/components/tool-execution.ts +1467 -0
- package/src/modes/components/transcript-container.ts +527 -0
- package/src/modes/components/tree-selector.ts +1006 -0
- package/src/modes/components/ttsr-notification.ts +123 -0
- package/src/modes/components/usage-row.ts +52 -0
- package/src/modes/components/user-message-selector.ts +227 -0
- package/src/modes/components/user-message.ts +167 -0
- package/src/modes/components/visual-truncate.ts +63 -0
- package/src/modes/components/welcome.ts +578 -0
- package/src/modes/controllers/btw-controller.ts +246 -0
- package/src/modes/controllers/command-controller-shared.ts +109 -0
- package/src/modes/controllers/command-controller.ts +2024 -0
- package/src/modes/controllers/event-controller.ts +2173 -0
- package/src/modes/controllers/extension-ui-controller.ts +1243 -0
- package/src/modes/controllers/input-controller.ts +2037 -0
- package/src/modes/controllers/live-command-controller.ts +261 -0
- package/src/modes/controllers/mcp-command-controller.ts +2552 -0
- package/src/modes/controllers/omfg-controller.ts +287 -0
- package/src/modes/controllers/omfg-rule.ts +647 -0
- package/src/modes/controllers/selector-controller.ts +2058 -0
- package/src/modes/controllers/session-focus-controller.ts +117 -0
- package/src/modes/controllers/ssh-command-controller.ts +385 -0
- package/src/modes/controllers/streaming-reveal.ts +399 -0
- package/src/modes/controllers/tan-command-controller.ts +243 -0
- package/src/modes/controllers/todo-command-controller.ts +487 -0
- package/src/modes/controllers/tool-args-reveal.ts +591 -0
- package/src/modes/data/emojis.json +1 -0
- package/src/modes/emoji-autocomplete.ts +285 -0
- package/src/modes/github-ref-autocomplete.ts +75 -0
- package/src/modes/gradient-highlight.ts +99 -0
- package/src/modes/image-references.ts +137 -0
- package/src/modes/index.ts +10 -0
- package/src/modes/interactive-mode.ts +5055 -0
- package/src/modes/internal-url-autocomplete.ts +158 -0
- package/src/modes/loop-limit.ts +192 -0
- package/src/modes/magic-keyword-boundary.ts +23 -0
- package/src/modes/magic-keywords.ts +42 -0
- package/src/modes/markdown-prose.ts +247 -0
- package/src/modes/oauth-manual-input.ts +69 -0
- package/src/modes/orchestrate.ts +43 -0
- package/src/modes/print-mode.ts +282 -0
- package/src/modes/prompt-action-autocomplete.ts +322 -0
- package/src/modes/queue-input.ts +132 -0
- package/src/modes/rpc/host-tools.ts +204 -0
- package/src/modes/rpc/host-uris.ts +241 -0
- package/src/modes/rpc/rpc-client.ts +1213 -0
- package/src/modes/rpc/rpc-frame.ts +316 -0
- package/src/modes/rpc/rpc-input.ts +38 -0
- package/src/modes/rpc/rpc-messages.ts +127 -0
- package/src/modes/rpc/rpc-mode.ts +1519 -0
- package/src/modes/rpc/rpc-subagents.ts +265 -0
- package/src/modes/rpc/rpc-types.ts +544 -0
- package/src/modes/running-subagent-badge.ts +13 -0
- package/src/modes/runtime-init.ts +144 -0
- package/src/modes/session-observer-registry.ts +223 -0
- package/src/modes/session-teardown.ts +82 -0
- package/src/modes/setup-version.ts +11 -0
- package/src/modes/setup-wizard/index.ts +103 -0
- package/src/modes/setup-wizard/lazy.ts +16 -0
- package/src/modes/setup-wizard/scenes/glyph.ts +103 -0
- package/src/modes/setup-wizard/scenes/model.ts +132 -0
- package/src/modes/setup-wizard/scenes/outro.ts +35 -0
- package/src/modes/setup-wizard/scenes/providers.ts +105 -0
- package/src/modes/setup-wizard/scenes/sign-in.ts +312 -0
- package/src/modes/setup-wizard/scenes/splash.ts +201 -0
- package/src/modes/setup-wizard/scenes/theme.ts +330 -0
- package/src/modes/setup-wizard/scenes/types.ts +65 -0
- package/src/modes/setup-wizard/scenes/web-search.ts +153 -0
- package/src/modes/setup-wizard/startup-splash.ts +107 -0
- package/src/modes/setup-wizard/wizard-overlay.ts +335 -0
- package/src/modes/shared.ts +49 -0
- package/src/modes/skill-command.ts +91 -0
- package/src/modes/theme/dark.json +95 -0
- package/src/modes/theme/defaults/alabaster.json +93 -0
- package/src/modes/theme/defaults/amethyst.json +96 -0
- package/src/modes/theme/defaults/anthracite.json +93 -0
- package/src/modes/theme/defaults/basalt.json +91 -0
- package/src/modes/theme/defaults/birch.json +95 -0
- package/src/modes/theme/defaults/dark-abyss.json +91 -0
- package/src/modes/theme/defaults/dark-arctic.json +104 -0
- package/src/modes/theme/defaults/dark-aurora.json +95 -0
- package/src/modes/theme/defaults/dark-catppuccin.json +107 -0
- package/src/modes/theme/defaults/dark-cavern.json +91 -0
- package/src/modes/theme/defaults/dark-copper.json +95 -0
- package/src/modes/theme/defaults/dark-cosmos.json +90 -0
- package/src/modes/theme/defaults/dark-cyberpunk.json +102 -0
- package/src/modes/theme/defaults/dark-dracula.json +98 -0
- package/src/modes/theme/defaults/dark-eclipse.json +91 -0
- package/src/modes/theme/defaults/dark-ember.json +95 -0
- package/src/modes/theme/defaults/dark-equinox.json +90 -0
- package/src/modes/theme/defaults/dark-forest.json +96 -0
- package/src/modes/theme/defaults/dark-github.json +105 -0
- package/src/modes/theme/defaults/dark-gruvbox.json +112 -0
- package/src/modes/theme/defaults/dark-lavender.json +95 -0
- package/src/modes/theme/defaults/dark-lunar.json +89 -0
- package/src/modes/theme/defaults/dark-midnight.json +95 -0
- package/src/modes/theme/defaults/dark-monochrome.json +94 -0
- package/src/modes/theme/defaults/dark-monokai.json +98 -0
- package/src/modes/theme/defaults/dark-nebula.json +90 -0
- package/src/modes/theme/defaults/dark-nord.json +97 -0
- package/src/modes/theme/defaults/dark-ocean.json +101 -0
- package/src/modes/theme/defaults/dark-one.json +100 -0
- package/src/modes/theme/defaults/dark-poimandres.json +143 -0
- package/src/modes/theme/defaults/dark-rainforest.json +91 -0
- package/src/modes/theme/defaults/dark-reef.json +91 -0
- package/src/modes/theme/defaults/dark-retro.json +92 -0
- package/src/modes/theme/defaults/dark-rose-pine.json +96 -0
- package/src/modes/theme/defaults/dark-sakura.json +95 -0
- package/src/modes/theme/defaults/dark-slate.json +95 -0
- package/src/modes/theme/defaults/dark-solarized.json +97 -0
- package/src/modes/theme/defaults/dark-solstice.json +90 -0
- package/src/modes/theme/defaults/dark-starfall.json +91 -0
- package/src/modes/theme/defaults/dark-sunset.json +99 -0
- package/src/modes/theme/defaults/dark-swamp.json +90 -0
- package/src/modes/theme/defaults/dark-synthwave.json +103 -0
- package/src/modes/theme/defaults/dark-taiga.json +91 -0
- package/src/modes/theme/defaults/dark-terminal.json +95 -0
- package/src/modes/theme/defaults/dark-tokyo-night.json +101 -0
- package/src/modes/theme/defaults/dark-tundra.json +91 -0
- package/src/modes/theme/defaults/dark-twilight.json +91 -0
- package/src/modes/theme/defaults/dark-volcanic.json +91 -0
- package/src/modes/theme/defaults/graphite.json +92 -0
- package/src/modes/theme/defaults/index.ts +199 -0
- package/src/modes/theme/defaults/light-arctic.json +107 -0
- package/src/modes/theme/defaults/light-aurora-day.json +91 -0
- package/src/modes/theme/defaults/light-canyon.json +91 -0
- package/src/modes/theme/defaults/light-catppuccin.json +106 -0
- package/src/modes/theme/defaults/light-cirrus.json +90 -0
- package/src/modes/theme/defaults/light-coral.json +95 -0
- package/src/modes/theme/defaults/light-cyberpunk.json +96 -0
- package/src/modes/theme/defaults/light-dawn.json +90 -0
- package/src/modes/theme/defaults/light-dunes.json +91 -0
- package/src/modes/theme/defaults/light-eucalyptus.json +95 -0
- package/src/modes/theme/defaults/light-forest.json +100 -0
- package/src/modes/theme/defaults/light-frost.json +95 -0
- package/src/modes/theme/defaults/light-github.json +115 -0
- package/src/modes/theme/defaults/light-glacier.json +91 -0
- package/src/modes/theme/defaults/light-gruvbox.json +108 -0
- package/src/modes/theme/defaults/light-haze.json +90 -0
- package/src/modes/theme/defaults/light-honeycomb.json +95 -0
- package/src/modes/theme/defaults/light-lagoon.json +91 -0
- package/src/modes/theme/defaults/light-lavender.json +95 -0
- package/src/modes/theme/defaults/light-meadow.json +91 -0
- package/src/modes/theme/defaults/light-mint.json +95 -0
- package/src/modes/theme/defaults/light-monochrome.json +101 -0
- package/src/modes/theme/defaults/light-ocean.json +99 -0
- package/src/modes/theme/defaults/light-one.json +99 -0
- package/src/modes/theme/defaults/light-opal.json +91 -0
- package/src/modes/theme/defaults/light-orchard.json +91 -0
- package/src/modes/theme/defaults/light-paper.json +95 -0
- package/src/modes/theme/defaults/light-poimandres.json +143 -0
- package/src/modes/theme/defaults/light-prism.json +90 -0
- package/src/modes/theme/defaults/light-retro.json +98 -0
- package/src/modes/theme/defaults/light-sand.json +95 -0
- package/src/modes/theme/defaults/light-savanna.json +91 -0
- package/src/modes/theme/defaults/light-solarized.json +102 -0
- package/src/modes/theme/defaults/light-soleil.json +90 -0
- package/src/modes/theme/defaults/light-sunset.json +99 -0
- package/src/modes/theme/defaults/light-synthwave.json +98 -0
- package/src/modes/theme/defaults/light-tokyo-night.json +111 -0
- package/src/modes/theme/defaults/light-wetland.json +91 -0
- package/src/modes/theme/defaults/light-zenith.json +89 -0
- package/src/modes/theme/defaults/limestone.json +94 -0
- package/src/modes/theme/defaults/mahogany.json +97 -0
- package/src/modes/theme/defaults/marble.json +93 -0
- package/src/modes/theme/defaults/obsidian.json +91 -0
- package/src/modes/theme/defaults/onyx.json +91 -0
- package/src/modes/theme/defaults/pearl.json +93 -0
- package/src/modes/theme/defaults/porcelain.json +91 -0
- package/src/modes/theme/defaults/quartz.json +96 -0
- package/src/modes/theme/defaults/sandstone.json +95 -0
- package/src/modes/theme/defaults/titanium.json +90 -0
- package/src/modes/theme/light.json +93 -0
- package/src/modes/theme/mermaid-cache.ts +92 -0
- package/src/modes/theme/shimmer.ts +305 -0
- package/src/modes/theme/theme-schema.json +463 -0
- package/src/modes/theme/theme.ts +3171 -0
- package/src/modes/turn-budget.ts +31 -0
- package/src/modes/types.ts +494 -0
- package/src/modes/ultrathink.ts +42 -0
- package/src/modes/utils/context-usage.ts +518 -0
- package/src/modes/utils/copy-targets.ts +378 -0
- package/src/modes/utils/hotkeys-markdown.ts +65 -0
- package/src/modes/utils/interactive-context-helpers.ts +31 -0
- package/src/modes/utils/keybinding-matchers.ts +86 -0
- package/src/modes/utils/tools-markdown.ts +31 -0
- package/src/modes/utils/transcript-render-helpers.ts +253 -0
- package/src/modes/utils/ui-helpers.ts +976 -0
- package/src/modes/warp-events.ts +232 -0
- package/src/modes/workflow.ts +55 -0
- package/src/plan-mode/approved-plan.ts +194 -0
- package/src/plan-mode/model-transition.ts +51 -0
- package/src/plan-mode/plan-files.ts +40 -0
- package/src/plan-mode/plan-handoff.ts +37 -0
- package/src/plan-mode/plan-protection.ts +31 -0
- package/src/plan-mode/state.ts +6 -0
- package/src/priority.json +60 -0
- package/src/prompts/advisor/active-repo-watchdog.md +6 -0
- package/src/prompts/advisor/advise-tool.md +3 -0
- package/src/prompts/advisor/context-files.md +8 -0
- package/src/prompts/advisor/system.md +98 -0
- package/src/prompts/agents/designer.md +74 -0
- package/src/prompts/agents/frontmatter.md +12 -0
- package/src/prompts/agents/init.md +33 -0
- package/src/prompts/agents/librarian.md +119 -0
- package/src/prompts/agents/reviewer.md +139 -0
- package/src/prompts/agents/scout.md +58 -0
- package/src/prompts/agents/security-reviewer.md +75 -0
- package/src/prompts/agents/task.md +17 -0
- package/src/prompts/bench/cache-prefix-chunk.md +1 -0
- package/src/prompts/bench/cache-prefix.md +3 -0
- package/src/prompts/bench/cache-suffix.md +1 -0
- package/src/prompts/bench.md +6 -0
- package/src/prompts/ci-green-request.md +36 -0
- package/src/prompts/dry-balance-bench.md +8 -0
- package/src/prompts/goals/goal-budget-limit.md +16 -0
- package/src/prompts/goals/goal-continuation.md +28 -0
- package/src/prompts/goals/goal-mode-active.md +23 -0
- package/src/prompts/goals/goal-mode-context.md +4 -0
- package/src/prompts/goals/goal-todo-context.md +12 -0
- package/src/prompts/goals/guided-goal-interview.md +43 -0
- package/src/prompts/memories/consolidation.md +30 -0
- package/src/prompts/memories/consolidation_system.md +4 -0
- package/src/prompts/memories/read-path.md +17 -0
- package/src/prompts/memories/stage_one_input.md +6 -0
- package/src/prompts/memories/stage_one_system.md +21 -0
- package/src/prompts/review-custom-request.md +21 -0
- package/src/prompts/review-headless-request.md +16 -0
- package/src/prompts/review-request.md +68 -0
- package/src/prompts/security/scan-coordinator.md +7 -0
- package/src/prompts/security/scan-request.md +21 -0
- package/src/prompts/security/validate-request.md +8 -0
- package/src/prompts/session/launch-completion.md +1 -0
- package/src/prompts/skills/autoload.md +8 -0
- package/src/prompts/skills/user-invocation.md +11 -0
- package/src/prompts/steering/parent-irc.md +5 -0
- package/src/prompts/steering/user-interjection.md +6 -0
- package/src/prompts/system/active-repo-context.md +4 -0
- package/src/prompts/system/agent-creation-architect.md +50 -0
- package/src/prompts/system/agent-creation-user.md +6 -0
- package/src/prompts/system/auto-continue.md +1 -0
- package/src/prompts/system/auto-thinking-difficulty-local.md +14 -0
- package/src/prompts/system/auto-thinking-difficulty.md +14 -0
- package/src/prompts/system/autolearn-guidance-learn.md +1 -0
- package/src/prompts/system/autolearn-guidance.md +7 -0
- package/src/prompts/system/autolearn-nudge-autocontinue.md +5 -0
- package/src/prompts/system/background-tan-dispatch.md +8 -0
- package/src/prompts/system/btw-user.md +8 -0
- package/src/prompts/system/commit-message-system.md +14 -0
- package/src/prompts/system/computer-safety.md +14 -0
- package/src/prompts/system/custom-system-prompt.md +64 -0
- package/src/prompts/system/eager-task.md +7 -0
- package/src/prompts/system/eager-todo.md +18 -0
- package/src/prompts/system/empty-stop-retry.md +4 -0
- package/src/prompts/system/gemini-tool-call-reminder.md +9 -0
- package/src/prompts/system/interrupted-thinking.md +7 -0
- package/src/prompts/system/irc-autoreply.md +6 -0
- package/src/prompts/system/irc-incoming.md +9 -0
- package/src/prompts/system/manual-continue.md +7 -0
- package/src/prompts/system/mcp-xdev-guidance.md +11 -0
- package/src/prompts/system/memory-consolidation-system.md +8 -0
- package/src/prompts/system/memory-extraction-system.md +26 -0
- package/src/prompts/system/mid-run-todo-nudge.md +3 -0
- package/src/prompts/system/omfg-user.md +50 -0
- package/src/prompts/system/orchestrate-notice.md +40 -0
- package/src/prompts/system/personalities/default.md +18 -0
- package/src/prompts/system/personalities/friendly.md +17 -0
- package/src/prompts/system/personalities/pragmatic.md +15 -0
- package/src/prompts/system/plan-mode-active.md +125 -0
- package/src/prompts/system/plan-mode-approved.md +22 -0
- package/src/prompts/system/plan-mode-compact-instructions.md +17 -0
- package/src/prompts/system/plan-mode-reference.md +10 -0
- package/src/prompts/system/plan-mode-subagent.md +33 -0
- package/src/prompts/system/plan-mode-tool-decision-reminder.md +9 -0
- package/src/prompts/system/plan-yolo-handoff.md +5 -0
- package/src/prompts/system/prewalk-checklist.md +7 -0
- package/src/prompts/system/prewalk-continue.md +1 -0
- package/src/prompts/system/prewalk-plan.md +13 -0
- package/src/prompts/system/project-prompt.md +61 -0
- package/src/prompts/system/recap-user.md +9 -0
- package/src/prompts/system/resolve-device-reminder.md +3 -0
- package/src/prompts/system/rewind-report.md +6 -0
- package/src/prompts/system/side-channel-no-tools.md +3 -0
- package/src/prompts/system/snapcompact-context-frames-note.md +1 -0
- package/src/prompts/system/snapcompact-context-stub.md +1 -0
- package/src/prompts/system/snapcompact-system-frames-note.md +1 -0
- package/src/prompts/system/snapcompact-system-stub.md +1 -0
- package/src/prompts/system/snapcompact-toolresult-note.md +1 -0
- package/src/prompts/system/speech-rewrite.md +15 -0
- package/src/prompts/system/subagent-async-pending.md +6 -0
- package/src/prompts/system/subagent-system-prompt.md +73 -0
- package/src/prompts/system/subagent-user-prompt.md +3 -0
- package/src/prompts/system/subagent-yield-reminder.md +23 -0
- package/src/prompts/system/system-prompt.md +263 -0
- package/src/prompts/system/tan-context-switch.md +17 -0
- package/src/prompts/system/task-label.md +23 -0
- package/src/prompts/system/thinking-loop-redirect.md +10 -0
- package/src/prompts/system/title-marker-instruction.md +1 -0
- package/src/prompts/system/title-system.md +16 -0
- package/src/prompts/system/tool-call-loop-redirect.md +8 -0
- package/src/prompts/system/ttsr-interrupt.md +7 -0
- package/src/prompts/system/ttsr-tool-reminder.md +5 -0
- package/src/prompts/system/ultrathink-notice.md +3 -0
- package/src/prompts/system/unexpected-stop-classifier.md +17 -0
- package/src/prompts/system/unexpected-stop-retry.md +4 -0
- package/src/prompts/system/vibe-mode-active.md +26 -0
- package/src/prompts/system/web-search.md +25 -0
- package/src/prompts/system/workflow-notice.md +112 -0
- package/src/prompts/system/xdev-mount-notice.md +20 -0
- package/src/prompts/tools/apply-patch.md +65 -0
- package/src/prompts/tools/ask.md +22 -0
- package/src/prompts/tools/ast-edit.md +11 -0
- package/src/prompts/tools/ast-grep.md +19 -0
- package/src/prompts/tools/async-result.md +8 -0
- package/src/prompts/tools/bash.md +23 -0
- package/src/prompts/tools/browser.md +29 -0
- package/src/prompts/tools/checkpoint.md +15 -0
- package/src/prompts/tools/computer.md +26 -0
- package/src/prompts/tools/debug.md +3 -0
- package/src/prompts/tools/eval.md +45 -0
- package/src/prompts/tools/github.md +22 -0
- package/src/prompts/tools/glob.md +16 -0
- package/src/prompts/tools/goal.md +11 -0
- package/src/prompts/tools/grep.md +13 -0
- package/src/prompts/tools/hub.md +34 -0
- package/src/prompts/tools/image-attachment-describe-system.md +8 -0
- package/src/prompts/tools/image-attachment-describe.md +10 -0
- package/src/prompts/tools/image-gen.md +7 -0
- package/src/prompts/tools/inspect-image-system.md +20 -0
- package/src/prompts/tools/inspect-image.md +22 -0
- package/src/prompts/tools/learn.md +7 -0
- package/src/prompts/tools/lsp-late-diagnostic.md +8 -0
- package/src/prompts/tools/lsp.md +19 -0
- package/src/prompts/tools/manage-skill.md +9 -0
- package/src/prompts/tools/memory-edit.md +12 -0
- package/src/prompts/tools/patch.md +57 -0
- package/src/prompts/tools/read.md +27 -0
- package/src/prompts/tools/recall.md +7 -0
- package/src/prompts/tools/reflect.md +5 -0
- package/src/prompts/tools/replace.md +30 -0
- package/src/prompts/tools/retain.md +6 -0
- package/src/prompts/tools/rewind.md +14 -0
- package/src/prompts/tools/security-publish.md +1 -0
- package/src/prompts/tools/security-scan.md +1 -0
- package/src/prompts/tools/task-async-contract.md +1 -0
- package/src/prompts/tools/task-summary.md +20 -0
- package/src/prompts/tools/task.md +83 -0
- package/src/prompts/tools/todo.md +42 -0
- package/src/prompts/tools/vibe-kill.md +3 -0
- package/src/prompts/tools/vibe-list.md +3 -0
- package/src/prompts/tools/vibe-send.md +9 -0
- package/src/prompts/tools/vibe-spawn.md +10 -0
- package/src/prompts/tools/vibe-turn-result.md +19 -0
- package/src/prompts/tools/vibe-wait.md +8 -0
- package/src/prompts/tools/web-search.md +8 -0
- package/src/prompts/tools/write.md +14 -0
- package/src/registry/agent-lifecycle.ts +505 -0
- package/src/registry/agent-registry.ts +287 -0
- package/src/registry/persisted-agents.ts +423 -0
- package/src/sdk.ts +3820 -0
- package/src/secrets/index.ts +375 -0
- package/src/secrets/obfuscator.ts +2629 -0
- package/src/secrets/regex.ts +21 -0
- package/src/security/auth.ts +98 -0
- package/src/security/cloud.ts +686 -0
- package/src/security/comparison.ts +255 -0
- package/src/security/contracts/ids.ts +111 -0
- package/src/security/contracts/index.ts +4 -0
- package/src/security/contracts/schemas.ts +219 -0
- package/src/security/contracts/types.ts +254 -0
- package/src/security/contracts/validation.ts +69 -0
- package/src/security/coordinator.ts +708 -0
- package/src/security/importers/codex-security.ts +387 -0
- package/src/security/importers/index.ts +2 -0
- package/src/security/importers/sarif.ts +357 -0
- package/src/security/index.ts +13 -0
- package/src/security/preflight.ts +405 -0
- package/src/security/provenance.ts +106 -0
- package/src/security/publication.ts +326 -0
- package/src/security/remediation.ts +93 -0
- package/src/security/resource-output.ts +50 -0
- package/src/security/sarif.ts +78 -0
- package/src/security/store.ts +430 -0
- package/src/session/acp-permission-gate.ts +165 -0
- package/src/session/agent-session-events.ts +67 -0
- package/src/session/agent-session-types.ts +407 -0
- package/src/session/agent-session.ts +9000 -0
- package/src/session/agent-storage.ts +807 -0
- package/src/session/artifacts.ts +154 -0
- package/src/session/async-job-delivery.ts +82 -0
- package/src/session/auth-broker-config.ts +92 -0
- package/src/session/auth-storage.ts +25 -0
- package/src/session/bash-runner.ts +326 -0
- package/src/session/blob-store.ts +295 -0
- package/src/session/checkpoint-entries.ts +81 -0
- package/src/session/claude-session-store.ts +426 -0
- package/src/session/client-bridge.ts +85 -0
- package/src/session/codex-auto-reset.ts +673 -0
- package/src/session/codex-session-store.ts +673 -0
- package/src/session/compact-modes.ts +105 -0
- package/src/session/credential-pin.ts +93 -0
- package/src/session/eval-runner.ts +219 -0
- package/src/session/exit-diagnostics.ts +310 -0
- package/src/session/foreign-session-import.ts +52 -0
- package/src/session/foreign-session-jsonl.ts +29 -0
- package/src/session/foreign-session-store.ts +26 -0
- package/src/session/history-storage.ts +329 -0
- package/src/session/indexed-session-storage.ts +553 -0
- package/src/session/irc-bridge.ts +203 -0
- package/src/session/launch-completion.ts +37 -0
- package/src/session/messages.ts +1304 -0
- package/src/session/model-controls.ts +757 -0
- package/src/session/prewalk.ts +279 -0
- package/src/session/provider-image-budget.ts +86 -0
- package/src/session/queued-messages.ts +99 -0
- package/src/session/redis-session-storage.ts +257 -0
- package/src/session/retry-fallback-chains.ts +455 -0
- package/src/session/role-models.ts +85 -0
- package/src/session/session-advisors.ts +1896 -0
- package/src/session/session-context.ts +584 -0
- package/src/session/session-dump-format.ts +216 -0
- package/src/session/session-entries.ts +306 -0
- package/src/session/session-handoff.ts +325 -0
- package/src/session/session-history-format.ts +459 -0
- package/src/session/session-listing.ts +715 -0
- package/src/session/session-loader.ts +362 -0
- package/src/session/session-maintenance.ts +3115 -0
- package/src/session/session-manager.ts +2747 -0
- package/src/session/session-memory.ts +222 -0
- package/src/session/session-metadata.ts +53 -0
- package/src/session/session-migrations.ts +78 -0
- package/src/session/session-paths.ts +280 -0
- package/src/session/session-persistence.ts +293 -0
- package/src/session/session-provider-boundary.ts +306 -0
- package/src/session/session-stats.ts +349 -0
- package/src/session/session-storage.ts +774 -0
- package/src/session/session-title-slot.ts +141 -0
- package/src/session/session-tools.ts +1385 -0
- package/src/session/session-workspace.ts +53 -0
- package/src/session/settings-stream-fn.ts +79 -0
- package/src/session/shake-types.ts +43 -0
- package/src/session/snapcompact-inline.ts +545 -0
- package/src/session/snapcompact-savings-journal.ts +113 -0
- package/src/session/sql-session-storage.ts +374 -0
- package/src/session/stream-guards.ts +417 -0
- package/src/session/streaming-output.ts +1459 -0
- package/src/session/todo-tracker.ts +380 -0
- package/src/session/tool-choice-queue.ts +305 -0
- package/src/session/ttsr-coordinator.ts +496 -0
- package/src/session/turn-persistence.ts +142 -0
- package/src/session/turn-recovery.ts +2005 -0
- package/src/session/unexpected-stop-classifier.ts +141 -0
- package/src/session/yield-queue.ts +288 -0
- package/src/slash-commands/acp-builtins.ts +70 -0
- package/src/slash-commands/available-commands.ts +105 -0
- package/src/slash-commands/builtin-registry.ts +3149 -0
- package/src/slash-commands/helpers/active-oauth-account.ts +80 -0
- package/src/slash-commands/helpers/collab-qrcode.ts +28 -0
- package/src/slash-commands/helpers/context-report.ts +66 -0
- package/src/slash-commands/helpers/format.ts +46 -0
- package/src/slash-commands/helpers/logout.ts +108 -0
- package/src/slash-commands/helpers/marketplace-manager.ts +25 -0
- package/src/slash-commands/helpers/mcp.ts +533 -0
- package/src/slash-commands/helpers/parse.ts +85 -0
- package/src/slash-commands/helpers/reset-usage.ts +68 -0
- package/src/slash-commands/helpers/security.ts +451 -0
- package/src/slash-commands/helpers/session-pin.ts +44 -0
- package/src/slash-commands/helpers/ssh.ts +196 -0
- package/src/slash-commands/helpers/stats-dashboard.ts +86 -0
- package/src/slash-commands/helpers/todo.ts +285 -0
- package/src/slash-commands/helpers/usage-report.ts +198 -0
- package/src/slash-commands/marketplace-install-parser.ts +99 -0
- package/src/slash-commands/types.ts +139 -0
- package/src/ssh/config-writer.ts +183 -0
- package/src/ssh/connection-manager.ts +667 -0
- package/src/ssh/file-transfer.ts +214 -0
- package/src/ssh/sshfs-mount.ts +163 -0
- package/src/ssh/utils.ts +51 -0
- package/src/startup-splash.ts +19 -0
- package/src/stt/asr-client.ts +401 -0
- package/src/stt/asr-protocol.ts +65 -0
- package/src/stt/asr-worker.ts +603 -0
- package/src/stt/downloader.ts +142 -0
- package/src/stt/endpointer.ts +259 -0
- package/src/stt/index.ts +6 -0
- package/src/stt/models.ts +150 -0
- package/src/stt/sherpa-runtime.ts +71 -0
- package/src/stt/stt-controller.ts +320 -0
- package/src/stt/submit-trigger.ts +74 -0
- package/src/subprocess/worker-client.ts +463 -0
- package/src/subprocess/worker-runtime.ts +494 -0
- package/src/system-prompt.ts +921 -0
- package/src/task/agents.ts +170 -0
- package/src/task/commands.ts +132 -0
- package/src/task/discovery.ts +145 -0
- package/src/task/executor.ts +3431 -0
- package/src/task/index.ts +1515 -0
- package/src/task/isolation-ownership.ts +106 -0
- package/src/task/isolation-runner.ts +444 -0
- package/src/task/label.ts +40 -0
- package/src/task/name-generator.ts +1577 -0
- package/src/task/omp-command.ts +26 -0
- package/src/task/output-manager.ts +115 -0
- package/src/task/parallel.ts +221 -0
- package/src/task/persisted-revive.ts +173 -0
- package/src/task/prewalk.ts +6 -0
- package/src/task/prompt-policy.ts +8 -0
- package/src/task/provider-concurrency.ts +100 -0
- package/src/task/read-only-policy.ts +27 -0
- package/src/task/render.ts +1830 -0
- package/src/task/renderer.ts +14 -0
- package/src/task/repair-args.ts +118 -0
- package/src/task/spawn-policy.ts +72 -0
- package/src/task/structured-subagent.ts +676 -0
- package/src/task/subprocess-tool-registry.ts +88 -0
- package/src/task/types.ts +555 -0
- package/src/task/worktree.ts +967 -0
- package/src/task/yield-assembly.ts +198 -0
- package/src/telemetry-export.ts +504 -0
- package/src/thinking.ts +377 -0
- package/src/tiny/device.ts +111 -0
- package/src/tiny/dtype.ts +101 -0
- package/src/tiny/message-preproc.ts +155 -0
- package/src/tiny/models.ts +268 -0
- package/src/tiny/text.ts +290 -0
- package/src/tiny/title-client.ts +460 -0
- package/src/tiny/title-protocol.ts +56 -0
- package/src/tiny/worker.ts +354 -0
- package/src/tools/acp-bridge.ts +125 -0
- package/src/tools/approval.ts +245 -0
- package/src/tools/ask.ts +1459 -0
- package/src/tools/ast-edit.ts +718 -0
- package/src/tools/ast-grep.ts +526 -0
- package/src/tools/auto-generated-guard.ts +335 -0
- package/src/tools/bash-interactive.ts +435 -0
- package/src/tools/bash-interceptor.ts +148 -0
- package/src/tools/bash-pty-selection.ts +14 -0
- package/src/tools/bash-skill-urls.ts +350 -0
- package/src/tools/bash.ts +1826 -0
- package/src/tools/browser/aria/aria-snapshot.bundle.txt +7 -0
- package/src/tools/browser/aria/aria-snapshot.ts +131 -0
- package/src/tools/browser/attach.ts +219 -0
- package/src/tools/browser/cmux/cmux-tab.ts +1531 -0
- package/src/tools/browser/cmux/rpc.ts +200 -0
- package/src/tools/browser/cmux/socket-client.ts +445 -0
- package/src/tools/browser/launch.ts +939 -0
- package/src/tools/browser/readable.ts +112 -0
- package/src/tools/browser/registry.ts +447 -0
- package/src/tools/browser/relay/bridge.ts +945 -0
- package/src/tools/browser/relay/daemon.ts +117 -0
- package/src/tools/browser/relay/extension-assets/background.js.txt +242 -0
- package/src/tools/browser/relay/extension-assets/manifest.json.txt +14 -0
- package/src/tools/browser/relay/extension-assets/options.html.txt +53 -0
- package/src/tools/browser/relay/extension-assets/options.js.txt +23 -0
- package/src/tools/browser/relay/kind.ts +41 -0
- package/src/tools/browser/relay/protocol.ts +54 -0
- package/src/tools/browser/relay/server.ts +141 -0
- package/src/tools/browser/render.ts +229 -0
- package/src/tools/browser/run-output.ts +76 -0
- package/src/tools/browser/shared-daemon.ts +139 -0
- package/src/tools/browser/tab-protocol.ts +123 -0
- package/src/tools/browser/tab-supervisor.ts +1077 -0
- package/src/tools/browser/tab-worker-entry.ts +29 -0
- package/src/tools/browser/tab-worker.ts +1982 -0
- package/src/tools/browser.ts +487 -0
- package/src/tools/builtin-names.ts +67 -0
- package/src/tools/checkpoint.ts +137 -0
- package/src/tools/computer/exposure.ts +14 -0
- package/src/tools/computer/protocol.ts +69 -0
- package/src/tools/computer/supervisor.ts +409 -0
- package/src/tools/computer/worker-entry.ts +39 -0
- package/src/tools/computer/worker.ts +745 -0
- package/src/tools/computer-renderer.ts +147 -0
- package/src/tools/computer.ts +222 -0
- package/src/tools/conflict-detect.ts +815 -0
- package/src/tools/context.ts +49 -0
- package/src/tools/debug.ts +1121 -0
- package/src/tools/default-renderer.ts +154 -0
- package/src/tools/essential-tools.ts +46 -0
- package/src/tools/eval-backends.ts +34 -0
- package/src/tools/eval-format/index.ts +24 -0
- package/src/tools/eval-format/javascript.ts +952 -0
- package/src/tools/eval-format/julia.ts +446 -0
- package/src/tools/eval-format/python.ts +544 -0
- package/src/tools/eval-format/ruby.ts +380 -0
- package/src/tools/eval-render.ts +784 -0
- package/src/tools/eval.ts +774 -0
- package/src/tools/fetch.ts +1889 -0
- package/src/tools/file-recorder.ts +35 -0
- package/src/tools/fs-cache-invalidation.ts +28 -0
- package/src/tools/gh-cache-invalidation.ts +175 -0
- package/src/tools/gh-format.ts +12 -0
- package/src/tools/gh-renderer.ts +484 -0
- package/src/tools/gh.ts +3958 -0
- package/src/tools/github-cache.ts +663 -0
- package/src/tools/glob.ts +691 -0
- package/src/tools/grep.ts +1920 -0
- package/src/tools/grouped-file-output.ts +210 -0
- package/src/tools/hub/index.ts +579 -0
- package/src/tools/hub/jobs.ts +714 -0
- package/src/tools/hub/launch.ts +690 -0
- package/src/tools/hub/messaging.ts +735 -0
- package/src/tools/hub/types.ts +117 -0
- package/src/tools/image-gen.ts +1689 -0
- package/src/tools/image-providers.ts +50 -0
- package/src/tools/index.ts +736 -0
- package/src/tools/inspect-image-renderer.ts +133 -0
- package/src/tools/inspect-image.ts +316 -0
- package/src/tools/json-tree.ts +260 -0
- package/src/tools/jtd-to-json-schema.ts +219 -0
- package/src/tools/jtd-to-typescript.ts +136 -0
- package/src/tools/jtd-utils.ts +102 -0
- package/src/tools/learn.ts +141 -0
- package/src/tools/list-limit.ts +40 -0
- package/src/tools/manage-skill.ts +102 -0
- package/src/tools/match-line-format.ts +20 -0
- package/src/tools/memory-edit.ts +61 -0
- package/src/tools/memory-recall.ts +102 -0
- package/src/tools/memory-reflect.ts +88 -0
- package/src/tools/memory-render.ts +211 -0
- package/src/tools/memory-retain.ts +89 -0
- package/src/tools/output-meta.ts +860 -0
- package/src/tools/output-schema-validator.ts +307 -0
- package/src/tools/path-utils.ts +1489 -0
- package/src/tools/plan-mode-guard.ts +155 -0
- package/src/tools/puppeteer/00_stealth_tampering.txt +44 -0
- package/src/tools/puppeteer/01_stealth_activity.txt +80 -0
- package/src/tools/puppeteer/02_stealth_hairline.txt +57 -0
- package/src/tools/puppeteer/03_stealth_botd.txt +380 -0
- package/src/tools/puppeteer/04_stealth_iframe.txt +174 -0
- package/src/tools/puppeteer/05_stealth_webgl.txt +233 -0
- package/src/tools/puppeteer/06_stealth_screen.txt +260 -0
- package/src/tools/puppeteer/07_stealth_fonts.txt +99 -0
- package/src/tools/puppeteer/08_stealth_audio.txt +63 -0
- package/src/tools/puppeteer/09_stealth_locale.txt +51 -0
- package/src/tools/puppeteer/10_stealth_plugins.txt +212 -0
- package/src/tools/puppeteer/11_stealth_hardware.txt +59 -0
- package/src/tools/puppeteer/12_stealth_codecs.txt +42 -0
- package/src/tools/puppeteer/13_stealth_worker.txt +235 -0
- package/src/tools/read.ts +3762 -0
- package/src/tools/render-utils.ts +926 -0
- package/src/tools/renderers.ts +133 -0
- package/src/tools/report-tool-issue.ts +568 -0
- package/src/tools/resolve.ts +423 -0
- package/src/tools/review.ts +103 -0
- package/src/tools/run-scope.ts +417 -0
- package/src/tools/security-scan.ts +287 -0
- package/src/tools/shell-tokenize.ts +213 -0
- package/src/tools/sqlite-reader.ts +884 -0
- package/src/tools/terminal-output.ts +141 -0
- package/src/tools/todo.ts +1226 -0
- package/src/tools/tool-errors.ts +62 -0
- package/src/tools/tool-result.ts +102 -0
- package/src/tools/tool-timeouts.ts +38 -0
- package/src/tools/tts.ts +266 -0
- package/src/tools/vibe.ts +608 -0
- package/src/tools/write.ts +1646 -0
- package/src/tools/xdev.ts +560 -0
- package/src/tools/yield.ts +486 -0
- package/src/tts/downloader.ts +64 -0
- package/src/tts/index.ts +10 -0
- package/src/tts/models.ts +137 -0
- package/src/tts/runtime.ts +21 -0
- package/src/tts/speakable.ts +392 -0
- package/src/tts/speech-enhancer.ts +206 -0
- package/src/tts/streaming-player.ts +120 -0
- package/src/tts/tts-client.ts +475 -0
- package/src/tts/tts-protocol.ts +69 -0
- package/src/tts/tts-worker.ts +434 -0
- package/src/tts/vocalizer.ts +419 -0
- package/src/tts/wav.ts +58 -0
- package/src/tui/code-cell.ts +268 -0
- package/src/tui/file-list.ts +55 -0
- package/src/tui/hyperlink.ts +178 -0
- package/src/tui/index.ts +13 -0
- package/src/tui/output-block.ts +268 -0
- package/src/tui/status-line.ts +54 -0
- package/src/tui/tree-list.ts +172 -0
- package/src/tui/types.ts +15 -0
- package/src/tui/utils.ts +103 -0
- package/src/tui/width-aware-text.ts +58 -0
- package/src/utils/active-repo-context.ts +143 -0
- package/src/utils/block-context.ts +312 -0
- package/src/utils/changelog.ts +373 -0
- package/src/utils/clipboard.ts +361 -0
- package/src/utils/command-args.ts +74 -0
- package/src/utils/commit-message-generator.ts +148 -0
- package/src/utils/cpuprofile.ts +235 -0
- package/src/utils/edit-mode.ts +61 -0
- package/src/utils/enhanced-paste.ts +230 -0
- package/src/utils/event-bus.ts +33 -0
- package/src/utils/external-editor.ts +80 -0
- package/src/utils/fetch-timeout.ts +10 -0
- package/src/utils/file-display-mode.ts +44 -0
- package/src/utils/file-mentions.ts +293 -0
- package/src/utils/git.ts +2472 -0
- package/src/utils/image-loading.ts +236 -0
- package/src/utils/image-resize.ts +420 -0
- package/src/utils/image-vision-fallback.ts +196 -0
- package/src/utils/inspect-image-mode.ts +39 -0
- package/src/utils/ipc.ts +38 -0
- package/src/utils/jj.ts +422 -0
- package/src/utils/lang-from-path.ts +251 -0
- package/src/utils/late-cleanup.ts +17 -0
- package/src/utils/local-date.ts +7 -0
- package/src/utils/mac-file-urls.applescript +37 -0
- package/src/utils/markit-cache.ts +166 -0
- package/src/utils/markit.ts +223 -0
- package/src/utils/mupdf-wasm-embed.ts +12 -0
- package/src/utils/open.ts +126 -0
- package/src/utils/profile-tree.ts +111 -0
- package/src/utils/prompt-path.ts +3 -0
- package/src/utils/qrcode.ts +535 -0
- package/src/utils/sample-profile.ts +437 -0
- package/src/utils/session-color.ts +142 -0
- package/src/utils/shell-snapshot-fn-env.sh +63 -0
- package/src/utils/shell-snapshot.ts +326 -0
- package/src/utils/sixel.ts +69 -0
- package/src/utils/thinking-display.ts +163 -0
- package/src/utils/title-generator.ts +597 -0
- package/src/utils/token-rate.ts +72 -0
- package/src/utils/tool-choice.ts +50 -0
- package/src/utils/tools-manager.ts +411 -0
- package/src/utils/turndown.ts +82 -0
- package/src/utils/zip.ts +1106 -0
- package/src/vibe/runtime.ts +1684 -0
- package/src/vibe/state.ts +4 -0
- package/src/web/kagi.ts +305 -0
- package/src/web/parallel.ts +354 -0
- package/src/web/scrapers/artifacthub.ts +207 -0
- package/src/web/scrapers/arxiv.ts +83 -0
- package/src/web/scrapers/aur.ts +162 -0
- package/src/web/scrapers/biorxiv.ts +133 -0
- package/src/web/scrapers/bluesky.ts +262 -0
- package/src/web/scrapers/brew.ts +172 -0
- package/src/web/scrapers/cheatsh.ts +68 -0
- package/src/web/scrapers/chocolatey.ts +196 -0
- package/src/web/scrapers/choosealicense.ts +95 -0
- package/src/web/scrapers/cisa-kev.ts +87 -0
- package/src/web/scrapers/clojars.ts +154 -0
- package/src/web/scrapers/coingecko.ts +177 -0
- package/src/web/scrapers/crates-io.ts +97 -0
- package/src/web/scrapers/crossref.ts +136 -0
- package/src/web/scrapers/devto.ts +147 -0
- package/src/web/scrapers/discogs.ts +306 -0
- package/src/web/scrapers/discourse.ts +197 -0
- package/src/web/scrapers/dockerhub.ts +138 -0
- package/src/web/scrapers/docs-rs.ts +663 -0
- package/src/web/scrapers/fdroid.ts +134 -0
- package/src/web/scrapers/firefox-addons.ts +191 -0
- package/src/web/scrapers/flathub.ts +223 -0
- package/src/web/scrapers/github-gist.ts +58 -0
- package/src/web/scrapers/github.ts +800 -0
- package/src/web/scrapers/gitlab.ts +401 -0
- package/src/web/scrapers/go-pkg.ts +266 -0
- package/src/web/scrapers/hackage.ts +129 -0
- package/src/web/scrapers/hackernews.ts +189 -0
- package/src/web/scrapers/hex.ts +105 -0
- package/src/web/scrapers/huggingface.ts +321 -0
- package/src/web/scrapers/iacr.ts +89 -0
- package/src/web/scrapers/index.ts +252 -0
- package/src/web/scrapers/jetbrains-marketplace.ts +159 -0
- package/src/web/scrapers/lemmy.ts +203 -0
- package/src/web/scrapers/lobsters.ts +175 -0
- package/src/web/scrapers/mastodon.ts +292 -0
- package/src/web/scrapers/maven.ts +138 -0
- package/src/web/scrapers/mdn.ts +173 -0
- package/src/web/scrapers/metacpan.ts +222 -0
- package/src/web/scrapers/musicbrainz.ts +250 -0
- package/src/web/scrapers/npm.ts +98 -0
- package/src/web/scrapers/nuget.ts +183 -0
- package/src/web/scrapers/nvd.ts +222 -0
- package/src/web/scrapers/ollama.ts +239 -0
- package/src/web/scrapers/open-vsx.ts +106 -0
- package/src/web/scrapers/opencorporates.ts +292 -0
- package/src/web/scrapers/openlibrary.ts +336 -0
- package/src/web/scrapers/orcid.ts +286 -0
- package/src/web/scrapers/osv.ts +176 -0
- package/src/web/scrapers/packagist.ts +160 -0
- package/src/web/scrapers/pub-dev.ts +143 -0
- package/src/web/scrapers/pubmed.ts +211 -0
- package/src/web/scrapers/pypi.ts +112 -0
- package/src/web/scrapers/rawg.ts +110 -0
- package/src/web/scrapers/readthedocs.ts +121 -0
- package/src/web/scrapers/reddit.ts +95 -0
- package/src/web/scrapers/repology.ts +251 -0
- package/src/web/scrapers/rfc.ts +201 -0
- package/src/web/scrapers/rubygems.ts +103 -0
- package/src/web/scrapers/searchcode.ts +189 -0
- package/src/web/scrapers/sec-edgar.ts +261 -0
- package/src/web/scrapers/semantic-scholar.ts +171 -0
- package/src/web/scrapers/snapcraft.ts +187 -0
- package/src/web/scrapers/sourcegraph.ts +336 -0
- package/src/web/scrapers/spdx.ts +108 -0
- package/src/web/scrapers/spotify.ts +198 -0
- package/src/web/scrapers/stackoverflow.ts +120 -0
- package/src/web/scrapers/terraform.ts +277 -0
- package/src/web/scrapers/tldr.ts +47 -0
- package/src/web/scrapers/twitter.ts +94 -0
- package/src/web/scrapers/types.ts +354 -0
- package/src/web/scrapers/utils.ts +109 -0
- package/src/web/scrapers/vimeo.ts +133 -0
- package/src/web/scrapers/vscode-marketplace.ts +187 -0
- package/src/web/scrapers/w3c.ts +156 -0
- package/src/web/scrapers/wikidata.ts +344 -0
- package/src/web/scrapers/wikipedia.ts +84 -0
- package/src/web/scrapers/youtube.ts +325 -0
- package/src/web/search/index.ts +393 -0
- package/src/web/search/provider.ts +272 -0
- package/src/web/search/providers/anthropic.ts +406 -0
- package/src/web/search/providers/base.ts +112 -0
- package/src/web/search/providers/brave.ts +181 -0
- package/src/web/search/providers/browser-headers.ts +82 -0
- package/src/web/search/providers/browser-page.ts +125 -0
- package/src/web/search/providers/codex.ts +788 -0
- package/src/web/search/providers/duckduckgo.ts +382 -0
- package/src/web/search/providers/ecosia.ts +183 -0
- package/src/web/search/providers/exa.ts +513 -0
- package/src/web/search/providers/firecrawl.ts +213 -0
- package/src/web/search/providers/gemini.ts +634 -0
- package/src/web/search/providers/google.ts +195 -0
- package/src/web/search/providers/jina.ts +144 -0
- package/src/web/search/providers/kagi.ts +98 -0
- package/src/web/search/providers/kimi.ts +221 -0
- package/src/web/search/providers/mojeek.ts +220 -0
- package/src/web/search/providers/parallel.ts +186 -0
- package/src/web/search/providers/perplexity-auth.ts +142 -0
- package/src/web/search/providers/perplexity.ts +997 -0
- package/src/web/search/providers/public.ts +199 -0
- package/src/web/search/providers/searxng.ts +467 -0
- package/src/web/search/providers/startpage.ts +225 -0
- package/src/web/search/providers/synthetic.ts +126 -0
- package/src/web/search/providers/tavily.ts +244 -0
- package/src/web/search/providers/tinyfish.ts +166 -0
- package/src/web/search/providers/utils.ts +130 -0
- package/src/web/search/providers/xai.ts +372 -0
- package/src/web/search/providers/zai.ts +452 -0
- package/src/web/search/query.ts +850 -0
- package/src/web/search/render.ts +262 -0
- package/src/web/search/types.ts +518 -0
- package/src/web/search/utils.ts +17 -0
- package/src/workspace-tree.ts +326 -0
|
@@ -0,0 +1,1226 @@
|
|
|
1
|
+
import { type } from "@oh-my-pi/omptype";
|
|
2
|
+
import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback } from "@oh-my-pi/pi-agent-core";
|
|
3
|
+
import type { ToolExample } from "@oh-my-pi/pi-ai";
|
|
4
|
+
import type { Component } from "@oh-my-pi/pi-tui";
|
|
5
|
+
import { Text } from "@oh-my-pi/pi-tui";
|
|
6
|
+
import { isRecord, prompt, sanitizeText } from "@oh-my-pi/pi-utils";
|
|
7
|
+
import chalk from "@oh-my-pi/pi-utils/chalk";
|
|
8
|
+
import type { RenderResultOptions } from "../extensibility/custom-tools/types";
|
|
9
|
+
import type { Theme } from "../modes/theme/theme";
|
|
10
|
+
import todoDescription from "../prompts/tools/todo.md" with { type: "text" };
|
|
11
|
+
import type { ToolSession } from "../sdk";
|
|
12
|
+
import type { SessionEntry } from "../session/session-entries";
|
|
13
|
+
import { framedBlock, renderStatusLine, renderTreeList } from "../tui";
|
|
14
|
+
import { normalizePathLikeInput, resolveToCwd } from "./path-utils";
|
|
15
|
+
import { formatErrorDetail, formatMoreItems, PREVIEW_LIMITS, pluralize, replaceTabs } from "./render-utils";
|
|
16
|
+
|
|
17
|
+
// =============================================================================
|
|
18
|
+
// Types
|
|
19
|
+
// =============================================================================
|
|
20
|
+
|
|
21
|
+
export type TodoStatus = "pending" | "in_progress" | "completed" | "abandoned" | "blocked";
|
|
22
|
+
/** Operation names accepted by the todo tool and echoed in successful result details. */
|
|
23
|
+
export type TodoOperation = "init" | "start" | "done" | "rm" | "drop" | "block" | "unblock" | "append" | "view";
|
|
24
|
+
|
|
25
|
+
export interface TodoItem {
|
|
26
|
+
content: string;
|
|
27
|
+
status: TodoStatus;
|
|
28
|
+
/** When `status === "blocked"`, an optional note on what the task is waiting for. */
|
|
29
|
+
blocker?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface TodoPhase {
|
|
33
|
+
name: string;
|
|
34
|
+
tasks: TodoItem[];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Whether an unknown value is a persisted todo phase. */
|
|
38
|
+
export function isTodoPhase(value: unknown): value is TodoPhase {
|
|
39
|
+
if (!isRecord(value) || typeof value.name !== "string" || !Array.isArray(value.tasks)) return false;
|
|
40
|
+
return value.tasks.every(
|
|
41
|
+
task =>
|
|
42
|
+
isRecord(task) &&
|
|
43
|
+
typeof task.content === "string" &&
|
|
44
|
+
(task.status === "pending" ||
|
|
45
|
+
task.status === "in_progress" ||
|
|
46
|
+
task.status === "completed" ||
|
|
47
|
+
task.status === "abandoned" ||
|
|
48
|
+
task.status === "blocked"),
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface TodoCompletionTransition {
|
|
53
|
+
phase: string;
|
|
54
|
+
content: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface TodoToolDetails {
|
|
58
|
+
/** Operation that produced this snapshot; absent on legacy transcript entries. */
|
|
59
|
+
op?: TodoOperation;
|
|
60
|
+
phases: TodoPhase[];
|
|
61
|
+
storage: "session" | "memory";
|
|
62
|
+
completedTasks?: TodoCompletionTransition[];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// =============================================================================
|
|
66
|
+
// Schema
|
|
67
|
+
// =============================================================================
|
|
68
|
+
|
|
69
|
+
const TodoOp = type('"init" | "start" | "done" | "rm" | "drop" | "block" | "unblock" | "append" | "view"').describe(
|
|
70
|
+
"operation to apply",
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
const InitListEntry = type({
|
|
74
|
+
phase: type("string").describe("phase name"),
|
|
75
|
+
items: type("string").describe("task content").array().atLeastLength(1).describe("tasks for this phase"),
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const todoSchema = type({
|
|
79
|
+
op: TodoOp,
|
|
80
|
+
"list?": InitListEntry.array().describe("phased task list (init)"),
|
|
81
|
+
"task?": type("string").describe("task content"),
|
|
82
|
+
"phase?": type("string").describe("phase name"),
|
|
83
|
+
// No `atLeastLength(1)` here: `items` is only meaningful for `init`/`append`,
|
|
84
|
+
// and both enforce non-empty with op-specific errors. A stray `items: []` on
|
|
85
|
+
// an op that ignores it (e.g. `view`) must not be a hard schema rejection.
|
|
86
|
+
"items?": type("string").describe("task content").array().describe("tasks to append"),
|
|
87
|
+
"reason?": type("string").describe("blocker note (block op)"),
|
|
88
|
+
}).describe("apply a single todo operation");
|
|
89
|
+
|
|
90
|
+
type TodoParams = TodoSchema;
|
|
91
|
+
type TodoSchema = typeof todoSchema.infer;
|
|
92
|
+
/** A single todo op entry (the params object itself). */
|
|
93
|
+
type TodoOpEntryValue = TodoParams;
|
|
94
|
+
|
|
95
|
+
// =============================================================================
|
|
96
|
+
// State helpers
|
|
97
|
+
// =============================================================================
|
|
98
|
+
|
|
99
|
+
function findTaskByContent(phases: TodoPhase[], content: string): { task: TodoItem; phase: TodoPhase } | undefined {
|
|
100
|
+
for (const phase of phases) {
|
|
101
|
+
const task = phase.tasks.find(t => t.content === content);
|
|
102
|
+
if (task) return { task, phase };
|
|
103
|
+
}
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function findPhaseByName(phases: TodoPhase[], name: string): TodoPhase | undefined {
|
|
108
|
+
return phases.find(phase => phase.name === name);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function cloneTask(task: TodoItem): TodoItem {
|
|
112
|
+
return task.blocker !== undefined
|
|
113
|
+
? { content: task.content, status: task.status, blocker: task.blocker }
|
|
114
|
+
: { content: task.content, status: task.status };
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function clonePhases(phases: TodoPhase[]): TodoPhase[] {
|
|
118
|
+
return phases.map(phase => ({ name: phase.name, tasks: phase.tasks.map(cloneTask) }));
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function todoTransitionKey(phase: string, content: string): string {
|
|
122
|
+
return `${phase}\u0000${content}`;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function getCompletionTransitions(previous: TodoPhase[], updated: TodoPhase[]): TodoCompletionTransition[] {
|
|
126
|
+
const previousStatuses = new Map<string, TodoStatus>();
|
|
127
|
+
for (const phase of previous) {
|
|
128
|
+
for (const task of phase.tasks) {
|
|
129
|
+
previousStatuses.set(todoTransitionKey(phase.name, task.content), task.status);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const transitions: TodoCompletionTransition[] = [];
|
|
134
|
+
for (const phase of updated) {
|
|
135
|
+
for (const task of phase.tasks) {
|
|
136
|
+
if (task.status !== "completed") continue;
|
|
137
|
+
const previousStatus = previousStatuses.get(todoTransitionKey(phase.name, task.content));
|
|
138
|
+
if (previousStatus && previousStatus !== "completed") {
|
|
139
|
+
transitions.push({ phase: phase.name, content: task.content });
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return transitions;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function normalizeInProgressTask(phases: TodoPhase[]): void {
|
|
147
|
+
const orderedTasks = phases.flatMap(phase => phase.tasks);
|
|
148
|
+
if (orderedTasks.length === 0) return;
|
|
149
|
+
|
|
150
|
+
const inProgressTasks = orderedTasks.filter(task => task.status === "in_progress");
|
|
151
|
+
if (inProgressTasks.length > 1) {
|
|
152
|
+
for (const task of inProgressTasks.slice(1)) {
|
|
153
|
+
task.status = "pending";
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (inProgressTasks.length > 0) return;
|
|
158
|
+
|
|
159
|
+
const firstPendingTask = orderedTasks.find(task => task.status === "pending");
|
|
160
|
+
if (firstPendingTask) firstPendingTask.status = "in_progress";
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/** Return the active todo task, preferring an in-progress item over the first pending item. */
|
|
164
|
+
export function nextActionableTask(phases: readonly TodoPhase[]): TodoItem | undefined {
|
|
165
|
+
let firstPending: TodoItem | undefined;
|
|
166
|
+
for (const phase of phases) {
|
|
167
|
+
for (const task of phase.tasks) {
|
|
168
|
+
if (task.status === "in_progress") return task;
|
|
169
|
+
if (!firstPending && task.status === "pending") firstPending = task;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return firstPending;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export const USER_TODO_EDIT_CUSTOM_TYPE = "user_todo_edit";
|
|
176
|
+
|
|
177
|
+
export function getLatestTodoPhasesFromEntries(entries: SessionEntry[]): TodoPhase[] {
|
|
178
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
179
|
+
const entry = entries[i];
|
|
180
|
+
if (entry.type === "custom" && entry.customType === USER_TODO_EDIT_CUSTOM_TYPE) {
|
|
181
|
+
const data = entry.data as { phases?: unknown } | undefined;
|
|
182
|
+
if (data && Array.isArray(data.phases)) {
|
|
183
|
+
return clonePhases(data.phases as TodoPhase[]);
|
|
184
|
+
}
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
if (entry.type !== "message") continue;
|
|
188
|
+
const message = entry.message as { role?: string; toolName?: string; details?: unknown; isError?: boolean };
|
|
189
|
+
if (message.role !== "toolResult" || message.toolName !== "todo" || message.isError) continue;
|
|
190
|
+
|
|
191
|
+
const details = message.details as { phases?: unknown } | undefined;
|
|
192
|
+
if (!details || !Array.isArray(details.phases)) continue;
|
|
193
|
+
|
|
194
|
+
return clonePhases(details.phases as TodoPhase[]);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return [];
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/** Minimum overlap (after normalization) required for a substring match.
|
|
201
|
+
* Picked at six chars to admit single-word identifiers like "review" /
|
|
202
|
+
* "Sonnet" without admitting tiny common substrings like "test" / "fix"
|
|
203
|
+
* that would collide across unrelated todos. */
|
|
204
|
+
const TODO_DESCRIPTION_MIN_OVERLAP = 6;
|
|
205
|
+
|
|
206
|
+
function normalizeForTodoMatch(value: string): string {
|
|
207
|
+
return value
|
|
208
|
+
.toLowerCase()
|
|
209
|
+
.replace(/[^\p{L}\p{N}]+/gu, " ")
|
|
210
|
+
.trim();
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Report whether `content` likely names the same work as any entry in
|
|
215
|
+
* `descriptions`. Used by the sticky todo panel to light up a pending todo
|
|
216
|
+
* when an in-flight subagent is doing the work for it, without requiring
|
|
217
|
+
* the caller to flip the todo's status.
|
|
218
|
+
*
|
|
219
|
+
* Matching is normalize-then-equal first (lowercased; punctuation and
|
|
220
|
+
* whitespace runs both collapsed to a single space; trimmed), with a
|
|
221
|
+
* substring fallback in either direction so minor wording drift
|
|
222
|
+
* ("Sonnet #2: bug scan" vs "Sonnet #2") still links up. The substring
|
|
223
|
+
* fallback requires at least {@link TODO_DESCRIPTION_MIN_OVERLAP} chars on
|
|
224
|
+
* the contained side.
|
|
225
|
+
*/
|
|
226
|
+
export function todoMatchesAnyDescription(content: string, descriptions: readonly string[]): boolean {
|
|
227
|
+
const target = normalizeForTodoMatch(content);
|
|
228
|
+
if (!target) return false;
|
|
229
|
+
for (const desc of descriptions) {
|
|
230
|
+
const candidate = normalizeForTodoMatch(desc);
|
|
231
|
+
if (!candidate) continue;
|
|
232
|
+
if (target === candidate) return true;
|
|
233
|
+
if (target.length >= TODO_DESCRIPTION_MIN_OVERLAP && candidate.includes(target)) return true;
|
|
234
|
+
if (candidate.length >= TODO_DESCRIPTION_MIN_OVERLAP && target.includes(candidate)) return true;
|
|
235
|
+
}
|
|
236
|
+
return false;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* A todo the collapsed viewport treats as current work: the literal
|
|
241
|
+
* `in_progress` task or a pending task a live subagent is executing. Both
|
|
242
|
+
* collapsed views (transient tool result + sticky HUD) run this same policy so
|
|
243
|
+
* they can never disagree about what the agent is doing (#5873).
|
|
244
|
+
*/
|
|
245
|
+
function isActiveTodo<T extends { status: TodoStatus }>(task: T, isMatched: (task: T) => boolean): boolean {
|
|
246
|
+
return task.status === "in_progress" || (task.status === "pending" && isMatched(task));
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/** Result of {@link selectCollapsedTodos}: the rows to render plus an optional
|
|
250
|
+
* summary line (empty string ⇒ no summary row). */
|
|
251
|
+
export interface CollapsedTodoSelection<T> {
|
|
252
|
+
items: T[];
|
|
253
|
+
summary: string;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Walking-viewport selection for a phase's collapsed todo preview (#5873).
|
|
258
|
+
*
|
|
259
|
+
* Policy, applied to `tasks` in todo order:
|
|
260
|
+
* 1. While the phase has open work, completed/abandoned tasks are omitted. A
|
|
261
|
+
* phase with no open tasks left falls back to its closed tasks so the sticky
|
|
262
|
+
* HUD's closed-todo persistence still has something to render.
|
|
263
|
+
* 2. Every active task (in-progress, or pending matched to a live subagent) is
|
|
264
|
+
* placed at the head in stable todo order — never dropped for lying outside
|
|
265
|
+
* an ordinary window.
|
|
266
|
+
* 3. Remaining rows up to `cap` are filled with the pending tasks that follow
|
|
267
|
+
* the first active one, in todo order (falling back to leading pending tasks
|
|
268
|
+
* when no active task exists), so a freshly-promoted task leads the preview.
|
|
269
|
+
* 4. When active tasks alone exceed `cap`, only the first `cap` active tasks are
|
|
270
|
+
* shown and the summary counts the hidden *active* todos, never replacing
|
|
271
|
+
* them with unrelated pending rows.
|
|
272
|
+
*
|
|
273
|
+
* The summary otherwise counts the remaining tasks in the display base. Returns
|
|
274
|
+
* the whole base with an empty summary when it already fits.
|
|
275
|
+
*/
|
|
276
|
+
export function selectCollapsedTodos<T extends { status: TodoStatus }>(
|
|
277
|
+
tasks: T[],
|
|
278
|
+
isMatched: (task: T) => boolean,
|
|
279
|
+
cap: number,
|
|
280
|
+
): CollapsedTodoSelection<T> {
|
|
281
|
+
const open = tasks.filter(
|
|
282
|
+
task => task.status === "pending" || task.status === "in_progress" || task.status === "blocked",
|
|
283
|
+
);
|
|
284
|
+
// No open work: fall back to the closed tasks so a settled phase still
|
|
285
|
+
// renders (HUD closed-todo persistence). Closed tasks are never active.
|
|
286
|
+
const base = open.length > 0 ? open : tasks;
|
|
287
|
+
if (base.length <= cap) return { items: base, summary: "" };
|
|
288
|
+
|
|
289
|
+
const active = base.filter(task => isActiveTodo(task, isMatched));
|
|
290
|
+
// Only when active work strictly exceeds the cap do we drop pending rows and
|
|
291
|
+
// count hidden *actives*. At exactly `cap` actives, fall through so the normal
|
|
292
|
+
// branch still surfaces any following pending work in the summary.
|
|
293
|
+
if (active.length > cap) {
|
|
294
|
+
const hiddenActive = active.length - cap;
|
|
295
|
+
return {
|
|
296
|
+
items: active.slice(0, cap),
|
|
297
|
+
summary: `… ${hiddenActive} more active ${pluralize("todo", hiddenActive)}`,
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// Fill trailing rows with tasks following the first active one, so the
|
|
302
|
+
// promoted/current task leads and its successors follow in todo order.
|
|
303
|
+
const firstActiveIdx = active.length > 0 ? base.indexOf(active[0]) : 0;
|
|
304
|
+
const fill: T[] = [];
|
|
305
|
+
for (let i = firstActiveIdx; i < base.length && active.length + fill.length < cap; i++) {
|
|
306
|
+
const task = base[i];
|
|
307
|
+
if (isActiveTodo(task, isMatched)) continue;
|
|
308
|
+
fill.push(task);
|
|
309
|
+
}
|
|
310
|
+
const items = [...active, ...fill];
|
|
311
|
+
const hidden = base.length - items.length;
|
|
312
|
+
return { items, summary: hidden > 0 ? formatMoreItems(hidden, "todo") : "" };
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
function resolveTaskOrError(
|
|
316
|
+
phases: TodoPhase[],
|
|
317
|
+
content: string | undefined,
|
|
318
|
+
errors: string[],
|
|
319
|
+
): { task: TodoItem; phase: TodoPhase } | undefined {
|
|
320
|
+
if (!content) {
|
|
321
|
+
errors.push("Missing task content");
|
|
322
|
+
return undefined;
|
|
323
|
+
}
|
|
324
|
+
const hit = findTaskByContent(phases, content);
|
|
325
|
+
if (!hit) {
|
|
326
|
+
if (/^task-\d+$/.test(content)) {
|
|
327
|
+
errors.push(
|
|
328
|
+
`Task "${content}" not found. Tasks are referenced by content, not by IDs — pass the task's full text from the previous result.`,
|
|
329
|
+
);
|
|
330
|
+
} else {
|
|
331
|
+
const totalTasks = phases.reduce((sum, phase) => sum + phase.tasks.length, 0);
|
|
332
|
+
const hint = totalTasks === 0 ? " (todo list is empty — was it replaced or not yet created?)" : "";
|
|
333
|
+
errors.push(`Task "${content}" not found${hint}`);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
return hit;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
function resolvePhaseOrError(phases: TodoPhase[], name: string | undefined, errors: string[]): TodoPhase | undefined {
|
|
340
|
+
if (!name) {
|
|
341
|
+
errors.push("Missing phase name");
|
|
342
|
+
return undefined;
|
|
343
|
+
}
|
|
344
|
+
const phase = findPhaseByName(phases, name);
|
|
345
|
+
if (!phase) errors.push(`Phase "${name}" not found`);
|
|
346
|
+
return phase;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
function getTaskTargets(phases: TodoPhase[], entry: TodoOpEntryValue, errors: string[]): TodoItem[] {
|
|
350
|
+
if (entry.task) {
|
|
351
|
+
const hit = resolveTaskOrError(phases, entry.task, errors);
|
|
352
|
+
return hit ? [hit.task] : [];
|
|
353
|
+
}
|
|
354
|
+
if (entry.phase) {
|
|
355
|
+
const phase = resolvePhaseOrError(phases, entry.phase, errors);
|
|
356
|
+
return phase ? [...phase.tasks] : [];
|
|
357
|
+
}
|
|
358
|
+
return phases.flatMap(phase => phase.tasks);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/** Phase name for `init` given a flat `items` list with no explicit `phase`. */
|
|
362
|
+
const DEFAULT_INIT_PHASE = "Tasks";
|
|
363
|
+
|
|
364
|
+
function initPhases(entry: TodoOpEntryValue, errors: string[]): TodoPhase[] {
|
|
365
|
+
// Models routinely flatten the single-phase init into `{op:"init", items:[...]}`
|
|
366
|
+
// (optionally with a bare `phase`) instead of the canonical
|
|
367
|
+
// `list: [{phase, items}]`. Accept that shape by synthesizing a one-phase list
|
|
368
|
+
// so a common, recoverable mistake isn't a hard error.
|
|
369
|
+
const list =
|
|
370
|
+
entry.list ??
|
|
371
|
+
(entry.items && entry.items.length > 0
|
|
372
|
+
? [{ phase: entry.phase ?? DEFAULT_INIT_PHASE, items: entry.items }]
|
|
373
|
+
: undefined);
|
|
374
|
+
if (!list) {
|
|
375
|
+
errors.push("Missing list for init operation");
|
|
376
|
+
return [];
|
|
377
|
+
}
|
|
378
|
+
// Duplicate phase names / task contents would be permanently unaddressable
|
|
379
|
+
// (every targeting op resolves the first match), so reject them up front.
|
|
380
|
+
const seenPhases = new Set<string>();
|
|
381
|
+
const seenTasks = new Set<string>();
|
|
382
|
+
for (const listEntry of list) {
|
|
383
|
+
if (seenPhases.has(listEntry.phase)) {
|
|
384
|
+
errors.push(`Duplicate phase "${listEntry.phase}" in init list`);
|
|
385
|
+
}
|
|
386
|
+
seenPhases.add(listEntry.phase);
|
|
387
|
+
for (const content of listEntry.items) {
|
|
388
|
+
if (seenTasks.has(content)) {
|
|
389
|
+
errors.push(`Duplicate task "${content}" in init list`);
|
|
390
|
+
}
|
|
391
|
+
seenTasks.add(content);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
return list.map(listEntry => ({
|
|
395
|
+
name: listEntry.phase,
|
|
396
|
+
tasks: listEntry.items.map<TodoItem>(content => ({ content, status: "pending" })),
|
|
397
|
+
}));
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
function appendItems(phases: TodoPhase[], entry: TodoOpEntryValue, errors: string[]): TodoPhase[] {
|
|
401
|
+
if (!entry.phase) {
|
|
402
|
+
errors.push("Missing phase name for append operation");
|
|
403
|
+
return phases;
|
|
404
|
+
}
|
|
405
|
+
if (!entry.items || entry.items.length === 0) {
|
|
406
|
+
errors.push("Missing items for append operation");
|
|
407
|
+
return phases;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// Validate the whole batch before mutating so a failing op reports every
|
|
411
|
+
// duplicate and leaves nothing half-applied.
|
|
412
|
+
const seen = new Set<string>();
|
|
413
|
+
let hasDuplicate = false;
|
|
414
|
+
for (const content of entry.items) {
|
|
415
|
+
if (seen.has(content) || findTaskByContent(phases, content)) {
|
|
416
|
+
errors.push(`Task "${content}" already exists`);
|
|
417
|
+
hasDuplicate = true;
|
|
418
|
+
}
|
|
419
|
+
seen.add(content);
|
|
420
|
+
}
|
|
421
|
+
if (hasDuplicate) return phases;
|
|
422
|
+
|
|
423
|
+
let phase = findPhaseByName(phases, entry.phase);
|
|
424
|
+
if (!phase) {
|
|
425
|
+
phase = { name: entry.phase, tasks: [] };
|
|
426
|
+
phases.push(phase);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
for (const content of entry.items) {
|
|
430
|
+
phase.tasks.push({ content, status: "pending" });
|
|
431
|
+
}
|
|
432
|
+
return phases;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
function removeTasks(phases: TodoPhase[], entry: TodoOpEntryValue, errors: string[]): TodoPhase[] {
|
|
436
|
+
if (entry.task) {
|
|
437
|
+
const hit = resolveTaskOrError(phases, entry.task, errors);
|
|
438
|
+
if (!hit) return phases;
|
|
439
|
+
hit.phase.tasks = hit.phase.tasks.filter(candidate => candidate !== hit.task);
|
|
440
|
+
return phases;
|
|
441
|
+
}
|
|
442
|
+
if (entry.phase) {
|
|
443
|
+
const phase = resolvePhaseOrError(phases, entry.phase, errors);
|
|
444
|
+
if (!phase) return phases;
|
|
445
|
+
phase.tasks = [];
|
|
446
|
+
return phases;
|
|
447
|
+
}
|
|
448
|
+
for (const phase of phases) {
|
|
449
|
+
phase.tasks = [];
|
|
450
|
+
}
|
|
451
|
+
return phases;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
function applyEntry(phases: TodoPhase[], entry: TodoOpEntryValue, errors: string[]): TodoPhase[] {
|
|
455
|
+
switch (entry.op) {
|
|
456
|
+
case "init":
|
|
457
|
+
return initPhases(entry, errors);
|
|
458
|
+
case "start": {
|
|
459
|
+
const hit = resolveTaskOrError(phases, entry.task, errors);
|
|
460
|
+
if (!hit) return phases;
|
|
461
|
+
for (const phase of phases) {
|
|
462
|
+
for (const candidate of phase.tasks) {
|
|
463
|
+
if (candidate.status === "in_progress" && candidate !== hit.task) {
|
|
464
|
+
candidate.status = "pending";
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
hit.task.status = "in_progress";
|
|
469
|
+
return phases;
|
|
470
|
+
}
|
|
471
|
+
case "done": {
|
|
472
|
+
for (const task of getTaskTargets(phases, entry, errors)) {
|
|
473
|
+
task.status = "completed";
|
|
474
|
+
}
|
|
475
|
+
return phases;
|
|
476
|
+
}
|
|
477
|
+
case "drop": {
|
|
478
|
+
for (const task of getTaskTargets(phases, entry, errors)) {
|
|
479
|
+
task.status = "abandoned";
|
|
480
|
+
}
|
|
481
|
+
return phases;
|
|
482
|
+
}
|
|
483
|
+
case "block": {
|
|
484
|
+
if (!entry.task && !entry.phase) {
|
|
485
|
+
errors.push("block requires a task or phase target");
|
|
486
|
+
return phases;
|
|
487
|
+
}
|
|
488
|
+
// Collapse whitespace runs (incl. newlines) to single spaces: a blocker
|
|
489
|
+
// note rides on one Markdown checklist line (as a trailing HTML comment)
|
|
490
|
+
// and one HUD/summary line, so an embedded newline from a multi-line
|
|
491
|
+
// external error or user question would corrupt the round-trip parse and
|
|
492
|
+
// the rendered line. Normalizing here keeps every consumer one-line-safe.
|
|
493
|
+
const reason = entry.reason?.replace(/\s+/g, " ").trim() || undefined;
|
|
494
|
+
for (const task of getTaskTargets(phases, entry, errors)) {
|
|
495
|
+
// Only actionable open work can be blocked: blocking a phase must not
|
|
496
|
+
// reopen completed/abandoned tasks or erase finished progress. An
|
|
497
|
+
// already-blocked task stays eligible so a later block can refine its
|
|
498
|
+
// blocker note (e.g. first blocked without a reason, then with one).
|
|
499
|
+
if (task.status !== "pending" && task.status !== "in_progress" && task.status !== "blocked") continue;
|
|
500
|
+
task.status = "blocked";
|
|
501
|
+
task.blocker = reason;
|
|
502
|
+
}
|
|
503
|
+
return phases;
|
|
504
|
+
}
|
|
505
|
+
case "unblock": {
|
|
506
|
+
if (!entry.task && !entry.phase) {
|
|
507
|
+
errors.push("unblock requires a task or phase target");
|
|
508
|
+
return phases;
|
|
509
|
+
}
|
|
510
|
+
for (const task of getTaskTargets(phases, entry, errors)) {
|
|
511
|
+
if (task.status === "blocked") {
|
|
512
|
+
task.status = "pending";
|
|
513
|
+
task.blocker = undefined;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
return phases;
|
|
517
|
+
}
|
|
518
|
+
case "rm":
|
|
519
|
+
return removeTasks(phases, entry, errors);
|
|
520
|
+
case "append":
|
|
521
|
+
return appendItems(phases, entry, errors);
|
|
522
|
+
case "view":
|
|
523
|
+
return phases;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* Infer a missing `op` from the raw argument shape. Only unambiguous shapes
|
|
529
|
+
* are inferred:
|
|
530
|
+
* - `list` → `init` (list is init-only)
|
|
531
|
+
* - `items` + `phase` → `append` (lazily creates the phase, so the result
|
|
532
|
+
* matches a single-phase init when nothing exists yet)
|
|
533
|
+
* - bare `items` with no existing todos → `init` (nothing to overwrite)
|
|
534
|
+
* Targeting args alone (`task`/`phase`) map to several ops and stay an error.
|
|
535
|
+
*/
|
|
536
|
+
function inferTodoOp(args: Record<string, unknown>, hasExistingPhases: boolean): TodoOperation | undefined {
|
|
537
|
+
if (Array.isArray(args.list) && args.list.length > 0) return "init";
|
|
538
|
+
if (Array.isArray(args.items) && args.items.length > 0) {
|
|
539
|
+
if (typeof args.phase === "string" && args.phase) return "append";
|
|
540
|
+
if (!hasExistingPhases) return "init";
|
|
541
|
+
}
|
|
542
|
+
return undefined;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
/**
|
|
546
|
+
* Validate execute-time arguments, repairing an omitted `op`. The tool sets
|
|
547
|
+
* `lenientArgValidation`, so the agent loop hands `execute()` the raw
|
|
548
|
+
* arguments when schema validation fails; the only failure repaired here is
|
|
549
|
+
* a missing `op` alongside an unambiguous payload (models routinely send
|
|
550
|
+
* `{list:[...]}` with no op). Anything else returns the schema error text
|
|
551
|
+
* for a normal model retry.
|
|
552
|
+
*/
|
|
553
|
+
function resolveTodoParams(raw: unknown, hasExistingPhases: boolean): TodoOpEntryValue | string {
|
|
554
|
+
const direct = todoSchema(raw);
|
|
555
|
+
if (!(direct instanceof type.errors)) return direct;
|
|
556
|
+
if (isRecord(raw) && raw.op === undefined) {
|
|
557
|
+
const inferred = inferTodoOp(raw, hasExistingPhases);
|
|
558
|
+
if (inferred) {
|
|
559
|
+
const repaired = todoSchema({ ...raw, op: inferred });
|
|
560
|
+
if (!(repaired instanceof type.errors)) return repaired;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
return `Invalid todo arguments: ${direct.summary}`;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
function applyParams(phases: TodoPhase[], params: TodoOpEntryValue): { phases: TodoPhase[]; errors: string[] } {
|
|
567
|
+
const errors: string[] = [];
|
|
568
|
+
const next = applyEntry(phases, params, errors);
|
|
569
|
+
normalizeInProgressTask(next);
|
|
570
|
+
return { phases: next, errors };
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
/** Apply an array of `todo`-style ops to existing phases. Used by /todo slash command. */
|
|
574
|
+
export function applyOpsToPhases(
|
|
575
|
+
currentPhases: TodoPhase[],
|
|
576
|
+
ops: TodoOpEntryValue[],
|
|
577
|
+
): { phases: TodoPhase[]; errors: string[] } {
|
|
578
|
+
const errors: string[] = [];
|
|
579
|
+
let next = clonePhases(currentPhases);
|
|
580
|
+
for (const op of ops) {
|
|
581
|
+
next = applyEntry(next, op, errors);
|
|
582
|
+
}
|
|
583
|
+
normalizeInProgressTask(next);
|
|
584
|
+
return { phases: next, errors };
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
// =============================================================================
|
|
588
|
+
// Markdown round-trip
|
|
589
|
+
// =============================================================================
|
|
590
|
+
|
|
591
|
+
const STATUS_TO_MARKER: Record<TodoStatus, string> = {
|
|
592
|
+
pending: " ",
|
|
593
|
+
in_progress: "/",
|
|
594
|
+
completed: "x",
|
|
595
|
+
abandoned: "-",
|
|
596
|
+
blocked: "!",
|
|
597
|
+
};
|
|
598
|
+
|
|
599
|
+
export function resolveTodoMarkdownPath(input: string, cwd: string): string {
|
|
600
|
+
const raw = normalizePathLikeInput(input) || "TODO.md";
|
|
601
|
+
return resolveToCwd(raw, cwd);
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
/** Render todo phases as a Markdown checklist suitable for editing/copying. */
|
|
605
|
+
export function phasesToMarkdown(phases: TodoPhase[]): string {
|
|
606
|
+
if (phases.length === 0) return "# Todos\n";
|
|
607
|
+
const out: string[] = [];
|
|
608
|
+
for (let i = 0; i < phases.length; i++) {
|
|
609
|
+
if (i > 0) out.push("");
|
|
610
|
+
out.push(`# ${phases[i].name}`);
|
|
611
|
+
for (const task of phases[i].tasks) {
|
|
612
|
+
// A blocked task's reason rides in a trailing HTML comment: invisible in
|
|
613
|
+
// rendered markdown, unambiguous to parse back (task content can't
|
|
614
|
+
// contain the comment delimiters), so the note survives `/todo edit` and
|
|
615
|
+
// export/import round-trips.
|
|
616
|
+
const blockerNote = task.status === "blocked" && task.blocker ? ` <!-- blocker: ${task.blocker} -->` : "";
|
|
617
|
+
out.push(`- [${STATUS_TO_MARKER[task.status]}] ${task.content}${blockerNote}`);
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
return `${out.join("\n")}\n`;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
const MARKER_TO_STATUS: Record<string, TodoStatus> = {
|
|
624
|
+
" ": "pending",
|
|
625
|
+
"": "pending",
|
|
626
|
+
x: "completed",
|
|
627
|
+
X: "completed",
|
|
628
|
+
"/": "in_progress",
|
|
629
|
+
">": "in_progress",
|
|
630
|
+
"-": "abandoned",
|
|
631
|
+
"~": "abandoned",
|
|
632
|
+
"!": "blocked",
|
|
633
|
+
};
|
|
634
|
+
|
|
635
|
+
/** Parse a Markdown checklist back into todo phases. */
|
|
636
|
+
export function markdownToPhases(md: string): { phases: TodoPhase[]; errors: string[] } {
|
|
637
|
+
const errors: string[] = [];
|
|
638
|
+
const phases: TodoPhase[] = [];
|
|
639
|
+
let currentPhase: TodoPhase | undefined;
|
|
640
|
+
|
|
641
|
+
const lines = md.split(/\r?\n/);
|
|
642
|
+
for (let lineNum = 0; lineNum < lines.length; lineNum++) {
|
|
643
|
+
const raw = lines[lineNum];
|
|
644
|
+
|
|
645
|
+
const trimmed = raw.trim();
|
|
646
|
+
if (!trimmed) continue;
|
|
647
|
+
|
|
648
|
+
const headingMatch = /^#{1,6}\s+(.+?)\s*$/.exec(trimmed);
|
|
649
|
+
if (headingMatch) {
|
|
650
|
+
currentPhase = { name: headingMatch[1].trim(), tasks: [] };
|
|
651
|
+
phases.push(currentPhase);
|
|
652
|
+
continue;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
const taskMatch = /^[-*+]\s*\[(.?)\]\s+(.+?)\s*$/.exec(trimmed);
|
|
656
|
+
if (taskMatch) {
|
|
657
|
+
if (!currentPhase) {
|
|
658
|
+
currentPhase = { name: "Todos", tasks: [] };
|
|
659
|
+
phases.push(currentPhase);
|
|
660
|
+
}
|
|
661
|
+
const marker = taskMatch[1];
|
|
662
|
+
const status = MARKER_TO_STATUS[marker];
|
|
663
|
+
if (!status) {
|
|
664
|
+
errors.push(`Line ${lineNum + 1}: unknown status marker "[${marker}]" (use [ ], [x], [/], [-], [!])`);
|
|
665
|
+
continue;
|
|
666
|
+
}
|
|
667
|
+
// Recover a blocked task's reason from its trailing HTML comment (see
|
|
668
|
+
// phasesToMarkdown), then strip the comment from the visible content.
|
|
669
|
+
const rawContent = taskMatch[2].trim();
|
|
670
|
+
const blockerMatch = /^(.*?)\s*<!--\s*blocker:\s*(.*?)\s*-->$/.exec(rawContent);
|
|
671
|
+
if (status === "blocked" && blockerMatch) {
|
|
672
|
+
currentPhase.tasks.push({ content: blockerMatch[1].trim(), status, blocker: blockerMatch[2].trim() });
|
|
673
|
+
} else {
|
|
674
|
+
currentPhase.tasks.push({ content: rawContent, status });
|
|
675
|
+
}
|
|
676
|
+
continue;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
errors.push(`Line ${lineNum + 1}: unrecognized syntax "${trimmed}"`);
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
normalizeInProgressTask(phases);
|
|
683
|
+
return { phases, errors };
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
function formatSummary(phases: TodoPhase[], errors: string[], readOnly = false): string {
|
|
687
|
+
const tasks = phases.flatMap(phase => phase.tasks);
|
|
688
|
+
if (tasks.length === 0) {
|
|
689
|
+
if (errors.length > 0) return `Errors: ${errors.join("; ")}`;
|
|
690
|
+
return readOnly ? "Todo list is empty." : "Todo list cleared.";
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
const remainingByPhase = phases
|
|
694
|
+
.map(phase => ({
|
|
695
|
+
name: phase.name,
|
|
696
|
+
tasks: phase.tasks.filter(task => task.status === "pending" || task.status === "in_progress"),
|
|
697
|
+
}))
|
|
698
|
+
.filter(phase => phase.tasks.length > 0);
|
|
699
|
+
const remainingTasks = remainingByPhase.flatMap(phase => phase.tasks.map(task => ({ ...task, phase: phase.name })));
|
|
700
|
+
|
|
701
|
+
let currentIdx = phases.findIndex(phase =>
|
|
702
|
+
phase.tasks.some(task => task.status === "pending" || task.status === "in_progress"),
|
|
703
|
+
);
|
|
704
|
+
if (currentIdx === -1) currentIdx = phases.length - 1;
|
|
705
|
+
const current = phases[currentIdx];
|
|
706
|
+
const done = current.tasks.filter(task => task.status === "completed" || task.status === "abandoned").length;
|
|
707
|
+
|
|
708
|
+
const lines: string[] = [];
|
|
709
|
+
if (errors.length > 0) lines.push(`Errors: ${errors.join("; ")}`);
|
|
710
|
+
if (remainingTasks.length === 0) {
|
|
711
|
+
lines.push("Remaining items: none.");
|
|
712
|
+
} else {
|
|
713
|
+
lines.push(`Remaining items (${remainingTasks.length}):`);
|
|
714
|
+
for (const task of remainingTasks) {
|
|
715
|
+
lines.push(` - ${task.content} [${task.status}] (${task.phase})`);
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
// Closed = completed + abandoned, mirroring the per-phase `done` count.
|
|
719
|
+
const closedAll = tasks.filter(task => task.status === "completed" || task.status === "abandoned").length;
|
|
720
|
+
const blockedAll = tasks.filter(task => task.status === "blocked").length;
|
|
721
|
+
// The active phase is the EARLIEST one still holding open work, so the
|
|
722
|
+
// in-progress pointer can sit in a phase whose successors already have
|
|
723
|
+
// completed tasks. Detect that "worked ahead" case to explain the
|
|
724
|
+
// otherwise-surprising backward pointer instead of letting it read as a
|
|
725
|
+
// completed task reverting to pending.
|
|
726
|
+
const workedAhead = phases.some(
|
|
727
|
+
(phase, idx) =>
|
|
728
|
+
idx > currentIdx && phase.tasks.some(task => task.status === "completed" || task.status === "abandoned"),
|
|
729
|
+
);
|
|
730
|
+
lines.push(
|
|
731
|
+
`Overall: ${closedAll}/${tasks.length} done, ${remainingTasks.length} open${blockedAll > 0 ? `, ${blockedAll} blocked` : ""}.`,
|
|
732
|
+
);
|
|
733
|
+
lines.push(
|
|
734
|
+
`Active phase ${currentIdx + 1}/${phases.length} "${current.name}" (${done}/${current.tasks.length})${
|
|
735
|
+
workedAhead
|
|
736
|
+
? " — earliest phase with open tasks; the in-progress pointer auto-advances to the earliest open task on each completion, so it can sit behind out-of-order work (nothing was un-completed)."
|
|
737
|
+
: "."
|
|
738
|
+
}`,
|
|
739
|
+
);
|
|
740
|
+
for (const phase of phases) {
|
|
741
|
+
lines.push(` ${phase.name}:`);
|
|
742
|
+
for (const task of phase.tasks) {
|
|
743
|
+
const checkbox = task.status === "completed" ? "[X]" : "[ ]";
|
|
744
|
+
const tag =
|
|
745
|
+
task.status === "in_progress"
|
|
746
|
+
? " (in progress)"
|
|
747
|
+
: task.status === "abandoned"
|
|
748
|
+
? " (dropped)"
|
|
749
|
+
: task.status === "blocked"
|
|
750
|
+
? task.blocker
|
|
751
|
+
? ` (blocked: ${task.blocker})`
|
|
752
|
+
: " (blocked)"
|
|
753
|
+
: "";
|
|
754
|
+
lines.push(` - ${checkbox} ${task.content}${tag}`);
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
return lines.join("\n");
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
// =============================================================================
|
|
761
|
+
// Tool Class
|
|
762
|
+
// =============================================================================
|
|
763
|
+
|
|
764
|
+
export class TodoTool implements AgentTool<typeof todoSchema, TodoToolDetails> {
|
|
765
|
+
readonly name = "todo";
|
|
766
|
+
readonly approval = "read" as const;
|
|
767
|
+
readonly label = "Todo";
|
|
768
|
+
readonly summary = "Write a structured todo list to track progress within a session";
|
|
769
|
+
readonly description: string;
|
|
770
|
+
readonly parameters = todoSchema;
|
|
771
|
+
readonly concurrency = "exclusive";
|
|
772
|
+
readonly strict = true;
|
|
773
|
+
// Raw args reach execute() on schema failure; resolveTodoParams re-validates
|
|
774
|
+
// and repairs the one recoverable shape (missing `op`, unambiguous payload).
|
|
775
|
+
readonly lenientArgValidation = true;
|
|
776
|
+
|
|
777
|
+
readonly examples: readonly ToolExample<typeof todoSchema.infer>[] = [
|
|
778
|
+
{
|
|
779
|
+
caption: "Initial setup (multi-phase)",
|
|
780
|
+
call: {
|
|
781
|
+
op: "init",
|
|
782
|
+
list: [
|
|
783
|
+
{ phase: "Foundation", items: ["Scaffold crate", "Wire workspace"] },
|
|
784
|
+
{ phase: "Auth", items: ["Port credential store", "Wire OAuth providers"] },
|
|
785
|
+
{ phase: "Verification", items: ["Run cargo test"] },
|
|
786
|
+
],
|
|
787
|
+
},
|
|
788
|
+
},
|
|
789
|
+
{
|
|
790
|
+
caption: "View current state (read-only)",
|
|
791
|
+
call: { op: "view" },
|
|
792
|
+
},
|
|
793
|
+
{
|
|
794
|
+
caption: "Initial setup (single phase)",
|
|
795
|
+
call: {
|
|
796
|
+
op: "init",
|
|
797
|
+
list: [{ phase: "Implementation", items: ["Apply fix", "Run tests"] }],
|
|
798
|
+
},
|
|
799
|
+
},
|
|
800
|
+
{
|
|
801
|
+
caption: "Complete one task",
|
|
802
|
+
call: { op: "done", task: "Wire workspace" },
|
|
803
|
+
},
|
|
804
|
+
{
|
|
805
|
+
caption: "Complete a whole phase",
|
|
806
|
+
call: { op: "done", phase: "Auth" },
|
|
807
|
+
},
|
|
808
|
+
{
|
|
809
|
+
caption: "Remove all tasks",
|
|
810
|
+
call: { op: "rm" },
|
|
811
|
+
},
|
|
812
|
+
{
|
|
813
|
+
caption: "Drop one task",
|
|
814
|
+
call: { op: "drop", task: "Run cargo test" },
|
|
815
|
+
},
|
|
816
|
+
{
|
|
817
|
+
caption: "Append tasks to a phase",
|
|
818
|
+
call: { op: "append", phase: "Auth", items: ["Handle retries", "Run tests"] },
|
|
819
|
+
},
|
|
820
|
+
];
|
|
821
|
+
readonly loadMode = "discoverable";
|
|
822
|
+
constructor(private readonly session: ToolSession) {
|
|
823
|
+
this.description = prompt.render(todoDescription);
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
async execute(
|
|
827
|
+
_toolCallId: string,
|
|
828
|
+
params: TodoParams,
|
|
829
|
+
_signal?: AbortSignal,
|
|
830
|
+
_onUpdate?: AgentToolUpdateCallback<TodoToolDetails>,
|
|
831
|
+
_context?: AgentToolContext,
|
|
832
|
+
): Promise<AgentToolResult<TodoToolDetails>> {
|
|
833
|
+
const previousPhases = clonePhases(this.session.getTodoPhases?.() ?? []);
|
|
834
|
+
const storage = this.session.getSessionFile() ? "session" : "memory";
|
|
835
|
+
const resolved = resolveTodoParams(params, previousPhases.length > 0);
|
|
836
|
+
if (typeof resolved === "string") {
|
|
837
|
+
return {
|
|
838
|
+
content: [{ type: "text", text: resolved }],
|
|
839
|
+
details: { phases: previousPhases, storage },
|
|
840
|
+
isError: true,
|
|
841
|
+
};
|
|
842
|
+
}
|
|
843
|
+
const entry = resolved;
|
|
844
|
+
const op = entry.op;
|
|
845
|
+
// Pure-view calls are reads: no normalization, no state write.
|
|
846
|
+
const readOnly = op === "view";
|
|
847
|
+
const { phases: updated, errors } = readOnly
|
|
848
|
+
? { phases: previousPhases, errors: [] as string[] }
|
|
849
|
+
: applyParams(clonePhases(previousPhases), entry);
|
|
850
|
+
// A batch with any error is discarded wholesale: persisting a
|
|
851
|
+
// half-applied batch makes the natural retry hit "already exists" for
|
|
852
|
+
// the ops that did land. State and rendered summary stay at previous.
|
|
853
|
+
const failed = errors.length > 0;
|
|
854
|
+
const effective = failed ? previousPhases : updated;
|
|
855
|
+
const completedTasks = readOnly || failed ? [] : getCompletionTransitions(previousPhases, updated);
|
|
856
|
+
if (!readOnly && !failed) this.session.setTodoPhases?.(updated);
|
|
857
|
+
const details: TodoToolDetails = { op, phases: effective, storage };
|
|
858
|
+
if (completedTasks.length > 0) details.completedTasks = completedTasks;
|
|
859
|
+
|
|
860
|
+
return {
|
|
861
|
+
content: [{ type: "text", text: formatSummary(effective, errors, readOnly) }],
|
|
862
|
+
details,
|
|
863
|
+
isError: errors.length > 0 ? true : undefined,
|
|
864
|
+
};
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
// =============================================================================
|
|
869
|
+
// TUI Renderer
|
|
870
|
+
// =============================================================================
|
|
871
|
+
|
|
872
|
+
type TodoRenderOp = {
|
|
873
|
+
op?: string;
|
|
874
|
+
task?: string;
|
|
875
|
+
phase?: string;
|
|
876
|
+
items?: string[];
|
|
877
|
+
};
|
|
878
|
+
|
|
879
|
+
/** New single-op shape `{op,...}`; legacy `{ops:[...]}` still seen in old transcripts. */
|
|
880
|
+
type TodoRenderArgs = TodoRenderOp & {
|
|
881
|
+
ops?: TodoRenderOp[];
|
|
882
|
+
};
|
|
883
|
+
|
|
884
|
+
/**
|
|
885
|
+
* Normalize streaming/legacy render args to a flat op list. Accepts the new
|
|
886
|
+
* top-level `{op,...}` shape (returned as a one-element list), the legacy
|
|
887
|
+
* `{ops:[...]}` batch from old transcripts/collab-web, and partially-parsed
|
|
888
|
+
* streaming deltas (non-array `ops`, non-object entries) without crashing.
|
|
889
|
+
*/
|
|
890
|
+
function normalizeTodoArg(args: TodoRenderArgs | undefined): TodoRenderOp[] {
|
|
891
|
+
if (!args || typeof args !== "object") return [];
|
|
892
|
+
if (Array.isArray(args.ops)) {
|
|
893
|
+
return args.ops.filter((entry): entry is TodoRenderOp => !!entry && typeof entry === "object");
|
|
894
|
+
}
|
|
895
|
+
return typeof args.op === "string" ? [args] : [];
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
// =============================================================================
|
|
899
|
+
// Phase numbering (display-only)
|
|
900
|
+
// =============================================================================
|
|
901
|
+
|
|
902
|
+
const ROMAN_PAIRS: Array<[number, string]> = [
|
|
903
|
+
[1000, "M"],
|
|
904
|
+
[900, "CM"],
|
|
905
|
+
[500, "D"],
|
|
906
|
+
[400, "CD"],
|
|
907
|
+
[100, "C"],
|
|
908
|
+
[90, "XC"],
|
|
909
|
+
[50, "L"],
|
|
910
|
+
[40, "XL"],
|
|
911
|
+
[10, "X"],
|
|
912
|
+
[9, "IX"],
|
|
913
|
+
[5, "V"],
|
|
914
|
+
[4, "IV"],
|
|
915
|
+
[1, "I"],
|
|
916
|
+
];
|
|
917
|
+
|
|
918
|
+
/** One-based ASCII roman numeral for display (I, II, III, IV, …). */
|
|
919
|
+
export function phaseRomanNumeral(oneBasedIndex: number): string {
|
|
920
|
+
if (oneBasedIndex <= 0) return "";
|
|
921
|
+
let out = "";
|
|
922
|
+
let rem = oneBasedIndex;
|
|
923
|
+
for (const [value, sym] of ROMAN_PAIRS) {
|
|
924
|
+
while (rem >= value) {
|
|
925
|
+
out += sym;
|
|
926
|
+
rem -= value;
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
return out;
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
/**
|
|
933
|
+
* Every render boundary in this file funnels display text through here.
|
|
934
|
+
*
|
|
935
|
+
* `sanitizeText` strips ANSI/C0 sequences but deliberately preserves tabs, and
|
|
936
|
+
* a raw tab punches holes in bordered TUI output, so both are needed. The raw
|
|
937
|
+
* value stays untouched everywhere else: task content and phase names are the
|
|
938
|
+
* identity keys the local list is looked up by, and what gets persisted.
|
|
939
|
+
*/
|
|
940
|
+
function forDisplay(text: string): string {
|
|
941
|
+
return replaceTabs(sanitizeText(text));
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
/**
|
|
945
|
+
* Display-only phase header: `I. Foundation`. State and prompts never see this.
|
|
946
|
+
*
|
|
947
|
+
* Sanitized for the same reason task labels are: this is a render boundary and
|
|
948
|
+
* the name may carry provider or session text holding control sequences. The
|
|
949
|
+
* raw `phase.name` stays the lookup key everywhere else.
|
|
950
|
+
*/
|
|
951
|
+
export function formatPhaseDisplayName(name: string, oneBasedIndex: number): string {
|
|
952
|
+
return `${phaseRomanNumeral(oneBasedIndex)}. ${forDisplay(name)}`;
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
export const TODO_STRIKE_HOLD_FRAMES = 2;
|
|
956
|
+
export const TODO_STRIKE_REVEAL_FRAMES = 12;
|
|
957
|
+
export const TODO_STRIKE_TOTAL_FRAMES = TODO_STRIKE_HOLD_FRAMES + TODO_STRIKE_REVEAL_FRAMES;
|
|
958
|
+
const EMPTY_COMPLETION_KEYS = new Set<string>();
|
|
959
|
+
const STRIKE_START = "\x1b[9m";
|
|
960
|
+
const STRIKE_END = "\x1b[29m";
|
|
961
|
+
|
|
962
|
+
function strikethroughText(text: string): string {
|
|
963
|
+
return `${STRIKE_START}${text}${STRIKE_END}`;
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
function partialStrikethrough(text: string, visibleChars: number): string {
|
|
967
|
+
if (visibleChars <= 0) return text;
|
|
968
|
+
const chars = [...text];
|
|
969
|
+
if (visibleChars >= chars.length) return strikethroughText(text);
|
|
970
|
+
return `${strikethroughText(chars.slice(0, visibleChars).join(""))}${chars.slice(visibleChars).join("")}`;
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
function strikeRevealCount(text: string, frame: number | undefined): number | undefined {
|
|
974
|
+
if (frame === undefined) return undefined;
|
|
975
|
+
if (frame <= TODO_STRIKE_HOLD_FRAMES) return 0;
|
|
976
|
+
const chars = [...text];
|
|
977
|
+
if (chars.length === 0) return undefined;
|
|
978
|
+
const revealFrame = Math.min(frame - TODO_STRIKE_HOLD_FRAMES, TODO_STRIKE_REVEAL_FRAMES);
|
|
979
|
+
return Math.ceil((chars.length * revealFrame) / TODO_STRIKE_REVEAL_FRAMES);
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
function formatTodoLine(
|
|
983
|
+
item: TodoItem,
|
|
984
|
+
uiTheme: Theme,
|
|
985
|
+
prefix: string,
|
|
986
|
+
completionKeys: Set<string>,
|
|
987
|
+
frame: number | undefined,
|
|
988
|
+
matched = false,
|
|
989
|
+
): string {
|
|
990
|
+
const checkbox = uiTheme.checkbox;
|
|
991
|
+
// Sanitize only for display. A mirrored Cursor snapshot carries provider text
|
|
992
|
+
// verbatim, and a label holding ANSI/C0 sequences would otherwise rewrite the
|
|
993
|
+
// terminal every time the list renders or replays. `item.content` stays raw
|
|
994
|
+
// everywhere else: it is the identity key the local list is looked up by
|
|
995
|
+
// (`findTaskByContent`) and what gets persisted.
|
|
996
|
+
const label = forDisplay(item.content);
|
|
997
|
+
switch (item.status) {
|
|
998
|
+
case "completed": {
|
|
999
|
+
const revealCount = completionKeys.has(item.content) ? strikeRevealCount(label, frame) : undefined;
|
|
1000
|
+
const content =
|
|
1001
|
+
revealCount === undefined ? strikethroughText(label) : partialStrikethrough(label, revealCount);
|
|
1002
|
+
return uiTheme.fg("success", `${prefix}${checkbox.checked} ${content}`);
|
|
1003
|
+
}
|
|
1004
|
+
case "in_progress":
|
|
1005
|
+
return uiTheme.fg("accent", `${prefix}${checkbox.unchecked} ${label}`);
|
|
1006
|
+
case "abandoned":
|
|
1007
|
+
return uiTheme.fg("error", `${prefix}${checkbox.unchecked} ${strikethroughText(label)}`);
|
|
1008
|
+
case "blocked": {
|
|
1009
|
+
const note = item.blocker ? `blocked: ${forDisplay(item.blocker)}` : "blocked";
|
|
1010
|
+
return uiTheme.fg("warning", `${prefix}${checkbox.unchecked} ${label} (${note})`);
|
|
1011
|
+
}
|
|
1012
|
+
default:
|
|
1013
|
+
// A pending todo lit by a live subagent match renders accent, matching
|
|
1014
|
+
// the sticky HUD's convention (#5873).
|
|
1015
|
+
return uiTheme.fg(matched ? "accent" : "dim", `${prefix}${checkbox.unchecked} ${label}`);
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
/**
|
|
1020
|
+
* Phases the latest update touched, plus the active (in_progress) phase.
|
|
1021
|
+
* Returns `null` when there is no usable signal, meaning "render every phase
|
|
1022
|
+
* fully" — this preserves the legacy view and the manual-expand path.
|
|
1023
|
+
*/
|
|
1024
|
+
function computeTouchedPhases(
|
|
1025
|
+
args: TodoRenderArgs | undefined,
|
|
1026
|
+
phases: TodoPhase[],
|
|
1027
|
+
completedTasks: TodoCompletionTransition[],
|
|
1028
|
+
): Set<string> | null {
|
|
1029
|
+
const touched = new Set<string>();
|
|
1030
|
+
// The phase holding the in_progress task is where attention sits after the
|
|
1031
|
+
// auto-promotion that follows every completion.
|
|
1032
|
+
for (const phase of phases) {
|
|
1033
|
+
if (phase.tasks.some(task => task.status === "in_progress")) touched.add(phase.name);
|
|
1034
|
+
}
|
|
1035
|
+
// Phases with a task that just transitioned to completed in this update.
|
|
1036
|
+
for (const transition of completedTasks) touched.add(transition.phase);
|
|
1037
|
+
// Phases explicitly named by the ops that ran. `init` replaces the whole
|
|
1038
|
+
// list, so the entire plan is fresh and every phase counts as touched.
|
|
1039
|
+
const ops = normalizeTodoArg(args);
|
|
1040
|
+
for (const op of ops) {
|
|
1041
|
+
if (!op || typeof op !== "object") continue;
|
|
1042
|
+
if (op.op === "init") {
|
|
1043
|
+
for (const phase of phases) touched.add(phase.name);
|
|
1044
|
+
break;
|
|
1045
|
+
}
|
|
1046
|
+
if (typeof op.phase === "string" && op.phase) {
|
|
1047
|
+
const named = phases.find(phase => phase.name === op.phase);
|
|
1048
|
+
if (named) touched.add(named.name);
|
|
1049
|
+
}
|
|
1050
|
+
if (typeof op.task === "string" && op.task) {
|
|
1051
|
+
const located = findTaskByContent(phases, op.task);
|
|
1052
|
+
if (located) touched.add(located.phase.name);
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
return touched.size > 0 ? touched : null;
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
/** One-line summary for a collapsed (untouched) phase: dim header + progress. */
|
|
1059
|
+
function formatPhaseSummary(phase: TodoPhase, oneBasedIndex: number, uiTheme: Theme): string {
|
|
1060
|
+
const total = phase.tasks.length;
|
|
1061
|
+
const done = phase.tasks.filter(task => task.status === "completed").length;
|
|
1062
|
+
const name = uiTheme.fg("dim", chalk.bold(formatPhaseDisplayName(phase.name, oneBasedIndex)));
|
|
1063
|
+
return `${name}${uiTheme.fg("dim", ` ${done}/${total}`)}`;
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
/**
|
|
1067
|
+
* Live subagent descriptions the transient tool result uses to detect
|
|
1068
|
+
* pending todos being executed by an in-flight subagent, so its collapsed
|
|
1069
|
+
* viewport surfaces the same active work the sticky HUD does (#5873). Wired
|
|
1070
|
+
* once by interactive mode from its observer registry; returns `[]` outside an
|
|
1071
|
+
* interactive session (tests, SDK, transcript rebuilds), where only literal
|
|
1072
|
+
* `in_progress` counts as active.
|
|
1073
|
+
*/
|
|
1074
|
+
let activeTodoDescriptionsProvider: () => readonly string[] = () => [];
|
|
1075
|
+
|
|
1076
|
+
/** Wire the live-subagent description source for {@link todoToolRenderer}. */
|
|
1077
|
+
export function setActiveTodoDescriptionsProvider(provider: () => readonly string[]): void {
|
|
1078
|
+
activeTodoDescriptionsProvider = provider;
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
export const todoToolRenderer = {
|
|
1082
|
+
renderCall(args: TodoRenderArgs, options: RenderResultOptions, uiTheme: Theme): Component {
|
|
1083
|
+
// `args` is the raw partially-parsed JSON from the streaming tool-call
|
|
1084
|
+
// delta and may not satisfy `TodoRenderArgs` at runtime:
|
|
1085
|
+
// `parseStreamingJson` can hand back `{ op: 1 }` mid-delta, or a legacy
|
|
1086
|
+
// `{ ops: "[" }` shape before fields stream. `normalizeTodoArg` guards
|
|
1087
|
+
// both the new single-op and legacy batch shapes so a malformed delta
|
|
1088
|
+
// never breaks the TUI render loop (#2005).
|
|
1089
|
+
const opsList = normalizeTodoArg(args);
|
|
1090
|
+
// Model-authored, partially-streamed strings going straight into a header:
|
|
1091
|
+
// `renderStatusLine` only flattens CR/LF and leaves the rest to the caller.
|
|
1092
|
+
const ops =
|
|
1093
|
+
opsList.length === 0
|
|
1094
|
+
? ["update"]
|
|
1095
|
+
: opsList.map(e => {
|
|
1096
|
+
const parts = [forDisplay(e.op ?? "update")];
|
|
1097
|
+
if (e.task) parts.push(forDisplay(e.task));
|
|
1098
|
+
if (e.phase) parts.push(forDisplay(e.phase));
|
|
1099
|
+
if (Array.isArray(e.items) && e.items.length) {
|
|
1100
|
+
parts.push(`${e.items.length} item${e.items.length === 1 ? "" : "s"}`);
|
|
1101
|
+
}
|
|
1102
|
+
return parts.join(" ");
|
|
1103
|
+
});
|
|
1104
|
+
// No body worth boxing while the call streams — a lone status line reads
|
|
1105
|
+
// cleaner than an empty frame. The container renders it without chrome.
|
|
1106
|
+
const header = renderStatusLine(
|
|
1107
|
+
{ icon: "pending", spinnerFrame: options?.spinnerFrame, title: "Todo", meta: ops },
|
|
1108
|
+
uiTheme,
|
|
1109
|
+
);
|
|
1110
|
+
return new Text(header, 0, 0);
|
|
1111
|
+
},
|
|
1112
|
+
|
|
1113
|
+
renderResult(
|
|
1114
|
+
result: { content: Array<{ type: string; text?: string }>; details?: TodoToolDetails; isError?: boolean },
|
|
1115
|
+
options: RenderResultOptions,
|
|
1116
|
+
uiTheme: Theme,
|
|
1117
|
+
args?: TodoRenderArgs,
|
|
1118
|
+
): Component {
|
|
1119
|
+
if (result.isError) {
|
|
1120
|
+
const errorText = result.content?.find(content => content.type === "text")?.text ?? "Todo operation failed";
|
|
1121
|
+
const header = renderStatusLine({ icon: "error", title: "Todo" }, uiTheme);
|
|
1122
|
+
return framedBlock(uiTheme, width => ({
|
|
1123
|
+
header,
|
|
1124
|
+
sections: [{ lines: formatErrorDetail(errorText, uiTheme).split("\n") }],
|
|
1125
|
+
state: "error",
|
|
1126
|
+
borderColor: "error",
|
|
1127
|
+
width,
|
|
1128
|
+
}));
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
const phases = (result.details?.phases ?? []).filter(phase => phase.tasks.length > 0);
|
|
1132
|
+
const completedTasks = result.details?.completedTasks ?? [];
|
|
1133
|
+
const completionKeysByPhase = new Map<string, Set<string>>();
|
|
1134
|
+
for (const task of completedTasks) {
|
|
1135
|
+
let keys = completionKeysByPhase.get(task.phase);
|
|
1136
|
+
if (!keys) {
|
|
1137
|
+
keys = new Set<string>();
|
|
1138
|
+
completionKeysByPhase.set(task.phase, keys);
|
|
1139
|
+
}
|
|
1140
|
+
keys.add(task.content);
|
|
1141
|
+
}
|
|
1142
|
+
const allTasks = phases.flatMap(phase => phase.tasks);
|
|
1143
|
+
const header = renderStatusLine(
|
|
1144
|
+
{
|
|
1145
|
+
iconOverride: uiTheme.styledSymbol("tool.todo", "accent"),
|
|
1146
|
+
title: "Todo",
|
|
1147
|
+
meta: [`${allTasks.length} tasks`],
|
|
1148
|
+
},
|
|
1149
|
+
uiTheme,
|
|
1150
|
+
);
|
|
1151
|
+
if (allTasks.length === 0) {
|
|
1152
|
+
// Provider text on the Cursor path (the todo summary or a refusal note),
|
|
1153
|
+
// so sanitize like every other label. The error branch above already
|
|
1154
|
+
// goes through `formatErrorDetail`.
|
|
1155
|
+
const fallback = forDisplay(result.content?.find(content => content.type === "text")?.text ?? "No todos");
|
|
1156
|
+
return new Text(`${header}\n ${uiTheme.fg("dim", fallback)}`, 0, 0);
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
return framedBlock(uiTheme, width => {
|
|
1160
|
+
const { expanded, spinnerFrame } = options;
|
|
1161
|
+
const multiPhase = phases.length > 1;
|
|
1162
|
+
const indent = multiPhase ? " " : "";
|
|
1163
|
+
// Collapse phases this update didn't touch down to a one-line summary so
|
|
1164
|
+
// a single task flip doesn't redraw every phase's full task list. The
|
|
1165
|
+
// manual expand toggle (and the no-signal fallback) still shows all.
|
|
1166
|
+
const touched = expanded || !multiPhase ? null : computeTouchedPhases(args, phases, completedTasks);
|
|
1167
|
+
// A pending todo counts as active work when an in-flight subagent is
|
|
1168
|
+
// executing it — the transient result surfaces the same active set the
|
|
1169
|
+
// sticky HUD does (#5873). Empty outside an interactive session.
|
|
1170
|
+
const activeDescs = expanded ? [] : activeTodoDescriptionsProvider();
|
|
1171
|
+
const isMatched = (task: TodoItem): boolean =>
|
|
1172
|
+
activeDescs.length > 0 && todoMatchesAnyDescription(task.content, activeDescs);
|
|
1173
|
+
const bodyLines: string[] = [];
|
|
1174
|
+
for (let p = 0; p < phases.length; p++) {
|
|
1175
|
+
const phase = phases[p];
|
|
1176
|
+
if (touched && !touched.has(phase.name)) {
|
|
1177
|
+
bodyLines.push(formatPhaseSummary(phase, p + 1, uiTheme));
|
|
1178
|
+
continue;
|
|
1179
|
+
}
|
|
1180
|
+
if (multiPhase) {
|
|
1181
|
+
bodyLines.push(uiTheme.fg("accent", chalk.bold(formatPhaseDisplayName(phase.name, p + 1))));
|
|
1182
|
+
}
|
|
1183
|
+
const completionKeys = completionKeysByPhase.get(phase.name) ?? EMPTY_COMPLETION_KEYS;
|
|
1184
|
+
// Collapsed: walking viewport — completed/abandoned omitted, active
|
|
1185
|
+
// work (in-progress / subagent-matched) pulled to the head, then
|
|
1186
|
+
// following pending tasks (#5873). Expanded: every task in order.
|
|
1187
|
+
const treeLines = expanded
|
|
1188
|
+
? renderTreeList(
|
|
1189
|
+
{
|
|
1190
|
+
items: phase.tasks,
|
|
1191
|
+
expanded,
|
|
1192
|
+
itemType: "todo",
|
|
1193
|
+
renderItem: todo => formatTodoLine(todo, uiTheme, "", completionKeys, spinnerFrame),
|
|
1194
|
+
},
|
|
1195
|
+
uiTheme,
|
|
1196
|
+
)
|
|
1197
|
+
: (() => {
|
|
1198
|
+
const selection = selectCollapsedTodos(phase.tasks, isMatched, PREVIEW_LIMITS.COLLAPSED_ITEMS);
|
|
1199
|
+
return renderTreeList(
|
|
1200
|
+
{
|
|
1201
|
+
items: selection.items,
|
|
1202
|
+
itemType: "todo",
|
|
1203
|
+
trailingSummary: selection.summary,
|
|
1204
|
+
renderItem: todo =>
|
|
1205
|
+
formatTodoLine(todo, uiTheme, "", completionKeys, spinnerFrame, isMatched(todo)),
|
|
1206
|
+
},
|
|
1207
|
+
uiTheme,
|
|
1208
|
+
);
|
|
1209
|
+
})();
|
|
1210
|
+
for (const line of treeLines) {
|
|
1211
|
+
bodyLines.push(`${indent}${line}`);
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
while (bodyLines.length > 0 && bodyLines[0].trim() === "") bodyLines.shift();
|
|
1215
|
+
return {
|
|
1216
|
+
header,
|
|
1217
|
+
sections: bodyLines.length > 0 ? [{ lines: bodyLines }] : [],
|
|
1218
|
+
state: options.isPartial ? "pending" : "success",
|
|
1219
|
+
borderColor: "borderMuted",
|
|
1220
|
+
applyBg: false,
|
|
1221
|
+
width,
|
|
1222
|
+
};
|
|
1223
|
+
});
|
|
1224
|
+
},
|
|
1225
|
+
mergeCallAndResult: true,
|
|
1226
|
+
};
|