@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,1684 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vibe mode worker-session runtime.
|
|
3
|
+
*
|
|
4
|
+
* Owns the persistent, addressable worker sessions ("CLIs") the vibe director
|
|
5
|
+
* drives. Each worker is a real task-executor subagent with full tool access:
|
|
6
|
+
* spawned once through {@link runSubprocess} (keep-alive), continued
|
|
7
|
+
* turn-by-turn through {@link runSubagentFollowUpTurn}. Between turns the
|
|
8
|
+
* worker lives in the AgentRegistry / AgentLifecycleManager as an adopted idle
|
|
9
|
+
* agent (TTL park + JSONL revive), so its conversation context survives across
|
|
10
|
+
* turns and even across parking.
|
|
11
|
+
*
|
|
12
|
+
* Every turn runs as an AsyncJobManager job, so a completed turn self-delivers
|
|
13
|
+
* into the director's conversation exactly like an async `task` result, and
|
|
14
|
+
* `vibe_wait` can block on the first settling turn with `hub`-wait semantics.
|
|
15
|
+
*/
|
|
16
|
+
import * as fs from "node:fs/promises";
|
|
17
|
+
import * as os from "node:os";
|
|
18
|
+
import * as path from "node:path";
|
|
19
|
+
import { logger, prompt, Snowflake } from "@oh-my-pi/pi-utils";
|
|
20
|
+
import type { AsyncJob, AsyncJobManager } from "../async/job-manager";
|
|
21
|
+
import { resolveAgentModelPatterns } from "../config/model-resolver";
|
|
22
|
+
import type { LocalProtocolOptions } from "../internal-urls";
|
|
23
|
+
import { registerArtifactsDir } from "../internal-urls/registry-helpers";
|
|
24
|
+
import { MCPManager } from "../mcp/manager";
|
|
25
|
+
import vibeTurnResultTemplate from "../prompts/tools/vibe-turn-result.md" with { type: "text" };
|
|
26
|
+
import { AgentLifecycleManager } from "../registry/agent-lifecycle";
|
|
27
|
+
import { type AgentRef, AgentRegistry, MAIN_AGENT_ID } from "../registry/agent-registry";
|
|
28
|
+
import { SessionManager, SessionPersistenceIndeterminateError } from "../session/session-manager";
|
|
29
|
+
import { getBundledAgent } from "../task/agents";
|
|
30
|
+
import { type ExecutorOptions, runSubagentFollowUpTurn, runSubprocess } from "../task/executor";
|
|
31
|
+
import { generateTaskName } from "../task/name-generator";
|
|
32
|
+
import { AgentOutputManager } from "../task/output-manager";
|
|
33
|
+
import { type AgentDefinition, type AgentProgress, oneLineLabel, type SingleResult } from "../task/types";
|
|
34
|
+
import type { ToolSession } from "../tools";
|
|
35
|
+
import { formatDuration } from "../tools/render-utils";
|
|
36
|
+
import { ToolError } from "../tools/tool-errors";
|
|
37
|
+
import { calculateTokensPerSecond } from "../utils/token-rate";
|
|
38
|
+
|
|
39
|
+
/** The two worker CLI flavors the director drives. */
|
|
40
|
+
export type VibeCli = "fast" | "good";
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* CLI flavor → bundled agent type. This IS the model-tier mapping: `sonic`
|
|
44
|
+
* carries `model: "@smol"` (the configured fast/low-latency role) and `task`
|
|
45
|
+
* carries `model: "@task"` (inherits the session's strong model).
|
|
46
|
+
* Resolution goes through {@link resolveAgentModelPatterns} exactly like a
|
|
47
|
+
* `task` spawn, so `task.agentModelOverrides` and model-role settings apply.
|
|
48
|
+
*/
|
|
49
|
+
export const VIBE_CLI_AGENT: Record<VibeCli, string> = {
|
|
50
|
+
fast: "sonic",
|
|
51
|
+
good: "task",
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/** Worker session lifecycle as shown to the director. */
|
|
55
|
+
export type VibeSessionState = "starting" | "running" | "idle" | "dead";
|
|
56
|
+
|
|
57
|
+
/** One completed tool call in the per-turn activity trace. */
|
|
58
|
+
interface VibeTraceEntry {
|
|
59
|
+
tool: string;
|
|
60
|
+
args: string;
|
|
61
|
+
endMs: number;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Cap on trace entries retained per turn (the run monitor keeps 5; we widen the window). */
|
|
65
|
+
const TURN_TRACE_CAP = 40;
|
|
66
|
+
/** Cap on a single rendered trace line. */
|
|
67
|
+
const TRACE_LINE_MAX = 120;
|
|
68
|
+
/** Default `vibe_wait` window when no timeout was given (ms). */
|
|
69
|
+
const DEFAULT_WAIT_TIMEOUT_MS = 30_000;
|
|
70
|
+
/** Response text cap inside a delivered turn result; full output stays at agent://<id>. */
|
|
71
|
+
const RESPONSE_PREVIEW_MAX = 6000;
|
|
72
|
+
/** Grace period for Vibe cancellation/release cleanup before teardown detaches (ms). */
|
|
73
|
+
const VIBE_TEARDOWN_GRACE_MS = 5_000;
|
|
74
|
+
|
|
75
|
+
const VIBE_LIFECYCLE_CUSTOM_TYPE = "vibe-session-lifecycle";
|
|
76
|
+
const VIBE_LIFECYCLE_VERSION = 1;
|
|
77
|
+
|
|
78
|
+
export interface VibeOwnerScope {
|
|
79
|
+
ownerId: string;
|
|
80
|
+
parentSessionId: string;
|
|
81
|
+
parentSessionFile: string | null;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export interface VibeParentSession {
|
|
85
|
+
getAgentId?: () => string | null;
|
|
86
|
+
getSessionId?: () => string | null;
|
|
87
|
+
getSessionFile: () => string | null;
|
|
88
|
+
sessionManager?: ToolSession["sessionManager"] &
|
|
89
|
+
Partial<
|
|
90
|
+
Pick<SessionManager, "appendModeChange" | "appendEntriesAtomically" | "recoverPersistenceFromCurrentState">
|
|
91
|
+
>;
|
|
92
|
+
asyncJobManager?: AsyncJobManager;
|
|
93
|
+
settings: ToolSession["settings"];
|
|
94
|
+
getActiveModelString?: () => string | undefined;
|
|
95
|
+
getModelString?: () => string | undefined;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
type VibeTombstoneReason = "explicit-kill" | "mode-exit" | "spawn-failed" | "unrecoverable";
|
|
99
|
+
|
|
100
|
+
interface VibeLifecycleBase {
|
|
101
|
+
version: typeof VIBE_LIFECYCLE_VERSION;
|
|
102
|
+
id: string;
|
|
103
|
+
ownerId: string;
|
|
104
|
+
parentSessionId: string;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
interface VibeSpawnLifecycleEvent extends VibeLifecycleBase {
|
|
108
|
+
action: "spawn";
|
|
109
|
+
cli: VibeCli;
|
|
110
|
+
agent: string;
|
|
111
|
+
childSessionFile: string;
|
|
112
|
+
createdAt: number;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
interface VibeTurnLifecycleEvent extends VibeLifecycleBase {
|
|
116
|
+
action: "turn-started" | "turn-settled";
|
|
117
|
+
turn: number;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
interface VibeTombstoneLifecycleEvent extends VibeLifecycleBase {
|
|
121
|
+
action: "tombstone";
|
|
122
|
+
reason: VibeTombstoneReason;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
interface VibeTombstoneRevocationEvent extends VibeLifecycleBase {
|
|
126
|
+
action: "tombstone-revoked";
|
|
127
|
+
reason: "mode-exit";
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
type VibeLifecycleEvent =
|
|
131
|
+
| VibeSpawnLifecycleEvent
|
|
132
|
+
| VibeTurnLifecycleEvent
|
|
133
|
+
| VibeTombstoneLifecycleEvent
|
|
134
|
+
| VibeTombstoneRevocationEvent;
|
|
135
|
+
|
|
136
|
+
interface VibeRestoreCandidate {
|
|
137
|
+
spawn: VibeSpawnLifecycleEvent;
|
|
138
|
+
turnCount: number;
|
|
139
|
+
lastActivityAt: number;
|
|
140
|
+
inFlight: boolean;
|
|
141
|
+
tombstoneReason?: VibeTombstoneReason;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
interface ResolvedVibeWorker {
|
|
145
|
+
agent: AgentDefinition;
|
|
146
|
+
modelOverride?: string | string[];
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
interface VibeTurn {
|
|
150
|
+
jobId: string;
|
|
151
|
+
message: string;
|
|
152
|
+
startedAt: number;
|
|
153
|
+
/** Trace of tool calls completed during this turn, oldest first. */
|
|
154
|
+
trace: VibeTraceEntry[];
|
|
155
|
+
/** Total completed tool calls (trace may be narrower than this). */
|
|
156
|
+
toolCount: number;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
interface VibeRecord {
|
|
160
|
+
id: string;
|
|
161
|
+
cli: VibeCli;
|
|
162
|
+
ownerId: string;
|
|
163
|
+
parentSessionId: string;
|
|
164
|
+
parentSessionFile: string | null;
|
|
165
|
+
childSessionFile?: string;
|
|
166
|
+
agent: AgentDefinition;
|
|
167
|
+
modelOverride?: string | string[];
|
|
168
|
+
state: VibeSessionState;
|
|
169
|
+
createdAt: number;
|
|
170
|
+
lastActivityAt: number;
|
|
171
|
+
/** One-line gist of the latest activity (intent, tool, or result preview). */
|
|
172
|
+
lastActivity?: string;
|
|
173
|
+
/** Resolved model display string once known. */
|
|
174
|
+
resolvedModel?: string;
|
|
175
|
+
turn?: VibeTurn;
|
|
176
|
+
/** Live view of the in-flight turn (current tool, intent, streamed text tail). */
|
|
177
|
+
live?: {
|
|
178
|
+
currentTool?: string;
|
|
179
|
+
currentToolArgs?: string;
|
|
180
|
+
lastIntent?: string;
|
|
181
|
+
/** Latest streamed assistant text lines, oldest first. */
|
|
182
|
+
outputTail: string[];
|
|
183
|
+
};
|
|
184
|
+
/** Job id of the most recently settled turn (wait snapshots after settle). */
|
|
185
|
+
lastJobId?: string;
|
|
186
|
+
/** Messages queued while a turn was in flight; drained into the next turn. */
|
|
187
|
+
queue: string[];
|
|
188
|
+
turnCount: number;
|
|
189
|
+
killed: boolean;
|
|
190
|
+
/** True while a parent switch is detaching this process-local record without terminating it. */
|
|
191
|
+
suspended: boolean;
|
|
192
|
+
/** True only after a terminal lifecycle event has durably flushed. */
|
|
193
|
+
terminalPersisted: boolean;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Live per-session "screen" for rich rendering: what the worker is doing right
|
|
198
|
+
* now (tool trace, current tool, streamed text tail) plus roster metadata.
|
|
199
|
+
* Every string is already one-line sanitized.
|
|
200
|
+
*/
|
|
201
|
+
export interface VibeScreenSnapshot {
|
|
202
|
+
id: string;
|
|
203
|
+
cli: VibeCli;
|
|
204
|
+
state: VibeSessionState;
|
|
205
|
+
model?: string;
|
|
206
|
+
turns: number;
|
|
207
|
+
queued: number;
|
|
208
|
+
/** Start of the in-flight turn, when running. */
|
|
209
|
+
turnStartedAt?: number;
|
|
210
|
+
/** Gist of the message that started the in-flight turn. */
|
|
211
|
+
turnMessage?: string;
|
|
212
|
+
currentTool?: string;
|
|
213
|
+
currentToolArgs?: string;
|
|
214
|
+
lastIntent?: string;
|
|
215
|
+
/** Completed tool calls of the in-flight turn, oldest first (tail). */
|
|
216
|
+
trace: string[];
|
|
217
|
+
/** Latest streamed worker text lines, oldest first. */
|
|
218
|
+
outputTail: string[];
|
|
219
|
+
lastActivity?: string;
|
|
220
|
+
lastActivityAt: number;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export interface VibeSpawnOutcome {
|
|
224
|
+
id: string;
|
|
225
|
+
jobId: string;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export interface VibeSendOutcome {
|
|
229
|
+
id: string;
|
|
230
|
+
/**
|
|
231
|
+
* - `turn`: a new background turn was started (`jobId` set).
|
|
232
|
+
* - `steered`: worker was mid-turn and streaming; delivered as steering.
|
|
233
|
+
* - `queued`: worker was mid-turn but not steerable; drained into the next turn.
|
|
234
|
+
*/
|
|
235
|
+
mode: "turn" | "steered" | "queued";
|
|
236
|
+
jobId?: string;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export interface VibeKillOutcome {
|
|
240
|
+
id: string;
|
|
241
|
+
/** True when an in-flight turn job was cancelled along the way. */
|
|
242
|
+
cancelledTurn: boolean;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export interface VibeWaitOutcome {
|
|
246
|
+
/** Watched sessions whose snapshotted turn settled during (or before) the wait.
|
|
247
|
+
* May overlap `stillRunning` when a queued follow-up turn already started. */
|
|
248
|
+
settled: Array<{ id: string; jobId: string; status: "completed" | "failed" | "cancelled"; resultText: string }>;
|
|
249
|
+
/** Watched sessions with a turn in flight when the wait returned. */
|
|
250
|
+
stillRunning: string[];
|
|
251
|
+
timedOut: boolean;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
type VibeTeardownStatus = "pending" | "settled" | "failed";
|
|
255
|
+
|
|
256
|
+
interface TrackedVibeTeardown {
|
|
257
|
+
promise: Promise<void>;
|
|
258
|
+
status: () => VibeTeardownStatus;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/** Observe cleanup without propagating a detached late rejection. */
|
|
262
|
+
function trackVibeTeardown(promise: Promise<unknown>, onError: (error: unknown) => void): TrackedVibeTeardown {
|
|
263
|
+
let status: VibeTeardownStatus = "pending";
|
|
264
|
+
return {
|
|
265
|
+
promise: promise.then(
|
|
266
|
+
() => {
|
|
267
|
+
status = "settled";
|
|
268
|
+
},
|
|
269
|
+
error => {
|
|
270
|
+
status = "failed";
|
|
271
|
+
onError(error);
|
|
272
|
+
},
|
|
273
|
+
),
|
|
274
|
+
status: () => status,
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/** Wait for cleanup only until the caller's shared absolute deadline. */
|
|
279
|
+
async function waitForVibeTeardown(tasks: readonly TrackedVibeTeardown[], deadline: number): Promise<boolean> {
|
|
280
|
+
if (tasks.length === 0 || tasks.every(task => task.status() !== "pending")) return true;
|
|
281
|
+
const remainingMs = deadline - Date.now();
|
|
282
|
+
if (remainingMs <= 0) return false;
|
|
283
|
+
const timeout = Promise.withResolvers<void>();
|
|
284
|
+
const timer = setTimeout(timeout.resolve, remainingMs);
|
|
285
|
+
timer.unref?.();
|
|
286
|
+
try {
|
|
287
|
+
return await Promise.race([
|
|
288
|
+
Promise.allSettled(tasks.map(task => task.promise)).then(() => true),
|
|
289
|
+
timeout.promise.then(() => false),
|
|
290
|
+
]);
|
|
291
|
+
} finally {
|
|
292
|
+
clearTimeout(timer);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/** Normalize a text fragment to one bounded roster/trace line. */
|
|
297
|
+
function firstLine(text: string, max = 100): string {
|
|
298
|
+
return oneLineLabel(text, max);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function scopeKey(scope: VibeOwnerScope, id: string): string {
|
|
302
|
+
return `${scope.parentSessionId}\0${scope.parentSessionFile ?? ""}\0${scope.ownerId}\0${id}`;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function matchesScope(record: VibeRecord, scope: VibeOwnerScope): boolean {
|
|
306
|
+
return (
|
|
307
|
+
record.ownerId === scope.ownerId &&
|
|
308
|
+
record.parentSessionId === scope.parentSessionId &&
|
|
309
|
+
record.parentSessionFile === scope.parentSessionFile
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
function objectRecord(value: unknown): Record<string, unknown> | undefined {
|
|
314
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return undefined;
|
|
315
|
+
return value as Record<string, unknown>;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function parseLifecycleEvent(value: unknown): VibeLifecycleEvent | undefined {
|
|
319
|
+
const data = objectRecord(value);
|
|
320
|
+
if (!data || data.version !== VIBE_LIFECYCLE_VERSION) return undefined;
|
|
321
|
+
if (typeof data.id !== "string" || !data.id) return undefined;
|
|
322
|
+
if (typeof data.ownerId !== "string" || !data.ownerId) return undefined;
|
|
323
|
+
if (typeof data.parentSessionId !== "string" || !data.parentSessionId) return undefined;
|
|
324
|
+
const base: VibeLifecycleBase = {
|
|
325
|
+
version: VIBE_LIFECYCLE_VERSION,
|
|
326
|
+
id: data.id,
|
|
327
|
+
ownerId: data.ownerId,
|
|
328
|
+
parentSessionId: data.parentSessionId,
|
|
329
|
+
};
|
|
330
|
+
if (data.action === "spawn") {
|
|
331
|
+
const cli = data.cli === "fast" || data.cli === "good" ? data.cli : undefined;
|
|
332
|
+
if (!cli || typeof data.agent !== "string" || typeof data.childSessionFile !== "string") return undefined;
|
|
333
|
+
if (typeof data.createdAt !== "number" || !Number.isFinite(data.createdAt)) return undefined;
|
|
334
|
+
return {
|
|
335
|
+
...base,
|
|
336
|
+
action: "spawn",
|
|
337
|
+
cli,
|
|
338
|
+
agent: data.agent,
|
|
339
|
+
childSessionFile: data.childSessionFile,
|
|
340
|
+
createdAt: data.createdAt,
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
if (data.action === "turn-started" || data.action === "turn-settled") {
|
|
344
|
+
if (typeof data.turn !== "number" || !Number.isInteger(data.turn) || data.turn < 1) return undefined;
|
|
345
|
+
return { ...base, action: data.action, turn: data.turn };
|
|
346
|
+
}
|
|
347
|
+
if (data.action === "tombstone") {
|
|
348
|
+
const reason = data.reason;
|
|
349
|
+
if (
|
|
350
|
+
reason !== "explicit-kill" &&
|
|
351
|
+
reason !== "mode-exit" &&
|
|
352
|
+
reason !== "spawn-failed" &&
|
|
353
|
+
reason !== "unrecoverable"
|
|
354
|
+
) {
|
|
355
|
+
return undefined;
|
|
356
|
+
}
|
|
357
|
+
return { ...base, action: "tombstone", reason };
|
|
358
|
+
}
|
|
359
|
+
if (data.action === "tombstone-revoked" && data.reason === "mode-exit") {
|
|
360
|
+
return { ...base, action: "tombstone-revoked", reason: "mode-exit" };
|
|
361
|
+
}
|
|
362
|
+
return undefined;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/** Child ids claimed by valid Vibe spawn records from untrusted persisted JSON. */
|
|
366
|
+
export function persistedVibeChildIds(entries: Iterable<unknown>): Set<string> {
|
|
367
|
+
const ids = new Set<string>();
|
|
368
|
+
for (const value of entries) {
|
|
369
|
+
const entry = objectRecord(value);
|
|
370
|
+
if (entry?.type !== "custom" || entry.customType !== VIBE_LIFECYCLE_CUSTOM_TYPE) continue;
|
|
371
|
+
const event = parseLifecycleEvent(entry.data);
|
|
372
|
+
if (
|
|
373
|
+
event?.action === "spawn" &&
|
|
374
|
+
/^[A-Za-z0-9_-]+$/.test(event.id) &&
|
|
375
|
+
event.childSessionFile === `${event.id}.jsonl`
|
|
376
|
+
) {
|
|
377
|
+
ids.add(event.id);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
return ids;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/** Merge the monitor's rolling `recentTools` window (newest first) into the per-turn trace (oldest first). */
|
|
384
|
+
function mergeTrace(turn: VibeTurn, progress: AgentProgress): void {
|
|
385
|
+
turn.toolCount = progress.toolCount;
|
|
386
|
+
for (let i = progress.recentTools.length - 1; i >= 0; i--) {
|
|
387
|
+
const entry = progress.recentTools[i];
|
|
388
|
+
if (turn.trace.some(seen => seen.endMs === entry.endMs && seen.tool === entry.tool && seen.args === entry.args)) {
|
|
389
|
+
continue;
|
|
390
|
+
}
|
|
391
|
+
turn.trace.push({ tool: entry.tool, args: entry.args, endMs: entry.endMs });
|
|
392
|
+
if (turn.trace.length > TURN_TRACE_CAP) turn.trace.shift();
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/** Thrown from a turn job body so the job manager marks the job failed while carrying the formatted result. */
|
|
397
|
+
export class VibeTurnError extends Error {}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Process-global registry of vibe worker sessions, scoped by both owner agent
|
|
401
|
+
* id and stable parent session id. Persisted lifecycle events rebuild idle
|
|
402
|
+
* records after a process restart; live turn jobs remain process-local.
|
|
403
|
+
*/
|
|
404
|
+
export class VibeSessionRegistry {
|
|
405
|
+
static #global: VibeSessionRegistry | undefined;
|
|
406
|
+
|
|
407
|
+
static global(): VibeSessionRegistry {
|
|
408
|
+
if (!VibeSessionRegistry.#global) {
|
|
409
|
+
VibeSessionRegistry.#global = new VibeSessionRegistry();
|
|
410
|
+
}
|
|
411
|
+
return VibeSessionRegistry.#global;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/** Reset the global registry. Test-only. */
|
|
415
|
+
static resetGlobalForTests(): void {
|
|
416
|
+
VibeSessionRegistry.#global = undefined;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Insert a bare worker record without the spawn/job machinery. Test-only —
|
|
421
|
+
* lets {@link aggregateVibeWorkerTokensPerSecond} be exercised against a
|
|
422
|
+
* fake roster + AgentRegistry session without driving a real turn.
|
|
423
|
+
*/
|
|
424
|
+
registerRecordForTests(record: { id: string; cli?: VibeCli; ownerId: string; state?: VibeSessionState }): void {
|
|
425
|
+
this.#records.set(record.id, {
|
|
426
|
+
id: record.id,
|
|
427
|
+
cli: record.cli ?? "fast",
|
|
428
|
+
ownerId: record.ownerId,
|
|
429
|
+
parentSessionId: "test-parent-session",
|
|
430
|
+
parentSessionFile: null,
|
|
431
|
+
agent: getBundledAgent("sonic")!,
|
|
432
|
+
state: record.state ?? "running",
|
|
433
|
+
createdAt: Date.now(),
|
|
434
|
+
lastActivityAt: Date.now(),
|
|
435
|
+
queue: [],
|
|
436
|
+
turnCount: 0,
|
|
437
|
+
killed: false,
|
|
438
|
+
suspended: false,
|
|
439
|
+
terminalPersisted: false,
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
readonly #records = new Map<string, VibeRecord>();
|
|
444
|
+
readonly #terminationTails = new Map<string, Promise<void>>();
|
|
445
|
+
readonly #terminatedScopes = new Set<string>();
|
|
446
|
+
#teardownGraceMs = VIBE_TEARDOWN_GRACE_MS;
|
|
447
|
+
|
|
448
|
+
/** Override the teardown grace period for deterministic lifecycle tests. */
|
|
449
|
+
setTeardownGraceForTesting(timeoutMs: number): void {
|
|
450
|
+
this.#teardownGraceMs = Math.max(1, timeoutMs);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
ownerScope(session: VibeParentSession): VibeOwnerScope {
|
|
454
|
+
const parentSessionId = session.getSessionId?.();
|
|
455
|
+
if (!parentSessionId) {
|
|
456
|
+
throw new ToolError("Vibe sessions require a stable parent session id.");
|
|
457
|
+
}
|
|
458
|
+
const parentSessionFile = session.getSessionFile();
|
|
459
|
+
return {
|
|
460
|
+
ownerId: session.getAgentId?.() ?? MAIN_AGENT_ID,
|
|
461
|
+
parentSessionId,
|
|
462
|
+
parentSessionFile: parentSessionFile ? path.resolve(parentSessionFile) : null,
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/** Re-open spawn admission after an explicit Vibe-mode entry. */
|
|
467
|
+
activateScope(scope: VibeOwnerScope): void {
|
|
468
|
+
this.#terminatedScopes.delete(scopeKey(scope, ""));
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
async #withTerminationLock<T>(scope: VibeOwnerScope, operation: () => Promise<T>): Promise<T> {
|
|
472
|
+
const key = scopeKey(scope, "");
|
|
473
|
+
const predecessor = this.#terminationTails.get(key) ?? Promise.resolve();
|
|
474
|
+
const released = Promise.withResolvers<void>();
|
|
475
|
+
const tail = predecessor.then(() => released.promise);
|
|
476
|
+
this.#terminationTails.set(key, tail);
|
|
477
|
+
await predecessor;
|
|
478
|
+
try {
|
|
479
|
+
return await operation();
|
|
480
|
+
} finally {
|
|
481
|
+
released.resolve();
|
|
482
|
+
if (this.#terminationTails.get(key) === tail) this.#terminationTails.delete(key);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
#resolveWorker(session: VibeParentSession, cli: VibeCli): ResolvedVibeWorker {
|
|
487
|
+
const agentName = VIBE_CLI_AGENT[cli];
|
|
488
|
+
const agent = getBundledAgent(agentName);
|
|
489
|
+
if (!agent) {
|
|
490
|
+
throw new ToolError(`Bundled agent "${agentName}" for vibe cli "${cli}" is unavailable.`);
|
|
491
|
+
}
|
|
492
|
+
const agentModelOverrides = session.settings.get("task.agentModelOverrides");
|
|
493
|
+
return {
|
|
494
|
+
agent,
|
|
495
|
+
modelOverride: resolveAgentModelPatterns({
|
|
496
|
+
settingsOverride: agentModelOverrides[agentName],
|
|
497
|
+
agentModel: agent.model,
|
|
498
|
+
settings: session.settings,
|
|
499
|
+
activeModelPattern: session.getActiveModelString?.(),
|
|
500
|
+
fallbackModelPattern: session.getModelString?.(),
|
|
501
|
+
}),
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
async #appendLifecycleEvent(
|
|
506
|
+
session: VibeParentSession,
|
|
507
|
+
event: VibeLifecycleEvent,
|
|
508
|
+
expectedParentSessionFile: string | null,
|
|
509
|
+
): Promise<boolean> {
|
|
510
|
+
if (!expectedParentSessionFile || !session.sessionManager) return false;
|
|
511
|
+
const matchesCurrentScope = (): boolean => {
|
|
512
|
+
const currentSessionFile = session.getSessionFile();
|
|
513
|
+
return (
|
|
514
|
+
session.getSessionId?.() === event.parentSessionId &&
|
|
515
|
+
(session.getAgentId?.() ?? MAIN_AGENT_ID) === event.ownerId &&
|
|
516
|
+
currentSessionFile !== null &&
|
|
517
|
+
path.resolve(currentSessionFile) === expectedParentSessionFile
|
|
518
|
+
);
|
|
519
|
+
};
|
|
520
|
+
if (!matchesCurrentScope()) return false;
|
|
521
|
+
await session.sessionManager.ensureOnDisk();
|
|
522
|
+
if (!matchesCurrentScope()) return false;
|
|
523
|
+
session.sessionManager.appendCustomEntry(VIBE_LIFECYCLE_CUSTOM_TYPE, event);
|
|
524
|
+
await session.sessionManager.flush();
|
|
525
|
+
return true;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
#eventBase(record: VibeRecord): VibeLifecycleBase {
|
|
529
|
+
return {
|
|
530
|
+
version: VIBE_LIFECYCLE_VERSION,
|
|
531
|
+
id: record.id,
|
|
532
|
+
ownerId: record.ownerId,
|
|
533
|
+
parentSessionId: record.parentSessionId,
|
|
534
|
+
};
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
async #appendTombstone(
|
|
538
|
+
session: VibeParentSession,
|
|
539
|
+
record: VibeRecord,
|
|
540
|
+
reason: VibeTombstoneReason,
|
|
541
|
+
): Promise<boolean> {
|
|
542
|
+
return this.#appendLifecycleEvent(
|
|
543
|
+
session,
|
|
544
|
+
{
|
|
545
|
+
...this.#eventBase(record),
|
|
546
|
+
action: "tombstone",
|
|
547
|
+
reason,
|
|
548
|
+
},
|
|
549
|
+
record.parentSessionFile,
|
|
550
|
+
);
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
#hasInMemoryTombstone(session: VibeParentSession, record: VibeRecord): boolean {
|
|
554
|
+
let terminalReason: VibeTombstoneReason | undefined;
|
|
555
|
+
for (const entry of session.sessionManager?.getEntries() ?? []) {
|
|
556
|
+
if (entry.type !== "custom" || entry.customType !== VIBE_LIFECYCLE_CUSTOM_TYPE) continue;
|
|
557
|
+
const event = parseLifecycleEvent(entry.data);
|
|
558
|
+
if (
|
|
559
|
+
!event ||
|
|
560
|
+
event.id !== record.id ||
|
|
561
|
+
event.ownerId !== record.ownerId ||
|
|
562
|
+
event.parentSessionId !== record.parentSessionId
|
|
563
|
+
) {
|
|
564
|
+
continue;
|
|
565
|
+
}
|
|
566
|
+
if (event.action === "tombstone") terminalReason = event.reason;
|
|
567
|
+
else if (event.action === "tombstone-revoked" && terminalReason === "mode-exit") terminalReason = undefined;
|
|
568
|
+
}
|
|
569
|
+
return terminalReason !== undefined;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
async #persistModeExit(
|
|
573
|
+
session: VibeParentSession,
|
|
574
|
+
scope: VibeOwnerScope,
|
|
575
|
+
records: readonly VibeRecord[],
|
|
576
|
+
): Promise<void> {
|
|
577
|
+
const pending = records.filter(record => !record.terminalPersisted);
|
|
578
|
+
const sessionManager = session.sessionManager;
|
|
579
|
+
if (!sessionManager) {
|
|
580
|
+
if (pending.some(record => record.childSessionFile)) {
|
|
581
|
+
throw new ToolError("Vibe mode exit cannot persist worker tombstones without the parent session manager.");
|
|
582
|
+
}
|
|
583
|
+
for (const record of pending) record.terminalPersisted = true;
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
const currentScope = this.ownerScope(session);
|
|
587
|
+
if (
|
|
588
|
+
currentScope.ownerId !== scope.ownerId ||
|
|
589
|
+
currentScope.parentSessionId !== scope.parentSessionId ||
|
|
590
|
+
currentScope.parentSessionFile !== scope.parentSessionFile
|
|
591
|
+
) {
|
|
592
|
+
throw new ToolError("Vibe parent session changed before mode exit could be persisted.");
|
|
593
|
+
}
|
|
594
|
+
const parentSessionFile = currentScope.parentSessionFile;
|
|
595
|
+
const persistedPending = pending.filter(record => record.childSessionFile !== undefined);
|
|
596
|
+
for (const record of persistedPending) {
|
|
597
|
+
if (
|
|
598
|
+
!parentSessionFile ||
|
|
599
|
+
path.resolve(parentSessionFile.slice(0, -6), `${record.id}.jsonl`) !== record.childSessionFile
|
|
600
|
+
) {
|
|
601
|
+
throw new ToolError(`Vibe session "${record.id}" changed parent scope before termination.`);
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
const appendEntriesAtomically = sessionManager.appendEntriesAtomically;
|
|
605
|
+
if (!appendEntriesAtomically) {
|
|
606
|
+
throw new ToolError("Vibe mode exit requires atomic parent-session persistence.");
|
|
607
|
+
}
|
|
608
|
+
await appendEntriesAtomically.call(sessionManager, () => {
|
|
609
|
+
for (const record of persistedPending) {
|
|
610
|
+
sessionManager.appendCustomEntry(VIBE_LIFECYCLE_CUSTOM_TYPE, {
|
|
611
|
+
...this.#eventBase(record),
|
|
612
|
+
action: "tombstone",
|
|
613
|
+
reason: "mode-exit",
|
|
614
|
+
});
|
|
615
|
+
}
|
|
616
|
+
sessionManager.appendModeChange?.("none");
|
|
617
|
+
});
|
|
618
|
+
for (const record of pending) record.terminalPersisted = true;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
#manager(session: ToolSession): AsyncJobManager {
|
|
622
|
+
const manager = session.asyncJobManager;
|
|
623
|
+
if (!manager) {
|
|
624
|
+
throw new ToolError("Vibe sessions require async execution (no background job manager is available).");
|
|
625
|
+
}
|
|
626
|
+
return manager;
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
#record(scope: VibeOwnerScope, id: string): VibeRecord {
|
|
630
|
+
const record = this.#records.get(scopeKey(scope, id.trim()));
|
|
631
|
+
if (!record || !matchesScope(record, scope)) {
|
|
632
|
+
const roster = this.#listIds(scope);
|
|
633
|
+
throw new ToolError(
|
|
634
|
+
`Unknown vibe session "${id}".${roster.length > 0 ? ` Active sessions: ${roster.join(", ")}` : " No sessions — spawn one with vibe_spawn."}`,
|
|
635
|
+
);
|
|
636
|
+
}
|
|
637
|
+
return record;
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
#registeredAgent(record: VibeRecord): AgentRef | undefined {
|
|
641
|
+
const ref = AgentRegistry.global().get(record.id);
|
|
642
|
+
if (ref?.kind !== "sub" || ref.parentId !== record.ownerId) return undefined;
|
|
643
|
+
if (record.childSessionFile && ref.sessionFile !== record.childSessionFile) return undefined;
|
|
644
|
+
return ref;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
#listIds(scope: VibeOwnerScope): string[] {
|
|
648
|
+
const ids: string[] = [];
|
|
649
|
+
for (const record of this.#records.values()) {
|
|
650
|
+
if (matchesScope(record, scope) && record.state !== "dead") ids.push(record.id);
|
|
651
|
+
}
|
|
652
|
+
return ids;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
listIds(session: ToolSession): string[] {
|
|
656
|
+
return this.#listIds(this.ownerScope(session));
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
/** Ids of every live worker owned by `ownerId`, across all parent scopes (status-line tok/s aggregation). */
|
|
660
|
+
listIdsByOwner(ownerId: string): string[] {
|
|
661
|
+
const ids: string[] = [];
|
|
662
|
+
for (const record of this.#records.values()) {
|
|
663
|
+
if (record.ownerId === ownerId && record.state !== "dead") ids.push(record.id);
|
|
664
|
+
}
|
|
665
|
+
return ids;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
/**
|
|
669
|
+
* Live screen snapshots for rich rendering (the "TV wall"): one entry per
|
|
670
|
+
* session in creation order, carrying the in-flight turn's trace, current
|
|
671
|
+
* tool, and streamed text tail. All strings are one-line sanitized here so
|
|
672
|
+
* renderers can print them verbatim.
|
|
673
|
+
*/
|
|
674
|
+
screens(session: ToolSession, ids?: string[]): VibeScreenSnapshot[] {
|
|
675
|
+
const scope = this.ownerScope(session);
|
|
676
|
+
const wanted = ids?.length ? new Set(ids.map(id => id.trim())) : undefined;
|
|
677
|
+
const records: VibeRecord[] = [];
|
|
678
|
+
for (const record of this.#records.values()) {
|
|
679
|
+
if (!matchesScope(record, scope)) continue;
|
|
680
|
+
if (wanted && !wanted.has(record.id)) continue;
|
|
681
|
+
records.push(record);
|
|
682
|
+
}
|
|
683
|
+
// Stable TV-wall ordering: spawn order, not activity order.
|
|
684
|
+
records.sort((a, b) => a.createdAt - b.createdAt);
|
|
685
|
+
return records.map(record => ({
|
|
686
|
+
id: record.id,
|
|
687
|
+
cli: record.cli,
|
|
688
|
+
state: record.state,
|
|
689
|
+
model: record.resolvedModel,
|
|
690
|
+
turns: record.turnCount,
|
|
691
|
+
queued: record.queue.length,
|
|
692
|
+
turnStartedAt: record.turn?.startedAt,
|
|
693
|
+
turnMessage: record.turn ? firstLine(record.turn.message, 80) : undefined,
|
|
694
|
+
currentTool: record.live?.currentTool,
|
|
695
|
+
currentToolArgs: record.live?.currentToolArgs ? firstLine(record.live.currentToolArgs, 60) : undefined,
|
|
696
|
+
lastIntent: record.live?.lastIntent ? firstLine(record.live.lastIntent, 80) : undefined,
|
|
697
|
+
trace: record.turn
|
|
698
|
+
? record.turn.trace
|
|
699
|
+
.slice(-6)
|
|
700
|
+
.map(entry => firstLine(`${entry.tool}${entry.args ? `(${entry.args})` : ""}`, TRACE_LINE_MAX))
|
|
701
|
+
: [],
|
|
702
|
+
outputTail: (record.live?.outputTail ?? []).map(line => firstLine(line, 100)),
|
|
703
|
+
lastActivity: record.lastActivity,
|
|
704
|
+
lastActivityAt: record.lastActivityAt,
|
|
705
|
+
}));
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
#persistedIds(session: VibeParentSession, scope: VibeOwnerScope): Set<string> {
|
|
709
|
+
const ids = new Set<string>();
|
|
710
|
+
for (const entry of session.sessionManager?.getEntries() ?? []) {
|
|
711
|
+
if (entry.type !== "custom" || entry.customType !== VIBE_LIFECYCLE_CUSTOM_TYPE) continue;
|
|
712
|
+
const event = parseLifecycleEvent(entry.data);
|
|
713
|
+
if (event?.ownerId === scope.ownerId && event.parentSessionId === scope.parentSessionId) ids.add(event.id);
|
|
714
|
+
}
|
|
715
|
+
for (const record of this.#records.values()) {
|
|
716
|
+
if (matchesScope(record, scope)) ids.add(record.id);
|
|
717
|
+
}
|
|
718
|
+
return ids;
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
async #resolvePersistedChild(
|
|
722
|
+
parentSessionFile: string,
|
|
723
|
+
spawn: VibeSpawnLifecycleEvent,
|
|
724
|
+
options?: { requireAgentMatch?: boolean },
|
|
725
|
+
): Promise<string | undefined> {
|
|
726
|
+
if (options?.requireAgentMatch !== false && spawn.agent !== VIBE_CLI_AGENT[spawn.cli]) return undefined;
|
|
727
|
+
if (!/^[A-Za-z0-9_-]+$/.test(spawn.id) || spawn.childSessionFile !== `${spawn.id}.jsonl`) return undefined;
|
|
728
|
+
const artifactsDir = path.resolve(parentSessionFile.slice(0, -6));
|
|
729
|
+
const childSessionFile = path.resolve(artifactsDir, spawn.childSessionFile);
|
|
730
|
+
const relative = path.relative(artifactsDir, childSessionFile);
|
|
731
|
+
if (!relative || path.isAbsolute(relative) || relative.startsWith(`..${path.sep}`) || relative === "..") {
|
|
732
|
+
return undefined;
|
|
733
|
+
}
|
|
734
|
+
try {
|
|
735
|
+
const persisted = await SessionManager.peekSessionInit(childSessionFile);
|
|
736
|
+
return persisted?.init ? childSessionFile : undefined;
|
|
737
|
+
} catch {
|
|
738
|
+
return undefined;
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
#trackAgentRelease(id: string, ref: AgentRef, action: "detach" | "release"): TrackedVibeTeardown {
|
|
743
|
+
return trackVibeTeardown(AgentLifecycleManager.global().release(id, ref), error => {
|
|
744
|
+
logger.warn(`vibe: failed to ${action} worker session`, {
|
|
745
|
+
id,
|
|
746
|
+
error: error instanceof Error ? error.message : String(error),
|
|
747
|
+
});
|
|
748
|
+
});
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
#finishAgentRelease(id: string, ref: AgentRef, task: TrackedVibeTeardown, action: "detach" | "release"): void {
|
|
752
|
+
if (task.status() === "settled") return;
|
|
753
|
+
if (task.status() === "pending") {
|
|
754
|
+
logger.warn(`vibe: timed out waiting to ${action} worker session; detaching registry ref`, { id });
|
|
755
|
+
}
|
|
756
|
+
AgentRegistry.global().unregister(id, ref);
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
async #releaseRefWithinDeadline(
|
|
760
|
+
id: string,
|
|
761
|
+
ref: AgentRef,
|
|
762
|
+
deadline: number,
|
|
763
|
+
action: "detach" | "release",
|
|
764
|
+
): Promise<void> {
|
|
765
|
+
const task = this.#trackAgentRelease(id, ref, action);
|
|
766
|
+
await waitForVibeTeardown([task], deadline);
|
|
767
|
+
this.#finishAgentRelease(id, ref, task, action);
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
#trackJobSettlement(record: VibeRecord, job: AsyncJob): TrackedVibeTeardown {
|
|
771
|
+
return trackVibeTeardown(job.promise, error => {
|
|
772
|
+
logger.warn("vibe: cancelled worker turn cleanup failed", {
|
|
773
|
+
id: record.id,
|
|
774
|
+
jobId: job.id,
|
|
775
|
+
error: error instanceof Error ? error.message : String(error),
|
|
776
|
+
});
|
|
777
|
+
});
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
async #markTerminalRef(
|
|
781
|
+
id: string,
|
|
782
|
+
ownerId: string,
|
|
783
|
+
childSessionFile: string,
|
|
784
|
+
expected?: AgentRef | null,
|
|
785
|
+
teardownDeadline?: number,
|
|
786
|
+
): Promise<void> {
|
|
787
|
+
const registry = AgentRegistry.global();
|
|
788
|
+
const existing = registry.get(id);
|
|
789
|
+
if (expected !== undefined && existing !== undefined && existing !== expected) return;
|
|
790
|
+
if (
|
|
791
|
+
existing &&
|
|
792
|
+
(existing.kind !== "sub" || existing.parentId !== ownerId || existing.sessionFile !== childSessionFile)
|
|
793
|
+
) {
|
|
794
|
+
return;
|
|
795
|
+
}
|
|
796
|
+
if (existing?.status === "aborted" && !existing.session) return;
|
|
797
|
+
if (existing && !registry.setStatus(id, "aborted", existing)) return;
|
|
798
|
+
if (existing && teardownDeadline !== undefined) {
|
|
799
|
+
await this.#releaseRefWithinDeadline(id, existing, teardownDeadline, "release");
|
|
800
|
+
} else if (existing && AgentLifecycleManager.global().has(id, existing)) {
|
|
801
|
+
await AgentLifecycleManager.global().release(id, existing);
|
|
802
|
+
} else if (existing?.session) {
|
|
803
|
+
await existing.session.dispose();
|
|
804
|
+
}
|
|
805
|
+
const current = registry.get(id);
|
|
806
|
+
if (current && current !== existing) return;
|
|
807
|
+
if (current) registry.unregister(id, current);
|
|
808
|
+
registry.register({
|
|
809
|
+
id,
|
|
810
|
+
displayName: id,
|
|
811
|
+
kind: "sub",
|
|
812
|
+
parentId: ownerId,
|
|
813
|
+
session: null,
|
|
814
|
+
sessionFile: childSessionFile,
|
|
815
|
+
status: "aborted",
|
|
816
|
+
});
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
/** Reconcile resumable and terminal workers from the persisted parent journal. */
|
|
820
|
+
async rehydrate(session: VibeParentSession): Promise<number> {
|
|
821
|
+
const sessionFile = session.getSessionFile();
|
|
822
|
+
const sessionManager = session.sessionManager;
|
|
823
|
+
if (!sessionFile || !sessionManager) return 0;
|
|
824
|
+
const scope = this.ownerScope(session);
|
|
825
|
+
const allSpawns = new Map<string, VibeSpawnLifecycleEvent>();
|
|
826
|
+
const terminalIntents = new Map<string, VibeTombstoneReason>();
|
|
827
|
+
for (const entry of sessionManager.getEntries()) {
|
|
828
|
+
if (entry.type !== "custom" || entry.customType !== VIBE_LIFECYCLE_CUSTOM_TYPE) continue;
|
|
829
|
+
const event = parseLifecycleEvent(entry.data);
|
|
830
|
+
if (!event || event.ownerId !== scope.ownerId || event.parentSessionId !== scope.parentSessionId) continue;
|
|
831
|
+
if (event.action === "spawn") allSpawns.set(event.id, event);
|
|
832
|
+
else if (event.action === "tombstone") terminalIntents.set(event.id, event.reason);
|
|
833
|
+
else if (event.action === "tombstone-revoked" && terminalIntents.get(event.id) === "mode-exit") {
|
|
834
|
+
terminalIntents.delete(event.id);
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
const candidates = new Map<string, VibeRestoreCandidate>();
|
|
839
|
+
for (const entry of sessionManager.getBranch()) {
|
|
840
|
+
if (entry.type !== "custom" || entry.customType !== VIBE_LIFECYCLE_CUSTOM_TYPE) continue;
|
|
841
|
+
const event = parseLifecycleEvent(entry.data);
|
|
842
|
+
if (!event || event.ownerId !== scope.ownerId || event.parentSessionId !== scope.parentSessionId) continue;
|
|
843
|
+
const eventTime = Date.parse(entry.timestamp);
|
|
844
|
+
if (event.action === "spawn") {
|
|
845
|
+
candidates.set(event.id, {
|
|
846
|
+
spawn: event,
|
|
847
|
+
turnCount: 0,
|
|
848
|
+
lastActivityAt: Number.isFinite(eventTime) ? eventTime : event.createdAt,
|
|
849
|
+
inFlight: false,
|
|
850
|
+
});
|
|
851
|
+
continue;
|
|
852
|
+
}
|
|
853
|
+
const candidate = candidates.get(event.id);
|
|
854
|
+
if (!candidate) continue;
|
|
855
|
+
candidate.lastActivityAt = Number.isFinite(eventTime) ? eventTime : candidate.lastActivityAt;
|
|
856
|
+
if (event.action === "turn-started" && event.turn >= candidate.turnCount) {
|
|
857
|
+
candidate.turnCount = event.turn;
|
|
858
|
+
candidate.inFlight = true;
|
|
859
|
+
} else if (event.action === "turn-settled" && event.turn >= candidate.turnCount) {
|
|
860
|
+
candidate.turnCount = event.turn;
|
|
861
|
+
candidate.inFlight = false;
|
|
862
|
+
} else if (event.action === "tombstone") {
|
|
863
|
+
candidate.tombstoneReason = event.reason;
|
|
864
|
+
} else if (event.action === "tombstone-revoked" && candidate.tombstoneReason === "mode-exit") {
|
|
865
|
+
candidate.tombstoneReason = undefined;
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
for (const id of terminalIntents.keys()) {
|
|
870
|
+
const spawn = allSpawns.get(id);
|
|
871
|
+
if (!spawn) continue;
|
|
872
|
+
const childSessionFile = await this.#resolvePersistedChild(sessionFile, spawn, { requireAgentMatch: false });
|
|
873
|
+
if (!childSessionFile) continue;
|
|
874
|
+
await this.#markTerminalRef(id, scope.ownerId, childSessionFile);
|
|
875
|
+
this.#records.delete(scopeKey(scope, id));
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
let restored = 0;
|
|
879
|
+
for (const candidate of candidates.values()) {
|
|
880
|
+
const { spawn } = candidate;
|
|
881
|
+
if (candidate.tombstoneReason || terminalIntents.has(spawn.id) || candidate.turnCount < 1) continue;
|
|
882
|
+
const childSessionFile = await this.#resolvePersistedChild(sessionFile, spawn);
|
|
883
|
+
if (!childSessionFile) continue;
|
|
884
|
+
const key = scopeKey(scope, spawn.id);
|
|
885
|
+
if (this.#records.has(key)) continue;
|
|
886
|
+
const existing = AgentRegistry.global().get(spawn.id);
|
|
887
|
+
const existingIsResumable =
|
|
888
|
+
existing?.kind === "sub" &&
|
|
889
|
+
existing.parentId === scope.ownerId &&
|
|
890
|
+
existing.sessionFile === childSessionFile &&
|
|
891
|
+
(existing.status === "idle" || existing.status === "parked");
|
|
892
|
+
const blockedByCollision = Boolean(existing && !existingIsResumable);
|
|
893
|
+
const { agent, modelOverride } = this.#resolveWorker(session, spawn.cli);
|
|
894
|
+
if (!existing) {
|
|
895
|
+
AgentRegistry.global().register({
|
|
896
|
+
id: spawn.id,
|
|
897
|
+
displayName: spawn.id,
|
|
898
|
+
kind: "sub",
|
|
899
|
+
parentId: scope.ownerId,
|
|
900
|
+
session: null,
|
|
901
|
+
sessionFile: childSessionFile,
|
|
902
|
+
status: "parked",
|
|
903
|
+
});
|
|
904
|
+
}
|
|
905
|
+
this.#records.set(key, {
|
|
906
|
+
id: spawn.id,
|
|
907
|
+
cli: spawn.cli,
|
|
908
|
+
ownerId: scope.ownerId,
|
|
909
|
+
parentSessionId: scope.parentSessionId,
|
|
910
|
+
parentSessionFile: scope.parentSessionFile,
|
|
911
|
+
childSessionFile,
|
|
912
|
+
agent,
|
|
913
|
+
modelOverride,
|
|
914
|
+
state: "idle",
|
|
915
|
+
createdAt: spawn.createdAt,
|
|
916
|
+
lastActivityAt: candidate.lastActivityAt,
|
|
917
|
+
lastActivity: blockedByCollision
|
|
918
|
+
? "blocked by an agent id collision"
|
|
919
|
+
: candidate.inFlight
|
|
920
|
+
? `turn ${candidate.turnCount} interrupted by process restart`
|
|
921
|
+
: undefined,
|
|
922
|
+
queue: [],
|
|
923
|
+
turnCount: candidate.turnCount,
|
|
924
|
+
killed: false,
|
|
925
|
+
suspended: false,
|
|
926
|
+
terminalPersisted: false,
|
|
927
|
+
});
|
|
928
|
+
restored++;
|
|
929
|
+
}
|
|
930
|
+
return restored;
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
/** Spawn a persistent worker session and start its first turn in the background. */
|
|
934
|
+
async spawn(session: ToolSession, args: { cli: VibeCli; name?: string; prompt: string }): Promise<VibeSpawnOutcome> {
|
|
935
|
+
const scope = this.ownerScope(session);
|
|
936
|
+
return this.#withTerminationLock(scope, () => this.#spawnLocked(session, scope, args));
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
async #spawnLocked(
|
|
940
|
+
session: ToolSession,
|
|
941
|
+
scope: VibeOwnerScope,
|
|
942
|
+
args: { cli: VibeCli; name?: string; prompt: string },
|
|
943
|
+
): Promise<VibeSpawnOutcome> {
|
|
944
|
+
if (this.#terminatedScopes.has(scopeKey(scope, ""))) {
|
|
945
|
+
throw new ToolError("Vibe mode has exited; enter Vibe mode again before spawning a worker.");
|
|
946
|
+
}
|
|
947
|
+
const manager = this.#manager(session);
|
|
948
|
+
const { agent, modelOverride } = this.#resolveWorker(session, args.cli);
|
|
949
|
+
if (!session.agentOutputManager) {
|
|
950
|
+
session.agentOutputManager = new AgentOutputManager(session.getArtifactsDir ?? (() => null));
|
|
951
|
+
}
|
|
952
|
+
const reservedIds = this.#persistedIds(session, scope);
|
|
953
|
+
for (const ref of AgentRegistry.global().list()) reservedIds.add(ref.id);
|
|
954
|
+
await session.agentOutputManager.reserve(reservedIds);
|
|
955
|
+
const requestedName = args.name?.replace(/[^A-Za-z0-9_-]+/g, "").slice(0, 48);
|
|
956
|
+
const id = await session.agentOutputManager.allocate(requestedName || generateTaskName());
|
|
957
|
+
const parentSessionFile = scope.parentSessionFile;
|
|
958
|
+
const childSessionName = `${id}.jsonl`;
|
|
959
|
+
const childSessionFile = parentSessionFile
|
|
960
|
+
? path.resolve(parentSessionFile.slice(0, -6), childSessionName)
|
|
961
|
+
: undefined;
|
|
962
|
+
const createdAt = Date.now();
|
|
963
|
+
const record: VibeRecord = {
|
|
964
|
+
id,
|
|
965
|
+
cli: args.cli,
|
|
966
|
+
ownerId: scope.ownerId,
|
|
967
|
+
parentSessionId: scope.parentSessionId,
|
|
968
|
+
parentSessionFile,
|
|
969
|
+
childSessionFile,
|
|
970
|
+
agent,
|
|
971
|
+
modelOverride,
|
|
972
|
+
state: "starting",
|
|
973
|
+
createdAt,
|
|
974
|
+
lastActivityAt: createdAt,
|
|
975
|
+
queue: [],
|
|
976
|
+
turnCount: 0,
|
|
977
|
+
killed: false,
|
|
978
|
+
suspended: false,
|
|
979
|
+
terminalPersisted: false,
|
|
980
|
+
};
|
|
981
|
+
const key = scopeKey(scope, id);
|
|
982
|
+
this.#records.set(key, record);
|
|
983
|
+
let spawnPersisted = false;
|
|
984
|
+
try {
|
|
985
|
+
if (childSessionFile) {
|
|
986
|
+
spawnPersisted = await this.#appendLifecycleEvent(
|
|
987
|
+
session,
|
|
988
|
+
{
|
|
989
|
+
...this.#eventBase(record),
|
|
990
|
+
action: "spawn",
|
|
991
|
+
cli: args.cli,
|
|
992
|
+
agent: agent.name,
|
|
993
|
+
childSessionFile: childSessionName,
|
|
994
|
+
createdAt,
|
|
995
|
+
},
|
|
996
|
+
record.parentSessionFile,
|
|
997
|
+
);
|
|
998
|
+
if (!spawnPersisted) throw new ToolError("Vibe parent session changed before the worker could start.");
|
|
999
|
+
}
|
|
1000
|
+
const jobId = this.#registerTurnJob(session, manager, record, args.prompt, { first: true });
|
|
1001
|
+
return { id, jobId };
|
|
1002
|
+
} catch (error) {
|
|
1003
|
+
record.killed = true;
|
|
1004
|
+
record.state = "dead";
|
|
1005
|
+
record.lastActivityAt = Date.now();
|
|
1006
|
+
record.lastActivity = "spawn failed";
|
|
1007
|
+
if (childSessionFile) {
|
|
1008
|
+
// A rejected terminal write leaves this dead record in the map so mode exit can retry it.
|
|
1009
|
+
record.terminalPersisted = await this.#appendTombstone(session, record, "spawn-failed");
|
|
1010
|
+
if (!record.terminalPersisted) {
|
|
1011
|
+
throw new ToolError("Vibe parent session changed before spawn failure could be persisted.");
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
this.#records.delete(key);
|
|
1015
|
+
throw error;
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
/**
|
|
1020
|
+
* Send a message to a worker. Mid-turn and streaming → steering; mid-turn
|
|
1021
|
+
* otherwise → queued for the next turn; idle/parked → starts a new
|
|
1022
|
+
* background turn immediately.
|
|
1023
|
+
*/
|
|
1024
|
+
async send(session: ToolSession, args: { session: string; message: string }): Promise<VibeSendOutcome> {
|
|
1025
|
+
const scope = this.ownerScope(session);
|
|
1026
|
+
const record = this.#record(scope, args.session);
|
|
1027
|
+
if (record.state === "dead") {
|
|
1028
|
+
throw new ToolError(`Vibe session "${record.id}" is dead. Spawn a new one with vibe_spawn.`);
|
|
1029
|
+
}
|
|
1030
|
+
const message = args.message.trim();
|
|
1031
|
+
if (!message) throw new ToolError("Message must not be empty.");
|
|
1032
|
+
const registered = this.#registeredAgent(record);
|
|
1033
|
+
if (AgentRegistry.global().get(record.id) && !registered) {
|
|
1034
|
+
throw new ToolError(`Vibe session "${record.id}" no longer resolves to this parent session.`);
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
if (record.turn) {
|
|
1038
|
+
const live = registered?.session;
|
|
1039
|
+
if (live?.isStreaming) {
|
|
1040
|
+
await live.steer(message);
|
|
1041
|
+
record.lastActivityAt = Date.now();
|
|
1042
|
+
return { id: record.id, mode: "steered" };
|
|
1043
|
+
}
|
|
1044
|
+
record.queue.push(message);
|
|
1045
|
+
record.lastActivityAt = Date.now();
|
|
1046
|
+
return { id: record.id, mode: "queued" };
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
if (!registered || (registered.status !== "idle" && registered.status !== "parked")) {
|
|
1050
|
+
throw new ToolError(`Vibe session "${record.id}" no longer resolves to this parent session.`);
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
const manager = this.#manager(session);
|
|
1054
|
+
const jobId = this.#registerTurnJob(session, manager, record, message, { first: false });
|
|
1055
|
+
return { id: record.id, mode: "turn", jobId };
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
/**
|
|
1059
|
+
* Block until one watched session's in-flight turn settles, the timeout
|
|
1060
|
+
* elapses, or `signal` aborts — `hub` wait semantics. Settled turns are
|
|
1061
|
+
* acknowledged against the job manager so their results are not delivered
|
|
1062
|
+
* a second time as async follow-ups.
|
|
1063
|
+
*/
|
|
1064
|
+
async wait(
|
|
1065
|
+
session: ToolSession,
|
|
1066
|
+
args: { sessions?: string[]; timeoutMs?: number; signal?: AbortSignal },
|
|
1067
|
+
): Promise<VibeWaitOutcome> {
|
|
1068
|
+
const scope = this.ownerScope(session);
|
|
1069
|
+
const manager = this.#manager(session);
|
|
1070
|
+
// Named sessions are watched regardless of state (a just-settled turn is
|
|
1071
|
+
// reported from its retained job); the no-args form watches every
|
|
1072
|
+
// session with a turn actually in flight.
|
|
1073
|
+
const watched = args.sessions?.length
|
|
1074
|
+
? args.sessions.map(id => this.#record(scope, id))
|
|
1075
|
+
: [...this.#records.values()].filter(record => matchesScope(record, scope) && record.turn !== undefined);
|
|
1076
|
+
|
|
1077
|
+
// Snapshot each watched turn's job at entry: #finishTurn installs a
|
|
1078
|
+
// queued follow-up turn inside the settling job's callback (before that
|
|
1079
|
+
// job's promise resolves), so re-reading record.turn after the race
|
|
1080
|
+
// would inspect the *next* running job and silently drop the settled
|
|
1081
|
+
// result — whose async delivery watchJobs is suppressing on our behalf.
|
|
1082
|
+
const snapshots: Array<{ record: VibeRecord; jobId: string }> = [];
|
|
1083
|
+
for (const record of watched) {
|
|
1084
|
+
const jobId = record.turn?.jobId ?? record.lastJobId;
|
|
1085
|
+
if (jobId) snapshots.push({ record, jobId });
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
const collectSettled = (): VibeWaitOutcome["settled"] => {
|
|
1089
|
+
const settled: VibeWaitOutcome["settled"] = [];
|
|
1090
|
+
for (const { record, jobId } of snapshots) {
|
|
1091
|
+
const job = manager.getJob(jobId);
|
|
1092
|
+
if (!job || job.status === "running") continue;
|
|
1093
|
+
settled.push({
|
|
1094
|
+
id: record.id,
|
|
1095
|
+
jobId,
|
|
1096
|
+
status: job.status,
|
|
1097
|
+
resultText: job.resultText ?? job.errorText ?? "(no output)",
|
|
1098
|
+
});
|
|
1099
|
+
}
|
|
1100
|
+
return settled;
|
|
1101
|
+
};
|
|
1102
|
+
|
|
1103
|
+
const runningJobs: AsyncJob[] = [];
|
|
1104
|
+
for (const { jobId } of snapshots) {
|
|
1105
|
+
const job = manager.getJob(jobId);
|
|
1106
|
+
if (job?.status === "running") runningJobs.push(job);
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
let waited = false;
|
|
1110
|
+
if (runningJobs.length > 0 && collectSettled().length === 0) {
|
|
1111
|
+
waited = true;
|
|
1112
|
+
const timeoutMs = Math.max(1, Math.trunc(args.timeoutMs ?? DEFAULT_WAIT_TIMEOUT_MS));
|
|
1113
|
+
const watchedJobIds = runningJobs.map(job => job.id);
|
|
1114
|
+
manager.watchJobs(watchedJobIds);
|
|
1115
|
+
const { promise: timeoutPromise, resolve: timeoutResolve } = Promise.withResolvers<void>();
|
|
1116
|
+
const timeoutHandle = setTimeout(() => timeoutResolve(), timeoutMs);
|
|
1117
|
+
const racePromises: Promise<unknown>[] = [...runningJobs.map(job => job.promise), timeoutPromise];
|
|
1118
|
+
let abortCleanup: (() => void) | undefined;
|
|
1119
|
+
if (args.signal) {
|
|
1120
|
+
const { promise: abortPromise, resolve: abortResolve } = Promise.withResolvers<void>();
|
|
1121
|
+
const onAbort = () => abortResolve();
|
|
1122
|
+
args.signal.addEventListener("abort", onAbort, { once: true });
|
|
1123
|
+
abortCleanup = () => args.signal?.removeEventListener("abort", onAbort);
|
|
1124
|
+
racePromises.push(abortPromise);
|
|
1125
|
+
}
|
|
1126
|
+
try {
|
|
1127
|
+
await Promise.race(racePromises);
|
|
1128
|
+
} finally {
|
|
1129
|
+
manager.unwatchJobs(watchedJobIds);
|
|
1130
|
+
clearTimeout(timeoutHandle);
|
|
1131
|
+
abortCleanup?.();
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
const settled = collectSettled();
|
|
1136
|
+
manager.acknowledgeDeliveries(settled.map(entry => entry.jobId));
|
|
1137
|
+
// Current in-flight state, independent of the snapshot: a session whose
|
|
1138
|
+
// watched turn settled may already be mid queued follow-up.
|
|
1139
|
+
const stillRunning = watched.filter(record => record.turn !== undefined).map(record => record.id);
|
|
1140
|
+
return { settled, stillRunning, timedOut: waited && settled.length === 0 };
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
/** Detach one parent's process-local workers without tombstoning their persisted conversations. */
|
|
1144
|
+
async suspendScope(scope: VibeOwnerScope, manager?: AsyncJobManager): Promise<number> {
|
|
1145
|
+
const records = [...this.#records.values()].filter(record => matchesScope(record, scope));
|
|
1146
|
+
const teardown = records.map(record => ({
|
|
1147
|
+
record,
|
|
1148
|
+
ref: this.#registeredAgent(record),
|
|
1149
|
+
job: record.turn && manager ? manager.getJob(record.turn.jobId) : undefined,
|
|
1150
|
+
}));
|
|
1151
|
+
for (const { record } of teardown) {
|
|
1152
|
+
record.suspended = true;
|
|
1153
|
+
record.queue.length = 0;
|
|
1154
|
+
record.state = "dead";
|
|
1155
|
+
record.lastActivityAt = Date.now();
|
|
1156
|
+
record.lastActivity = "suspended for parent-session switch";
|
|
1157
|
+
this.#records.delete(scopeKey(scope, record.id));
|
|
1158
|
+
if (record.turn && manager) manager.cancel(record.turn.jobId, { ownerId: record.ownerId });
|
|
1159
|
+
}
|
|
1160
|
+
const deadline = Date.now() + this.#teardownGraceMs;
|
|
1161
|
+
const cleanup = teardown.map(entry => ({
|
|
1162
|
+
...entry,
|
|
1163
|
+
releaseTask: entry.ref ? this.#trackAgentRelease(entry.record.id, entry.ref, "detach") : undefined,
|
|
1164
|
+
jobTask: entry.job ? this.#trackJobSettlement(entry.record, entry.job) : undefined,
|
|
1165
|
+
}));
|
|
1166
|
+
await waitForVibeTeardown(
|
|
1167
|
+
cleanup.flatMap(entry => [entry.releaseTask, entry.jobTask].filter(task => task !== undefined)),
|
|
1168
|
+
deadline,
|
|
1169
|
+
);
|
|
1170
|
+
for (const { record, ref, releaseTask, job, jobTask } of cleanup) {
|
|
1171
|
+
if (ref && releaseTask) this.#finishAgentRelease(record.id, ref, releaseTask, "detach");
|
|
1172
|
+
if (job && jobTask?.status() === "pending") {
|
|
1173
|
+
logger.warn("vibe: timed out waiting for cancelled worker turn; cleanup continues in the background", {
|
|
1174
|
+
id: record.id,
|
|
1175
|
+
jobId: job.id,
|
|
1176
|
+
});
|
|
1177
|
+
this.#continueSuspendedCleanup(scope, record, jobTask);
|
|
1178
|
+
}
|
|
1179
|
+
if (this.#records.has(scopeKey(scope, record.id))) continue;
|
|
1180
|
+
const lateRef = this.#registeredAgent(record);
|
|
1181
|
+
if (lateRef && lateRef !== ref) {
|
|
1182
|
+
await this.#releaseRefWithinDeadline(record.id, lateRef, deadline, "detach");
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
return records.length;
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
#continueSuspendedCleanup(scope: VibeOwnerScope, record: VibeRecord, jobTask: TrackedVibeTeardown): void {
|
|
1189
|
+
void jobTask.promise
|
|
1190
|
+
.then(async () => {
|
|
1191
|
+
if (this.#records.has(scopeKey(scope, record.id))) return;
|
|
1192
|
+
const lateRef = this.#registeredAgent(record);
|
|
1193
|
+
if (!lateRef) return;
|
|
1194
|
+
await this.#releaseRefWithinDeadline(record.id, lateRef, Date.now() + this.#teardownGraceMs, "detach");
|
|
1195
|
+
})
|
|
1196
|
+
.catch(error => {
|
|
1197
|
+
logger.warn("vibe: failed to finish suspended worker cleanup", {
|
|
1198
|
+
id: record.id,
|
|
1199
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1200
|
+
});
|
|
1201
|
+
});
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
/** Terminate one worker; a tombstone failure still tears it down before reconciliation and error delivery. */
|
|
1205
|
+
async kill(session: ToolSession, id: string): Promise<VibeKillOutcome> {
|
|
1206
|
+
const scope = this.ownerScope(session);
|
|
1207
|
+
return this.#withTerminationLock(scope, () => {
|
|
1208
|
+
const record = this.#record(scope, id);
|
|
1209
|
+
return this.#killRecord(record, session.asyncJobManager, session, "explicit-kill");
|
|
1210
|
+
});
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
/** Kill every live session in one parent scope after durably recording the complete mode-exit intent. */
|
|
1214
|
+
async killAll(session: VibeParentSession, ownerScope?: VibeOwnerScope): Promise<number> {
|
|
1215
|
+
const scope = ownerScope ?? this.ownerScope(session);
|
|
1216
|
+
return this.#withTerminationLock(scope, async () => {
|
|
1217
|
+
try {
|
|
1218
|
+
const killed = await this.#killAllLocked(session, scope);
|
|
1219
|
+
this.#terminatedScopes.add(scopeKey(scope, ""));
|
|
1220
|
+
return killed;
|
|
1221
|
+
} catch (error) {
|
|
1222
|
+
if (error instanceof SessionPersistenceIndeterminateError) {
|
|
1223
|
+
this.#terminatedScopes.add(scopeKey(scope, ""));
|
|
1224
|
+
}
|
|
1225
|
+
throw error;
|
|
1226
|
+
}
|
|
1227
|
+
});
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
async #killAllLocked(session: VibeParentSession, scope: VibeOwnerScope): Promise<number> {
|
|
1231
|
+
const records = [...this.#records.values()].filter(
|
|
1232
|
+
record => matchesScope(record, scope) && !(record.state === "dead" && record.terminalPersisted),
|
|
1233
|
+
);
|
|
1234
|
+
if (records.length === 0) {
|
|
1235
|
+
const entries = session.sessionManager?.getBranch() ?? [];
|
|
1236
|
+
for (let index = entries.length - 1; index >= 0; index--) {
|
|
1237
|
+
const entry = entries[index];
|
|
1238
|
+
if (entry.type !== "mode_change") continue;
|
|
1239
|
+
if (entry.mode === "none") return 0;
|
|
1240
|
+
break;
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
try {
|
|
1244
|
+
await this.#persistModeExit(session, scope, records);
|
|
1245
|
+
} catch (error) {
|
|
1246
|
+
if (error instanceof SessionPersistenceIndeterminateError) {
|
|
1247
|
+
const teardownDeadline = Date.now() + this.#teardownGraceMs;
|
|
1248
|
+
await Promise.all(
|
|
1249
|
+
records.map(record =>
|
|
1250
|
+
this.#killRecord(record, session.asyncJobManager, session, "mode-exit", false, teardownDeadline),
|
|
1251
|
+
),
|
|
1252
|
+
);
|
|
1253
|
+
}
|
|
1254
|
+
throw error;
|
|
1255
|
+
}
|
|
1256
|
+
const teardownDeadline = Date.now() + this.#teardownGraceMs;
|
|
1257
|
+
await Promise.all(
|
|
1258
|
+
records.map(record =>
|
|
1259
|
+
this.#killRecord(record, session.asyncJobManager, session, "mode-exit", true, teardownDeadline),
|
|
1260
|
+
),
|
|
1261
|
+
);
|
|
1262
|
+
return records.length;
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
async #killRecord(
|
|
1266
|
+
record: VibeRecord,
|
|
1267
|
+
manager: AsyncJobManager | undefined,
|
|
1268
|
+
session: VibeParentSession,
|
|
1269
|
+
reason: VibeTombstoneReason,
|
|
1270
|
+
persistTerminal = true,
|
|
1271
|
+
teardownDeadline?: number,
|
|
1272
|
+
): Promise<VibeKillOutcome> {
|
|
1273
|
+
const registered = this.#registeredAgent(record);
|
|
1274
|
+
const settlingJobs = new Set<AsyncJob>();
|
|
1275
|
+
if (record.turn && manager) {
|
|
1276
|
+
const job = manager.getJob(record.turn.jobId);
|
|
1277
|
+
if (job) settlingJobs.add(job);
|
|
1278
|
+
}
|
|
1279
|
+
let persistenceError: unknown;
|
|
1280
|
+
if (persistTerminal && !record.terminalPersisted) {
|
|
1281
|
+
try {
|
|
1282
|
+
if (record.killed) {
|
|
1283
|
+
const recover = session.sessionManager?.recoverPersistenceFromCurrentState;
|
|
1284
|
+
if (!recover) throw new ToolError("Vibe tombstone recovery requires parent-session persistence.");
|
|
1285
|
+
await recover.call(session.sessionManager);
|
|
1286
|
+
}
|
|
1287
|
+
if (!this.#hasInMemoryTombstone(session, record) && record.childSessionFile) {
|
|
1288
|
+
if (!(await this.#appendTombstone(session, record, reason))) {
|
|
1289
|
+
throw new ToolError(`Vibe session "${record.id}" changed parent scope before termination.`);
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
record.terminalPersisted = true;
|
|
1293
|
+
} catch (error) {
|
|
1294
|
+
persistenceError = error;
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
record.killed = true;
|
|
1298
|
+
record.queue.length = 0;
|
|
1299
|
+
let cancelledTurn = false;
|
|
1300
|
+
if (record.turn && manager) {
|
|
1301
|
+
const job = manager.getJob(record.turn.jobId);
|
|
1302
|
+
if (job) settlingJobs.add(job);
|
|
1303
|
+
cancelledTurn = manager.cancel(record.turn.jobId, { ownerId: record.ownerId });
|
|
1304
|
+
}
|
|
1305
|
+
record.state = "dead";
|
|
1306
|
+
record.lastActivityAt = Date.now();
|
|
1307
|
+
record.lastActivity = "killed";
|
|
1308
|
+
const deadline = teardownDeadline ?? Date.now() + this.#teardownGraceMs;
|
|
1309
|
+
const releaseTask = registered ? this.#trackAgentRelease(record.id, registered, "release") : undefined;
|
|
1310
|
+
const jobCleanup = [...settlingJobs].map(job => ({ job, task: this.#trackJobSettlement(record, job) }));
|
|
1311
|
+
await waitForVibeTeardown(
|
|
1312
|
+
[releaseTask, ...jobCleanup.map(entry => entry.task)].filter(task => task !== undefined),
|
|
1313
|
+
deadline,
|
|
1314
|
+
);
|
|
1315
|
+
if (registered && releaseTask) this.#finishAgentRelease(record.id, registered, releaseTask, "release");
|
|
1316
|
+
const pendingJobs = jobCleanup.filter(entry => entry.task.status() === "pending");
|
|
1317
|
+
for (const { job } of pendingJobs) {
|
|
1318
|
+
logger.warn("vibe: timed out waiting for cancelled worker turn; cleanup continues in the background", {
|
|
1319
|
+
id: record.id,
|
|
1320
|
+
jobId: job.id,
|
|
1321
|
+
});
|
|
1322
|
+
}
|
|
1323
|
+
const terminalRef = registered ?? this.#registeredAgent(record) ?? null;
|
|
1324
|
+
await this.#markTerminalRecord(record, terminalRef, deadline);
|
|
1325
|
+
if (pendingJobs.length > 0) {
|
|
1326
|
+
this.#continueKilledCleanup(
|
|
1327
|
+
record,
|
|
1328
|
+
pendingJobs.map(entry => entry.task),
|
|
1329
|
+
registered,
|
|
1330
|
+
);
|
|
1331
|
+
}
|
|
1332
|
+
if (persistenceError) {
|
|
1333
|
+
let finalPersistenceError = persistenceError;
|
|
1334
|
+
const recover = session.sessionManager?.recoverPersistenceFromCurrentState;
|
|
1335
|
+
if (recover) {
|
|
1336
|
+
try {
|
|
1337
|
+
await recover.call(session.sessionManager);
|
|
1338
|
+
if (!this.#hasInMemoryTombstone(session, record) && record.childSessionFile) {
|
|
1339
|
+
if (!(await this.#appendTombstone(session, record, reason))) {
|
|
1340
|
+
throw new ToolError(`Vibe session "${record.id}" changed parent scope before termination.`);
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
record.terminalPersisted = true;
|
|
1344
|
+
} catch (recoveryError) {
|
|
1345
|
+
if (recoveryError instanceof SessionPersistenceIndeterminateError) {
|
|
1346
|
+
finalPersistenceError = recoveryError;
|
|
1347
|
+
}
|
|
1348
|
+
logger.warn("vibe: failed to reconcile explicit tombstone persistence", {
|
|
1349
|
+
id: record.id,
|
|
1350
|
+
error: recoveryError instanceof Error ? recoveryError.message : String(recoveryError),
|
|
1351
|
+
});
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1354
|
+
throw finalPersistenceError;
|
|
1355
|
+
}
|
|
1356
|
+
return { id: record.id, cancelledTurn };
|
|
1357
|
+
}
|
|
1358
|
+
|
|
1359
|
+
async #markTerminalRecord(
|
|
1360
|
+
record: VibeRecord,
|
|
1361
|
+
expected: AgentRef | null | undefined,
|
|
1362
|
+
teardownDeadline: number,
|
|
1363
|
+
): Promise<void> {
|
|
1364
|
+
if (!record.childSessionFile) return;
|
|
1365
|
+
try {
|
|
1366
|
+
const persisted = await SessionManager.peekSessionInit(record.childSessionFile);
|
|
1367
|
+
if (persisted?.init) {
|
|
1368
|
+
await this.#markTerminalRef(record.id, record.ownerId, record.childSessionFile, expected, teardownDeadline);
|
|
1369
|
+
}
|
|
1370
|
+
} catch (error) {
|
|
1371
|
+
logger.warn("vibe: failed to retain terminal worker transcript", {
|
|
1372
|
+
id: record.id,
|
|
1373
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1374
|
+
});
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
|
|
1378
|
+
#continueKilledCleanup(
|
|
1379
|
+
record: VibeRecord,
|
|
1380
|
+
jobTasks: readonly TrackedVibeTeardown[],
|
|
1381
|
+
expected: AgentRef | undefined,
|
|
1382
|
+
): void {
|
|
1383
|
+
void Promise.allSettled(jobTasks.map(task => task.promise))
|
|
1384
|
+
.then(() => this.#markTerminalRecord(record, expected, Date.now() + this.#teardownGraceMs))
|
|
1385
|
+
.catch(error => {
|
|
1386
|
+
logger.warn("vibe: failed to finish killed worker cleanup", {
|
|
1387
|
+
id: record.id,
|
|
1388
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1389
|
+
});
|
|
1390
|
+
});
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1393
|
+
/** Build the ExecutorOptions for a first spawn, mirroring the `task`/eval-bridge plumbing. */
|
|
1394
|
+
async #buildSpawnOptions(
|
|
1395
|
+
session: ToolSession,
|
|
1396
|
+
record: VibeRecord,
|
|
1397
|
+
message: string,
|
|
1398
|
+
signal: AbortSignal,
|
|
1399
|
+
onProgress: (progress: AgentProgress) => void,
|
|
1400
|
+
): Promise<ExecutorOptions> {
|
|
1401
|
+
const sessionFile = session.getSessionFile();
|
|
1402
|
+
const sessionArtifactsDir = sessionFile ? sessionFile.slice(0, -6) : null;
|
|
1403
|
+
const artifactsDir = sessionArtifactsDir ?? path.join(os.tmpdir(), `omp-vibe-${Snowflake.next()}`);
|
|
1404
|
+
await fs.mkdir(artifactsDir, { recursive: true });
|
|
1405
|
+
if (!sessionArtifactsDir) registerArtifactsDir(artifactsDir);
|
|
1406
|
+
const localProtocolOptions: LocalProtocolOptions = session.localProtocolOptions ?? {
|
|
1407
|
+
getArtifactsDir: session.getArtifactsDir ?? (() => null),
|
|
1408
|
+
getSessionId: session.getSessionId ?? (() => null),
|
|
1409
|
+
};
|
|
1410
|
+
return {
|
|
1411
|
+
cwd: session.cwd,
|
|
1412
|
+
agent: record.agent,
|
|
1413
|
+
task: message,
|
|
1414
|
+
assignment: message,
|
|
1415
|
+
description: `vibe ${record.cli} session`,
|
|
1416
|
+
index: 0,
|
|
1417
|
+
id: record.id,
|
|
1418
|
+
taskDepth: session.taskDepth ?? 0,
|
|
1419
|
+
detached: true,
|
|
1420
|
+
modelOverride: record.modelOverride,
|
|
1421
|
+
parentActiveModelPattern: session.getActiveModelString?.(),
|
|
1422
|
+
thinkingLevel: record.agent.thinkingLevel,
|
|
1423
|
+
sessionFile,
|
|
1424
|
+
persistArtifacts: Boolean(sessionFile),
|
|
1425
|
+
artifactsDir,
|
|
1426
|
+
enableLsp: (session.enableLsp ?? true) && session.settings.get("task.enableLsp"),
|
|
1427
|
+
signal,
|
|
1428
|
+
eventBus: session.eventBus,
|
|
1429
|
+
onProgress,
|
|
1430
|
+
authStorage: session.authStorage,
|
|
1431
|
+
modelRegistry: session.modelRegistry,
|
|
1432
|
+
settings: session.settings,
|
|
1433
|
+
mcpManager: session.mcpManager ?? MCPManager.instance(),
|
|
1434
|
+
contextFiles: session.contextFiles?.filter(file => path.basename(file.path).toLowerCase() !== "agents.md"),
|
|
1435
|
+
skills: [...(session.skills ?? [])],
|
|
1436
|
+
workspaceTree: session.workspaceTree,
|
|
1437
|
+
promptTemplates: session.promptTemplates,
|
|
1438
|
+
rules: session.rules,
|
|
1439
|
+
preloadedExtensionPaths: session.extensionPaths,
|
|
1440
|
+
preloadedCustomToolPaths: session.customToolPaths,
|
|
1441
|
+
localProtocolOptions,
|
|
1442
|
+
parentArtifactManager: session.getArtifactManager?.() ?? undefined,
|
|
1443
|
+
parentHindsightSessionState: session.getHindsightSessionState?.(),
|
|
1444
|
+
parentMnemopiSessionState: session.getMnemopiSessionState?.(),
|
|
1445
|
+
parentTelemetry: session.getTelemetry?.(),
|
|
1446
|
+
parentEvalSessionId: session.getEvalSessionId?.() ?? undefined,
|
|
1447
|
+
parentAgentId: session.getAgentId?.() ?? MAIN_AGENT_ID,
|
|
1448
|
+
parentServiceTier: session.getServiceTierByFamily ? (session.getServiceTierByFamily() ?? null) : undefined,
|
|
1449
|
+
keepAlive: true,
|
|
1450
|
+
};
|
|
1451
|
+
}
|
|
1452
|
+
|
|
1453
|
+
/** Register one background job that runs a single worker turn and self-delivers its result. */
|
|
1454
|
+
#registerTurnJob(
|
|
1455
|
+
session: ToolSession,
|
|
1456
|
+
manager: AsyncJobManager,
|
|
1457
|
+
record: VibeRecord,
|
|
1458
|
+
message: string,
|
|
1459
|
+
options: { first: boolean },
|
|
1460
|
+
): string {
|
|
1461
|
+
const turnIndex = record.turnCount + 1;
|
|
1462
|
+
const turn: VibeTurn = {
|
|
1463
|
+
jobId: "",
|
|
1464
|
+
message,
|
|
1465
|
+
startedAt: Date.now(),
|
|
1466
|
+
trace: [],
|
|
1467
|
+
toolCount: 0,
|
|
1468
|
+
};
|
|
1469
|
+
const onProgress = (progress: AgentProgress): void => {
|
|
1470
|
+
mergeTrace(turn, progress);
|
|
1471
|
+
record.resolvedModel = progress.resolvedModel ?? record.resolvedModel;
|
|
1472
|
+
// recentOutput is newest-first; keep the latest lines oldest-first for display.
|
|
1473
|
+
record.live = {
|
|
1474
|
+
currentTool: progress.currentTool,
|
|
1475
|
+
currentToolArgs: progress.currentToolArgs,
|
|
1476
|
+
lastIntent: progress.lastIntent,
|
|
1477
|
+
outputTail: progress.recentOutput.slice(0, 3).reverse(),
|
|
1478
|
+
};
|
|
1479
|
+
const gist =
|
|
1480
|
+
progress.lastIntent ??
|
|
1481
|
+
(progress.currentTool ? `${progress.currentTool} ${progress.currentToolArgs ?? ""}` : undefined);
|
|
1482
|
+
if (gist) record.lastActivity = firstLine(gist);
|
|
1483
|
+
record.lastActivityAt = Date.now();
|
|
1484
|
+
};
|
|
1485
|
+
|
|
1486
|
+
const jobId = manager.register(
|
|
1487
|
+
"task",
|
|
1488
|
+
`vibe ${record.cli} ${record.id}: ${firstLine(message, 60)}`,
|
|
1489
|
+
async ({ jobId: ownJobId, signal }) => {
|
|
1490
|
+
record.state = "running";
|
|
1491
|
+
record.turnCount = turnIndex;
|
|
1492
|
+
record.lastActivityAt = Date.now();
|
|
1493
|
+
try {
|
|
1494
|
+
const turnStartedPersisted = await this.#appendLifecycleEvent(
|
|
1495
|
+
session,
|
|
1496
|
+
{
|
|
1497
|
+
...this.#eventBase(record),
|
|
1498
|
+
action: "turn-started",
|
|
1499
|
+
turn: turnIndex,
|
|
1500
|
+
},
|
|
1501
|
+
record.parentSessionFile,
|
|
1502
|
+
);
|
|
1503
|
+
if (record.childSessionFile && !turnStartedPersisted) {
|
|
1504
|
+
throw new ToolError(`Vibe session "${record.id}" changed parent scope before its turn started.`);
|
|
1505
|
+
}
|
|
1506
|
+
const result = options.first
|
|
1507
|
+
? await runSubprocess(await this.#buildSpawnOptions(session, record, message, signal, onProgress))
|
|
1508
|
+
: await runSubagentFollowUpTurn({
|
|
1509
|
+
id: record.id,
|
|
1510
|
+
agent: record.agent,
|
|
1511
|
+
message,
|
|
1512
|
+
description: `vibe ${record.cli} session`,
|
|
1513
|
+
signal,
|
|
1514
|
+
onProgress,
|
|
1515
|
+
eventBus: session.eventBus,
|
|
1516
|
+
artifactsDir: session.getSessionFile()?.slice(0, -6),
|
|
1517
|
+
});
|
|
1518
|
+
return await this.#settleTurn(session, manager, record, turn, ownJobId, turnIndex, result);
|
|
1519
|
+
} catch (error) {
|
|
1520
|
+
if (error instanceof VibeTurnError) throw error;
|
|
1521
|
+
await this.#finishTurn(session, manager, record, ownJobId);
|
|
1522
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
1523
|
+
record.lastActivity = firstLine(`turn failed: ${reason}`);
|
|
1524
|
+
throw new VibeTurnError(
|
|
1525
|
+
`[vibe:${record.id} cli=${record.cli} turn=${turnIndex}] turn failed: ${reason}`,
|
|
1526
|
+
);
|
|
1527
|
+
}
|
|
1528
|
+
},
|
|
1529
|
+
{ id: `${record.id}-t${turnIndex}`, agentId: record.id, ownerId: record.ownerId },
|
|
1530
|
+
);
|
|
1531
|
+
turn.jobId = jobId;
|
|
1532
|
+
record.turn = turn;
|
|
1533
|
+
return jobId;
|
|
1534
|
+
}
|
|
1535
|
+
|
|
1536
|
+
/** Post-turn bookkeeping shared by success and failure paths: clear the in-flight turn, flush the queue. */
|
|
1537
|
+
async #finishTurn(
|
|
1538
|
+
session: ToolSession,
|
|
1539
|
+
manager: AsyncJobManager,
|
|
1540
|
+
record: VibeRecord,
|
|
1541
|
+
settledJobId: string,
|
|
1542
|
+
): Promise<void> {
|
|
1543
|
+
record.lastJobId = settledJobId;
|
|
1544
|
+
record.turn = undefined;
|
|
1545
|
+
record.live = undefined;
|
|
1546
|
+
record.lastActivityAt = Date.now();
|
|
1547
|
+
if (record.killed || record.suspended) {
|
|
1548
|
+
record.state = "dead";
|
|
1549
|
+
return;
|
|
1550
|
+
}
|
|
1551
|
+
// Only an idle/parked ref with this parent's exact child file is resumable.
|
|
1552
|
+
const registered = this.#registeredAgent(record);
|
|
1553
|
+
record.state = registered && (registered.status === "idle" || registered.status === "parked") ? "idle" : "dead";
|
|
1554
|
+
if (record.state === "dead") {
|
|
1555
|
+
record.terminalPersisted = await this.#appendTombstone(session, record, "unrecoverable");
|
|
1556
|
+
return;
|
|
1557
|
+
}
|
|
1558
|
+
const settledPersisted = await this.#appendLifecycleEvent(
|
|
1559
|
+
session,
|
|
1560
|
+
{
|
|
1561
|
+
...this.#eventBase(record),
|
|
1562
|
+
action: "turn-settled",
|
|
1563
|
+
turn: record.turnCount,
|
|
1564
|
+
},
|
|
1565
|
+
record.parentSessionFile,
|
|
1566
|
+
);
|
|
1567
|
+
if (record.childSessionFile && !settledPersisted) {
|
|
1568
|
+
record.state = "dead";
|
|
1569
|
+
return;
|
|
1570
|
+
}
|
|
1571
|
+
if (record.queue.length === 0) return;
|
|
1572
|
+
const nextMessage = record.queue.splice(0, record.queue.length).join("\n\n");
|
|
1573
|
+
try {
|
|
1574
|
+
this.#registerTurnJob(session, manager, record, nextMessage, { first: false });
|
|
1575
|
+
} catch (error) {
|
|
1576
|
+
// Leave the messages recoverable: a later vibe_send flushes again.
|
|
1577
|
+
record.queue.unshift(nextMessage);
|
|
1578
|
+
logger.warn("vibe: failed to start queued follow-up turn", {
|
|
1579
|
+
id: record.id,
|
|
1580
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1581
|
+
});
|
|
1582
|
+
}
|
|
1583
|
+
}
|
|
1584
|
+
|
|
1585
|
+
/** Format a settled turn into the self-delivering result text (activity trace + response). */
|
|
1586
|
+
async #settleTurn(
|
|
1587
|
+
session: ToolSession,
|
|
1588
|
+
manager: AsyncJobManager,
|
|
1589
|
+
record: VibeRecord,
|
|
1590
|
+
turn: VibeTurn,
|
|
1591
|
+
settledJobId: string,
|
|
1592
|
+
turnIndex: number,
|
|
1593
|
+
result: SingleResult,
|
|
1594
|
+
): Promise<string> {
|
|
1595
|
+
await this.#finishTurn(session, manager, record, settledJobId);
|
|
1596
|
+
const failed = result.exitCode !== 0 || result.aborted === true;
|
|
1597
|
+
const status = result.aborted ? "aborted" : failed ? "failed" : "completed";
|
|
1598
|
+
record.lastActivity = firstLine(
|
|
1599
|
+
failed
|
|
1600
|
+
? `turn ${turnIndex} ${status}: ${result.abortReason ?? result.error ?? ""}`
|
|
1601
|
+
: (result.lastIntent ?? result.output),
|
|
1602
|
+
);
|
|
1603
|
+
|
|
1604
|
+
const traceLines = turn.trace.map(entry =>
|
|
1605
|
+
firstLine(`${entry.tool}${entry.args ? `(${entry.args})` : ""}`, TRACE_LINE_MAX),
|
|
1606
|
+
);
|
|
1607
|
+
const traceOverflow = Math.max(0, turn.toolCount - turn.trace.length);
|
|
1608
|
+
let response = result.output.trim() || "(no output)";
|
|
1609
|
+
let responseTruncated = false;
|
|
1610
|
+
if (response.length > RESPONSE_PREVIEW_MAX) {
|
|
1611
|
+
const slice = response.slice(0, RESPONSE_PREVIEW_MAX);
|
|
1612
|
+
const lastNewline = slice.lastIndexOf("\n");
|
|
1613
|
+
response = lastNewline > 0 ? slice.slice(0, lastNewline) : slice;
|
|
1614
|
+
responseTruncated = true;
|
|
1615
|
+
}
|
|
1616
|
+
let text: string;
|
|
1617
|
+
try {
|
|
1618
|
+
text = prompt
|
|
1619
|
+
.render(vibeTurnResultTemplate, {
|
|
1620
|
+
id: record.id,
|
|
1621
|
+
cli: record.cli,
|
|
1622
|
+
turn: turnIndex,
|
|
1623
|
+
status,
|
|
1624
|
+
duration: formatDuration(result.durationMs),
|
|
1625
|
+
requests: result.requests,
|
|
1626
|
+
toolCount: turn.toolCount,
|
|
1627
|
+
model: result.resolvedModel ?? record.resolvedModel ?? "",
|
|
1628
|
+
trace: traceLines,
|
|
1629
|
+
traceOverflow: traceOverflow > 0 ? traceOverflow : undefined,
|
|
1630
|
+
response,
|
|
1631
|
+
responseTruncated,
|
|
1632
|
+
error: failed ? (result.abortReason ?? result.error ?? result.stderr ?? "") : "",
|
|
1633
|
+
alive: record.state !== "dead",
|
|
1634
|
+
})
|
|
1635
|
+
.trim();
|
|
1636
|
+
} catch (error) {
|
|
1637
|
+
// A formatting bug must never turn a finished worker turn into a false
|
|
1638
|
+
// failure — the work is done; degrade to a plain-text assembly.
|
|
1639
|
+
logger.warn("vibe: turn-result template render failed; using plain fallback", {
|
|
1640
|
+
id: record.id,
|
|
1641
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1642
|
+
});
|
|
1643
|
+
text = [
|
|
1644
|
+
`[vibe:${record.id} cli=${record.cli} turn=${turnIndex} status=${status}]`,
|
|
1645
|
+
`Activity (${turn.toolCount} tool calls, ${result.requests} requests):`,
|
|
1646
|
+
...traceLines.map(line => `- ${line}`),
|
|
1647
|
+
"",
|
|
1648
|
+
"Response:",
|
|
1649
|
+
response,
|
|
1650
|
+
].join("\n");
|
|
1651
|
+
}
|
|
1652
|
+
if (failed) throw new VibeTurnError(text);
|
|
1653
|
+
return text;
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1656
|
+
|
|
1657
|
+
/**
|
|
1658
|
+
* Aggregate tok/s across every live vibe worker session owned by `ownerId`.
|
|
1659
|
+
* Returns null when no workers are streaming (so callers can fall back to
|
|
1660
|
+
* their own rate unchanged). The director is often idle while workers stream,
|
|
1661
|
+
* so without this aggregation the status-line tok/s badge would show a stale
|
|
1662
|
+
* value while parallel work is actively generating tokens.
|
|
1663
|
+
*
|
|
1664
|
+
* Reads each worker's last assistant message via {@link calculateTokensPerSecond}
|
|
1665
|
+
* — the same leaf calculator the main status line uses — so worker rates are
|
|
1666
|
+
* computed identically to the main session's rate.
|
|
1667
|
+
*/
|
|
1668
|
+
export function aggregateVibeWorkerTokensPerSecond(ownerId: string): number | null {
|
|
1669
|
+
const ids = VibeSessionRegistry.global().listIdsByOwner(ownerId);
|
|
1670
|
+
if (ids.length === 0) return null;
|
|
1671
|
+
let total = 0;
|
|
1672
|
+
let any = false;
|
|
1673
|
+
const registry = AgentRegistry.global();
|
|
1674
|
+
for (const id of ids) {
|
|
1675
|
+
const workerSession = registry.get(id)?.session;
|
|
1676
|
+
if (!workerSession?.isStreaming) continue;
|
|
1677
|
+
const rate = calculateTokensPerSecond(workerSession.state.messages, true);
|
|
1678
|
+
if (rate !== null) {
|
|
1679
|
+
total += rate;
|
|
1680
|
+
any = true;
|
|
1681
|
+
}
|
|
1682
|
+
}
|
|
1683
|
+
return any ? total : null;
|
|
1684
|
+
}
|