one-code-extension 0.4.1 → 0.6.0
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/README.md +16 -5
- package/agents/general-purpose.md +2 -2
- package/docs/guide/README.md +2 -1
- package/docs/guide/bring-your-claude-code-setup.md +60 -9
- package/docs/guide/configuration.md +48 -14
- package/docs/guide/differences-from-claude-code.md +40 -28
- package/docs/guide/doctor.md +20 -13
- package/docs/guide/hooks.md +18 -3
- package/docs/guide/installation.md +26 -4
- package/docs/guide/permissions-modes-and-auto-mode.md +225 -49
- package/docs/guide/providers-and-models.md +137 -54
- package/docs/guide/reference.md +27 -15
- package/docs/guide/sessions-and-context.md +69 -16
- package/docs/guide/skills-plugins-and-mcp.md +57 -20
- package/docs/guide/subagents-and-workflows.md +95 -29
- package/docs/guide/tasks-and-background-work.md +101 -26
- package/docs/guide/terminal-interface.md +24 -12
- package/docs/guide/tools.md +46 -5
- package/docs/guide/troubleshooting.md +13 -9
- package/docs/guide/windows.md +58 -31
- package/extensions/artifacts/gallery.ts +227 -0
- package/extensions/artifacts/index.ts +288 -0
- package/extensions/artifacts/store.ts +570 -0
- package/extensions/artifacts/viewer.ts +199 -0
- package/extensions/ask-user/description.ts +67 -0
- package/extensions/ask-user/dialogs.ts +80 -0
- package/extensions/ask-user/index.ts +37 -33
- package/extensions/ask-user/questions.ts +32 -7
- package/extensions/ask-user/widget.ts +45 -25
- package/extensions/auto-mode/actions.ts +6 -0
- package/extensions/auto-mode/cache.ts +88 -0
- package/extensions/auto-mode/classifier-prompt.ts +5 -4
- package/extensions/auto-mode/classifier.ts +290 -65
- package/extensions/auto-mode/config.ts +72 -20
- package/extensions/auto-mode/decision-log.ts +2 -0
- package/extensions/auto-mode/defaults.ts +1 -1
- package/extensions/auto-mode/denials.ts +124 -0
- package/extensions/auto-mode/git-checkout-programs.ts +187 -0
- package/extensions/auto-mode/git-status-meta.ts +159 -0
- package/extensions/auto-mode/history.ts +189 -0
- package/extensions/auto-mode/instructions.ts +58 -52
- package/extensions/auto-mode/model-select.ts +159 -134
- package/extensions/auto-mode/paths.ts +57 -5
- package/extensions/auto-mode/pause.ts +57 -2
- package/extensions/auto-mode/prompt.ts +37 -21
- package/extensions/auto-mode/read-only-options.ts +724 -0
- package/extensions/auto-mode/resolved-paths-meta.ts +133 -0
- package/extensions/auto-mode/rules.ts +18 -1
- package/extensions/auto-mode/safety-floor.ts +361 -18
- package/extensions/auto-mode/setup-run.ts +20 -14
- package/extensions/auto-mode/shell-analysis.ts +764 -490
- package/extensions/auto-mode/shell-parse.ts +885 -0
- package/extensions/auto-mode/system-note.ts +33 -0
- package/extensions/auto-mode/transcript.ts +80 -51
- package/extensions/background/cron.ts +642 -0
- package/extensions/background/index.ts +614 -248
- package/extensions/background/loop-fire.ts +173 -0
- package/extensions/background/loop-preamble.ts +59 -0
- package/extensions/background/loop-skill.ts +163 -0
- package/extensions/background/monitor-batch.ts +53 -0
- package/extensions/background/noop-fold.ts +128 -0
- package/extensions/background/switch-guard.ts +56 -0
- package/extensions/background/wakeup.ts +178 -55
- package/extensions/bash/background.ts +53 -17
- package/extensions/bash/child.ts +7 -0
- package/extensions/bash/description.ts +188 -0
- package/extensions/bash/guards.ts +15 -67
- package/extensions/bash/index.ts +66 -35
- package/extensions/branding/compaction-keep.ts +63 -0
- package/extensions/branding/declined.ts +22 -0
- package/extensions/branding/index.ts +133 -9
- package/extensions/branding/prompt-editor.ts +53 -6
- package/extensions/branding/queued-edit.ts +31 -0
- package/extensions/branding/replaced-builtins.ts +68 -0
- package/extensions/branding/startup.ts +33 -71
- package/extensions/btw/index.ts +250 -78
- package/extensions/btw/panel.ts +228 -100
- package/extensions/btw/prompt.ts +41 -4
- package/extensions/cache-marks/index.ts +42 -0
- package/extensions/claude-compat/index.ts +7 -11
- package/extensions/claude-context/index.ts +436 -63
- package/extensions/compaction/cut.ts +157 -0
- package/extensions/compaction/index.ts +219 -75
- package/extensions/compaction/kept-thinking.ts +62 -0
- package/extensions/compaction/prompt.ts +15 -12
- package/extensions/context-budget/budget.ts +16 -2
- package/extensions/context-budget/index.ts +35 -15
- package/extensions/context-management/index.ts +36 -28
- package/extensions/doctor/build.ts +59 -8
- package/extensions/doctor/builtins.ts +84 -0
- package/extensions/doctor/cli.ts +7 -1
- package/extensions/doctor/compat.ts +88 -23
- package/extensions/doctor/dependencies.ts +41 -5
- package/extensions/doctor/fix-prompt.ts +9 -2
- package/extensions/doctor/index.ts +102 -58
- package/extensions/doctor/models.ts +102 -63
- package/extensions/doctor/presets.ts +42 -27
- package/extensions/doctor/report.ts +19 -2
- package/extensions/doctor/viewer.ts +49 -27
- package/extensions/effort/index.ts +141 -25
- package/extensions/effort/settings.ts +21 -0
- package/extensions/effort/slider.ts +24 -20
- package/extensions/exit/index.ts +32 -1
- package/extensions/file-tracker/index.ts +420 -42
- package/extensions/file-tracker/replay.ts +137 -24
- package/extensions/file-tracker/restore.ts +66 -0
- package/extensions/file-tracker/results.ts +66 -0
- package/extensions/file-tracker/shell-reads.ts +211 -0
- package/extensions/file-tracker/tracker.ts +45 -15
- package/extensions/footer/footer-line.ts +45 -24
- package/extensions/footer/index.ts +47 -2
- package/extensions/footer/pr.ts +34 -5
- package/extensions/hooks/compaction.ts +7 -0
- package/extensions/hooks/executor.ts +32 -30
- package/extensions/hooks/index.ts +209 -58
- package/extensions/hooks/matcher.ts +3 -0
- package/extensions/hooks/prompt-context.ts +59 -0
- package/extensions/hooks/protocol.ts +41 -3
- package/extensions/hooks/settings.ts +50 -19
- package/extensions/hooks/subagent-bridge.ts +2 -0
- package/extensions/hooks/trust.ts +26 -12
- package/extensions/idle-compact/index.ts +119 -0
- package/extensions/idle-compact/policy.ts +143 -0
- package/extensions/init/index.ts +11 -10
- package/extensions/init/prompt.ts +25 -32
- package/extensions/interrupted/index.ts +13 -1
- package/extensions/kept-thinking/index.ts +27 -0
- package/extensions/ledger/index.ts +46 -0
- package/extensions/ledger/wire.ts +154 -0
- package/extensions/lib/agent-cron.ts +146 -0
- package/extensions/lib/agent-loader.ts +18 -3
- package/extensions/lib/agent-view.ts +85 -0
- package/extensions/lib/anthropic-auth.ts +98 -0
- package/extensions/lib/anthropic-payload.ts +82 -1
- package/extensions/lib/anthropic-server-call.ts +230 -0
- package/extensions/lib/anthropic-server-tools.ts +485 -0
- package/extensions/lib/app-launch.mjs +94 -0
- package/extensions/lib/argument-hints.ts +190 -0
- package/extensions/lib/atomic-write.ts +6 -2
- package/extensions/lib/auto-memory.ts +75 -0
- package/extensions/lib/bash-parser.ts +84 -0
- package/extensions/lib/btw-fork.ts +93 -0
- package/extensions/lib/child-extensions.ts +52 -0
- package/extensions/lib/child-writes.ts +45 -0
- package/extensions/lib/claude-context.ts +515 -100
- package/extensions/lib/claude-external-includes.ts +68 -0
- package/extensions/lib/claude-id.ts +22 -0
- package/extensions/lib/claude-rules.ts +323 -0
- package/extensions/lib/claude-settings.ts +76 -4
- package/extensions/lib/compaction-boundary.ts +36 -0
- package/extensions/lib/compaction-keep.mjs +83 -0
- package/extensions/lib/config-mode.ts +112 -0
- package/extensions/lib/consent-dialogs.ts +63 -0
- package/extensions/lib/consent-preview.ts +5 -1
- package/extensions/lib/consent-stores.ts +48 -0
- package/extensions/lib/context-facts.ts +97 -0
- package/extensions/lib/covered-messages.ts +23 -0
- package/extensions/lib/deferred.ts +359 -25
- package/extensions/lib/dock-rows.ts +60 -0
- package/extensions/lib/empty-tool-result.ts +27 -0
- package/extensions/lib/environment-block.ts +76 -0
- package/extensions/lib/fetch-timeout.ts +24 -6
- package/extensions/{system-prompt → lib}/git-status.ts +51 -13
- package/extensions/lib/git.ts +75 -13
- package/extensions/lib/grammars/LICENSE-tree-sitter-bash +21 -0
- package/extensions/lib/grammars/README.md +2 -0
- package/extensions/lib/grammars/tree-sitter-bash.wasm +0 -0
- package/extensions/lib/guide-docs.ts +45 -0
- package/extensions/lib/headless-output.ts +46 -0
- package/extensions/lib/hook-gate.ts +7 -7
- package/extensions/lib/interrupt.ts +20 -4
- package/extensions/lib/key-input.ts +455 -0
- package/extensions/lib/keys.ts +14 -1
- package/extensions/lib/ledger/fold-memo.ts +49 -0
- package/extensions/lib/ledger/fold.ts +265 -0
- package/extensions/lib/ledger/layout.ts +72 -0
- package/extensions/lib/ledger/plan.ts +102 -0
- package/extensions/lib/ledger/records.ts +276 -0
- package/extensions/lib/ledger/state.ts +47 -0
- package/extensions/lib/ledger/validate.ts +141 -0
- package/extensions/lib/ledger/wire.ts +632 -0
- package/extensions/lib/local-command.ts +71 -19
- package/extensions/lib/mcp-overrides.ts +1 -1
- package/extensions/lib/mcp-share.ts +46 -0
- package/extensions/lib/memory-content.ts +146 -0
- package/extensions/lib/memory-index.ts +18 -0
- package/extensions/lib/memory.ts +134 -123
- package/extensions/lib/model-catalog/huggingface.json +178 -0
- package/extensions/lib/model-catalog/models-dev.json +18533 -0
- package/extensions/lib/model-catalog/openrouter.json +5050 -0
- package/extensions/lib/model-catalog-data.ts +513 -0
- package/extensions/lib/model-catalog.ts +462 -0
- package/extensions/lib/model-choice-warnings.ts +137 -0
- package/extensions/lib/model-pairings.ts +152 -0
- package/extensions/{auto-mode → lib}/model-picker.ts +26 -43
- package/extensions/lib/model-policy.ts +112 -15
- package/extensions/lib/model-tier.ts +283 -355
- package/extensions/lib/model-unusable.ts +1 -1
- package/extensions/lib/newer-model.ts +100 -0
- package/extensions/lib/notices.ts +87 -0
- package/extensions/lib/notifications.ts +357 -73
- package/extensions/lib/one-code-settings.ts +74 -8
- package/extensions/lib/open-browser.ts +63 -0
- package/extensions/lib/openrouter-generation.ts +94 -0
- package/extensions/lib/operation-deadline.ts +30 -0
- package/extensions/lib/original-command.ts +4 -4
- package/extensions/lib/package-version.ts +1 -1
- package/extensions/lib/panel-focus.ts +134 -0
- package/extensions/lib/paths.ts +17 -2
- package/extensions/lib/permission-gate.ts +72 -6
- package/extensions/lib/persisted-output.ts +60 -8
- package/extensions/lib/pi-ai-estimate.ts +19 -3
- package/extensions/lib/pi-version.ts +38 -2
- package/extensions/lib/plan-mode-channels.ts +42 -5
- package/extensions/lib/plugins.ts +26 -17
- package/extensions/lib/powershell-parse-script.ts +208 -0
- package/extensions/lib/powershell-parser.ts +344 -0
- package/extensions/lib/previous-mark.ts +101 -0
- package/extensions/lib/process-state.ts +48 -0
- package/extensions/lib/process-tree.ts +132 -8
- package/extensions/lib/prompt-options.ts +82 -0
- package/extensions/lib/queued-delivery.ts +44 -0
- package/extensions/lib/reminders.ts +370 -358
- package/extensions/lib/replaced-builtins.mjs +199 -0
- package/extensions/lib/replay-call.ts +70 -0
- package/extensions/lib/request-replay.ts +547 -0
- package/extensions/lib/scratchpad.ts +81 -14
- package/extensions/lib/send-now-channel.ts +7 -0
- package/extensions/lib/session-model-tier.ts +51 -0
- package/extensions/lib/session-work.ts +64 -0
- package/extensions/lib/settings-channels.ts +4 -4
- package/extensions/lib/shell-exit-semantics.ts +170 -0
- package/extensions/lib/shell-quote.ts +11 -0
- package/extensions/lib/shell-result.ts +70 -0
- package/extensions/lib/shell-spawn.ts +70 -6
- package/extensions/lib/shell-tool.ts +75 -25
- package/extensions/lib/side-call-cache.ts +124 -0
- package/extensions/lib/side-call-run.ts +96 -0
- package/extensions/lib/side-call-usage.ts +38 -0
- package/extensions/lib/side-call.ts +24 -1
- package/extensions/lib/single-flight.ts +18 -0
- package/extensions/lib/skill-body.ts +42 -0
- package/extensions/lib/skill-scan.ts +63 -24
- package/extensions/lib/spill-file.ts +140 -0
- package/extensions/lib/subagent-handback.ts +112 -0
- package/extensions/lib/system-role.ts +156 -0
- package/extensions/lib/terminal-text.ts +114 -0
- package/extensions/lib/text-width.ts +47 -16
- package/extensions/lib/timer-ops.ts +20 -0
- package/extensions/lib/tool-additions.ts +129 -0
- package/extensions/lib/tool-call-corruption.ts +134 -0
- package/extensions/lib/tool-path.ts +66 -0
- package/extensions/lib/tool-variants.ts +69 -0
- package/extensions/lib/tui-render.ts +255 -27
- package/extensions/lib/turn-budget-layout.ts +159 -0
- package/extensions/lib/update-check.mjs +15 -2
- package/extensions/lib/usage-bus.ts +1 -1
- package/extensions/lib/user-denial.ts +38 -0
- package/extensions/lib/workspace-channel.ts +16 -0
- package/extensions/lib/worktree-channel.ts +31 -3
- package/extensions/lib/worktree-isolation.ts +40 -10
- package/extensions/lsp/client.ts +8 -9
- package/extensions/lsp/index.ts +76 -12
- package/extensions/lsp/keep-alive.ts +1 -1
- package/extensions/lsp/trust.ts +119 -0
- package/extensions/lsp/watcher.ts +1 -1
- package/extensions/mcp/announce.ts +90 -43
- package/extensions/mcp/client.ts +161 -48
- package/extensions/mcp/config.ts +132 -8
- package/extensions/mcp/discovery.ts +19 -0
- package/extensions/mcp/index.ts +220 -121
- package/extensions/mcp/oauth/browser.ts +38 -17
- package/extensions/mcp/oauth/flow.ts +25 -17
- package/extensions/mcp/oauth/provider.ts +14 -8
- package/extensions/mcp/oauth/store.ts +34 -16
- package/extensions/mcp/panel/keys.ts +12 -11
- package/extensions/mcp/panel/render.ts +9 -6
- package/extensions/mcp/schema.ts +104 -5
- package/extensions/mcp/trust.ts +164 -73
- package/extensions/memory/entries.ts +23 -14
- package/extensions/memory/index.ts +134 -28
- package/extensions/memory/open-external.ts +33 -18
- package/extensions/memory/panel.ts +135 -26
- package/extensions/model-default/index.ts +86 -19
- package/extensions/newer-model/index.ts +31 -0
- package/extensions/notebook/description.ts +18 -0
- package/extensions/notebook/index.ts +6 -5
- package/extensions/notebook/notebook.ts +1 -1
- package/extensions/permissions/index.ts +1426 -398
- package/extensions/permissions/matcher.ts +425 -74
- package/extensions/permissions/modes.ts +11 -4
- package/extensions/permissions/panel/host.ts +130 -0
- package/extensions/permissions/panel/keys.ts +48 -0
- package/extensions/permissions/panel/render.ts +450 -0
- package/extensions/permissions/panel/state.ts +550 -0
- package/extensions/permissions/powershell-cmdlets.ts +198 -0
- package/extensions/permissions/powershell-paths.ts +197 -0
- package/extensions/permissions/powershell-rules.ts +207 -280
- package/extensions/permissions/powershell-tree.ts +557 -0
- package/extensions/permissions/project-trust.ts +27 -11
- package/extensions/permissions/protected-paths.ts +14 -2
- package/extensions/permissions/session-grant.ts +6 -0
- package/extensions/permissions/settings.ts +166 -31
- package/extensions/permissions/subagent-gate.ts +25 -0
- package/extensions/permissions/workspace.ts +78 -0
- package/extensions/plan-mode/index.ts +276 -92
- package/extensions/plan-mode/reminder.ts +89 -21
- package/extensions/plan-mode/run-state.ts +26 -0
- package/extensions/plan-mode/texts.ts +177 -0
- package/extensions/plan-mode/viewer.ts +92 -27
- package/extensions/plugins/counts.ts +3 -3
- package/extensions/plugins/index.ts +64 -46
- package/extensions/plugins/install/install.ts +16 -0
- package/extensions/plugins/marketplace/sync.ts +9 -3
- package/extensions/plugins/marketplace/types.ts +3 -1
- package/extensions/plugins/panel/keys.ts +21 -24
- package/extensions/plugins/panel/render.ts +12 -6
- package/extensions/plugins/shell-expand.ts +107 -0
- package/extensions/plugins/template.ts +32 -15
- package/extensions/powershell/child.ts +7 -0
- package/extensions/powershell/description.ts +38 -6
- package/extensions/powershell/guards.ts +1 -1
- package/extensions/powershell/index.ts +14 -7
- package/extensions/recap/index.ts +73 -71
- package/extensions/recap/prompt.ts +2 -2
- package/extensions/recap/scheduler.ts +3 -5
- package/extensions/search-tools/grep-merge.ts +39 -0
- package/extensions/search-tools/index.ts +0 -0
- package/extensions/send-now/chord.ts +62 -0
- package/extensions/send-now/index.ts +133 -0
- package/extensions/session-title/index.ts +3 -0
- package/extensions/session-title/title.ts +4 -1
- package/extensions/skill/announce.ts +30 -0
- package/extensions/skill/code-review.ts +97 -0
- package/extensions/skill/index.ts +469 -132
- package/extensions/skill/invoke.ts +118 -75
- package/extensions/skill/listing.ts +133 -9
- package/extensions/skill/panel/keys.ts +15 -16
- package/extensions/skill/panel/render.ts +5 -2
- package/extensions/skill/panel/state.ts +12 -1
- package/extensions/subagents/agent-args.ts +39 -0
- package/extensions/subagents/agent-description.ts +132 -0
- package/extensions/subagents/agents.ts +146 -31
- package/extensions/subagents/default-model.ts +2 -3
- package/extensions/subagents/delegation-steer.ts +4 -4
- package/extensions/subagents/fork-cache.ts +82 -0
- package/extensions/subagents/guide-agent.ts +189 -0
- package/extensions/subagents/hand-back-review.ts +3 -0
- package/extensions/subagents/index.ts +1594 -852
- package/extensions/subagents/live-runs.ts +26 -6
- package/extensions/subagents/model-select.ts +38 -25
- package/extensions/subagents/outcome.ts +5 -2
- package/extensions/subagents/panel-keys.ts +73 -31
- package/extensions/subagents/panel-render.ts +120 -96
- package/extensions/subagents/panel-widget.ts +60 -89
- package/extensions/subagents/parent-mode.ts +50 -0
- package/extensions/subagents/pending-claim.ts +18 -1
- package/extensions/subagents/runner.ts +135 -80
- package/extensions/subagents/runs.ts +44 -5
- package/extensions/subagents/send-to-main-tool.ts +1 -1
- package/extensions/subagents/session-turns.ts +32 -8
- package/extensions/subagents/shell-panel.ts +36 -178
- package/extensions/subagents/tasks-dialog.ts +170 -0
- package/extensions/subagents/viewport-mirror.ts +95 -0
- package/extensions/subagents/worktree.ts +57 -13
- package/extensions/system-prompt/environment.ts +19 -19
- package/extensions/system-prompt/idle-turn.ts +65 -0
- package/extensions/system-prompt/index.ts +165 -47
- package/extensions/system-prompt/template.ts +34 -51
- package/extensions/system-prompt/tiers/common.ts +23 -64
- package/extensions/system-prompt/tiers/frontier.ts +32 -11
- package/extensions/system-prompt/tiers/low.ts +67 -45
- package/extensions/system-prompt/tiers/mid.ts +96 -38
- package/extensions/system-reminder/index.ts +204 -70
- package/extensions/tasks/descriptions.ts +190 -0
- package/extensions/tasks/index.ts +120 -41
- package/extensions/tasks/store.ts +83 -16
- package/extensions/tool-call-corruption/child.ts +7 -0
- package/extensions/tool-call-corruption/index.ts +237 -0
- package/extensions/tool-search/index.ts +366 -144
- package/extensions/tool-style/index.ts +68 -10
- package/extensions/tool-style/write-description.ts +40 -0
- package/extensions/tool-style/write-render.ts +237 -0
- package/extensions/turn-duration/index.ts +7 -3
- package/extensions/turn-duration/line.ts +47 -4
- package/extensions/web/backends.ts +6 -9
- package/extensions/web/description.ts +50 -0
- package/extensions/web/index.ts +118 -53
- package/extensions/web/native-call.ts +15 -0
- package/extensions/web/native-results.ts +41 -0
- package/extensions/web-fetch/description.ts +42 -0
- package/extensions/web-fetch/extract.ts +53 -6
- package/extensions/web-fetch/index.ts +125 -76
- package/extensions/web-fetch/page-content.ts +19 -0
- package/extensions/web-fetch/response.ts +49 -0
- package/extensions/web-fetch/summarize.ts +9 -10
- package/extensions/workflow/agent-session.ts +108 -18
- package/extensions/workflow/args.ts +24 -0
- package/extensions/workflow/description.ts +67 -0
- package/extensions/workflow/globals.ts +17 -3
- package/extensions/workflow/index.ts +157 -162
- package/extensions/workflow/records.ts +1 -0
- package/extensions/workflow/run-manager.ts +33 -6
- package/extensions/workflow/saved-workflows.ts +3 -2
- package/extensions/workflow/types.ts +22 -1
- package/extensions/workflow/viewer.ts +54 -24
- package/extensions/workflow/widget.ts +20 -0
- package/extensions/worktree/descriptions.ts +91 -0
- package/extensions/worktree/guards.ts +316 -54
- package/extensions/worktree/index.ts +162 -44
- package/extensions/worktree/powershell-guards.ts +167 -0
- package/extensions/worktree/rewrite.ts +14 -16
- package/package.json +21 -7
- package/skills/artifact-design/SKILL.md +85 -0
- package/skills/code-review/SKILL.md +20 -20
- package/skills/code-review/cells/arguments-and-flags.md +19 -0
- package/skills/code-review/cells/high-3x5-recall-verify.md +137 -0
- package/skills/code-review/cells/high-8-inline.md +122 -0
- package/skills/code-review/cells/low-1-pass-max4.md +27 -0
- package/skills/code-review/cells/low-1-pass-min-files-4.md +28 -0
- package/skills/code-review/cells/max-5x5-verify-sweep.md +162 -0
- package/skills/code-review/cells/medium-3x5-verify.md +132 -0
- package/skills/code-review/cells/minimal-prompt.md +32 -0
- package/skills/code-review/cells/xhigh-10-inline-sweep.md +149 -0
- package/skills/code-review/cells/xhigh-5x5-verify-sweep.md +162 -0
- package/skills/fewer-permission-prompts/SKILL.md +1 -1
- package/skills/loop/SKILL.md +11 -0
- package/skills/security-review/SKILL.md +2 -5
- package/skills/simplify/SKILL.md +7 -5
- package/skills/workflow-authoring/SKILL.md +143 -0
- package/themes/onecode-light.json +1 -1
- package/themes/onecode.json +1 -1
- package/types/app.d.ts +58 -0
- package/types/community-packages.d.ts +26 -1
- package/extensions/auto-mode/recoverability.ts +0 -229
- package/extensions/lib/capability-index.ts +0 -466
- package/extensions/lib/model-facts.generated.json +0 -2675
- package/extensions/lib/model-facts.ts +0 -162
- package/extensions/tool-search/announce.ts +0 -42
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Agent tool's model-facing description: Claude Code's Agent text plus
|
|
3
|
+
* One Code's own paragraph (pure).
|
|
4
|
+
*
|
|
5
|
+
* The short form goes to frontier and workhorse models, the long form (the
|
|
6
|
+
* text Claude Code writes for its weakest models, with the fork guidance,
|
|
7
|
+
* the briefing section and worked examples) to cheap and tiny ones
|
|
8
|
+
* (lib/tool-variants.ts). Changes from Claude Code's text: a fork rejects a
|
|
9
|
+
* `model` override rather than ignoring it, agent definitions come from
|
|
10
|
+
* `.claude/agents/*.md` only, and tool names are One Code's. The closing
|
|
11
|
+
* paragraph describes what only One Code has: `task_output` and `task_stop`,
|
|
12
|
+
* the one-shot print session, run names and `action: "list"`.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import type { DescriptionForm } from "../lib/tool-variants.ts";
|
|
16
|
+
|
|
17
|
+
export const AGENT_SHORT_DESCRIPTION = `Launch a new agent to handle complex, multi-step tasks. Each agent type has specific capabilities and tools available to it.
|
|
18
|
+
|
|
19
|
+
Available agent types are listed in <system-reminder> messages in the conversation.
|
|
20
|
+
|
|
21
|
+
When using the Agent tool, specify a subagent_type to select an agent: \`"fork"\` forks yourself (the fork inherits your full conversation context and always runs on your model — a \`model\` override is rejected); any other type — or omitting it — starts a fresh agent (general-purpose by default).
|
|
22
|
+
|
|
23
|
+
## When to use
|
|
24
|
+
|
|
25
|
+
Reach for this when the task matches an available agent type, when you have independent work to run in parallel, or when answering would mean reading across several files — delegate it and you keep the conclusion, not the file dumps. For a single-fact lookup where you already know the file, symbol, or value, search directly. Once you've delegated a search, don't also run it yourself — wait for the result.
|
|
26
|
+
|
|
27
|
+
A fork runs in the background and keeps its tool output out of your context. If you are the fork, execute directly — don't re-delegate. Subagents run in the background; you'll be notified when one completes. Never fabricate or predict a pending agent's results — the notification is never something you write yourself; if the user asks before it arrives, say it's still running.
|
|
28
|
+
|
|
29
|
+
- The agent's final report is not shown to the user — relay what matters.
|
|
30
|
+
- Use SendMessage with the agent's ID or name to continue a previously spawned agent with its context intact; a new Agent call starts fresh (except subagent_type: "fork", which inherits your context).
|
|
31
|
+
- Each agent type's model, reasoning effort, and tools come from its definition (\`.claude/agents/*.md\` frontmatter).
|
|
32
|
+
- \`isolation: "worktree"\` gives the agent its own git worktree (auto-cleaned if unchanged).`;
|
|
33
|
+
|
|
34
|
+
export const AGENT_LONG_DESCRIPTION = `Launch a new agent to handle complex, multi-step tasks. Each agent type has specific capabilities and tools available to it.
|
|
35
|
+
|
|
36
|
+
Available agent types are listed in <system-reminder> messages in the conversation.
|
|
37
|
+
|
|
38
|
+
When using the Agent tool, specify a subagent_type to select an agent: \`"fork"\` forks yourself (the fork inherits your full conversation context and always runs on your model — a \`model\` override is rejected); any other type — or omitting it — starts a fresh agent (general-purpose by default).
|
|
39
|
+
|
|
40
|
+
## Usage notes
|
|
41
|
+
|
|
42
|
+
- Always include a short description summarizing what the agent will do
|
|
43
|
+
- When the agent is done, its final report is not visible to the user. To show the user the result, you should send a text message back to the user with a concise summary of the result.
|
|
44
|
+
- Trust but verify: an agent's summary describes what it intended to do, not necessarily what it did. When an agent writes or edits code, check the actual changes before reporting the work as done.
|
|
45
|
+
- To continue a previously spawned agent, use SendMessage with the agent's ID or name as the \`to\` field — that resumes it with full context. A new Agent call starts a fresh agent with no memory of prior runs (except subagent_type: "fork"), so the prompt must be self-contained.
|
|
46
|
+
- Each agent type's model, reasoning effort, and tool access are set in its definition (\`.claude/agents/*.md\` frontmatter); the \`model\` parameter here overrides the definition for this one call.
|
|
47
|
+
- Clearly tell the agent whether you expect it to write code or just to do research (search, file reads, web fetches, etc.), since a fresh agent is not aware of the user's intent
|
|
48
|
+
- If the agent description mentions that it should be used proactively, then you should try your best to use it without the user having to ask for it first.
|
|
49
|
+
- If the user specifies that they want you to run agents "in parallel", you MUST send a single message with multiple Agent tool use content blocks. For example, if you need to launch both a build-validator agent and a test-runner agent in parallel, send a single message with both tool calls.
|
|
50
|
+
- With \`isolation: "worktree"\`, the worktree is automatically cleaned up if the agent makes no changes; otherwise the path and branch are returned in the result.
|
|
51
|
+
|
|
52
|
+
## When to fork
|
|
53
|
+
|
|
54
|
+
Fork yourself (pass \`subagent_type: "fork"\`) when the intermediate tool output isn't worth keeping in your context. The criterion is qualitative — "will I need this output again" — not task size. Fork open-ended questions. If research can be broken into independent questions, launch parallel forks in one message. A fork beats a fresh subagent for this — it inherits context and shares your cache.
|
|
55
|
+
|
|
56
|
+
Forks are cheap because they share your prompt cache.
|
|
57
|
+
|
|
58
|
+
**Don't peek.** The tool result includes an \`output_file\` path — do not read or tail it. You get a completion notification; trust it. Reading the transcript mid-flight pulls the fork's tool noise into your context, which defeats the point of forking.
|
|
59
|
+
|
|
60
|
+
**Don't race.** After launching, you know nothing about what the fork found. Never fabricate or predict fork results in any format — not as prose, summary, or structured output. The notification arrives as a user-role message in a later turn; it is never something you write yourself. If the user asks a follow-up before the notification lands, tell them the fork is still running — give status, not a guess.
|
|
61
|
+
|
|
62
|
+
**Writing a fork prompt.** Since the fork inherits your context, the prompt is a *directive* — what to do, not what the situation is. Be specific about scope: what's in, what's out, what another agent is handling. Don't re-explain background.
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
## Writing the prompt
|
|
66
|
+
|
|
67
|
+
Any agent other than a fork starts with zero context. Brief the agent like a smart colleague who just walked into the room — it hasn't seen this conversation, doesn't know what you've tried, doesn't understand why this task matters.
|
|
68
|
+
- Explain what you're trying to accomplish and why.
|
|
69
|
+
- Describe what you've already learned or ruled out.
|
|
70
|
+
- Give enough context about the surrounding problem that the agent can make judgment calls rather than just following a narrow instruction.
|
|
71
|
+
- If you need a short response, say so ("report in under 200 words").
|
|
72
|
+
- Lookups: hand over the exact command. Investigations: hand over the question — prescribed steps become dead weight when the premise is wrong.
|
|
73
|
+
|
|
74
|
+
For fresh agents, terse command-style prompts produce shallow, generic work.
|
|
75
|
+
|
|
76
|
+
**Never delegate understanding.** Don't write "based on your findings, fix the bug" or "based on the research, implement it." Those phrases push synthesis onto the agent instead of doing it yourself. Write prompts that prove you understood: include file paths, line numbers, what specifically to change.
|
|
77
|
+
|
|
78
|
+
Example usage:
|
|
79
|
+
|
|
80
|
+
<example>
|
|
81
|
+
user: "What's left on this branch before we can ship?"
|
|
82
|
+
assistant: <thinking>Forking this — it's a survey question. I want the punch list, not the git output in my context.</thinking>
|
|
83
|
+
Agent({
|
|
84
|
+
subagent_type: "fork",
|
|
85
|
+
name: "ship-audit",
|
|
86
|
+
description: "Branch ship-readiness audit",
|
|
87
|
+
prompt: "Audit what's left before this branch can ship. Check: uncommitted changes, commits ahead of main, whether tests exist, whether the GrowthBook gate is wired up, whether CI-relevant files changed. Report a punch list — done vs. missing. Under 200 words."
|
|
88
|
+
})
|
|
89
|
+
assistant: Ship-readiness audit running.
|
|
90
|
+
<commentary>
|
|
91
|
+
Turn ends here. The coordinator knows nothing about the findings yet. What follows is a SEPARATE turn — the notification arrives from outside, as a user-role message. It is not something the coordinator writes.
|
|
92
|
+
</commentary>
|
|
93
|
+
[later turn — notification arrives as user message]
|
|
94
|
+
assistant: Audit's back. Three blockers: no tests for the new prompt path, GrowthBook gate wired but not in build_flags.yaml, and one uncommitted file.
|
|
95
|
+
</example>
|
|
96
|
+
|
|
97
|
+
<example>
|
|
98
|
+
user: "so is the gate wired up or not"
|
|
99
|
+
<commentary>
|
|
100
|
+
User asks mid-wait. The audit fork was launched to answer exactly this, and it hasn't returned. The coordinator does not have this answer. Give status, not a fabricated result.
|
|
101
|
+
</commentary>
|
|
102
|
+
assistant: Still waiting on the audit — that's one of the things it's checking. Should land shortly.
|
|
103
|
+
</example>
|
|
104
|
+
|
|
105
|
+
<example>
|
|
106
|
+
user: "Can you get a second opinion on whether this migration is safe?"
|
|
107
|
+
assistant: <thinking>I'll ask the code-reviewer agent — it won't see my analysis, so it can give an independent read.</thinking>
|
|
108
|
+
<commentary>
|
|
109
|
+
A non-fork subagent_type is specified, so the agent starts fresh. It needs full context in the prompt. The briefing explains what to assess and why.
|
|
110
|
+
</commentary>
|
|
111
|
+
Agent({
|
|
112
|
+
name: "migration-review",
|
|
113
|
+
description: "Independent migration review",
|
|
114
|
+
subagent_type: "code-reviewer",
|
|
115
|
+
prompt: "Review migration 0042_user_schema.sql for safety. Context: we're adding a NOT NULL column to a 50M-row table. Existing rows get a backfill default. I want a second opinion on whether the backfill approach is safe under concurrent writes — I've checked locking behavior but want independent verification. Report: is this safe, and if not, what specifically breaks?"
|
|
116
|
+
})
|
|
117
|
+
</example>
|
|
118
|
+
`;
|
|
119
|
+
|
|
120
|
+
/** One Code's own part, after Claude Code's text in both forms. */
|
|
121
|
+
export const AGENT_HOW_AGENTS_RUN = `## How agents run
|
|
122
|
+
|
|
123
|
+
- Call task_output only if your next step cannot proceed without the result (block=true waits); stop a run with task_stop. Both are deferred — load them with tool_search first.
|
|
124
|
+
- In a one-shot print session the call blocks and returns the report directly — no notification follows.
|
|
125
|
+
- Give a complete, self-contained task: the agent cannot ask follow-up questions.
|
|
126
|
+
- Each run gets a name — SendMessage reaches it live while it runs and continues it after it finishes. \`action: "list"\` re-prints the agent catalog.`;
|
|
127
|
+
|
|
128
|
+
/** The Agent description for a form, naming the mode's agent folder (`.onecode` in independent mode, lib/config-mode.ts). */
|
|
129
|
+
export function agentDescription(form: DescriptionForm, configDir = ".claude"): string {
|
|
130
|
+
const base = form === "long" ? AGENT_LONG_DESCRIPTION : AGENT_SHORT_DESCRIPTION;
|
|
131
|
+
return `${base.trimEnd()}\n\n${AGENT_HOW_AGENTS_RUN}`.replaceAll("`.claude/agents/*.md`", `\`${configDir}/agents/*.md\``);
|
|
132
|
+
}
|
|
@@ -14,10 +14,12 @@
|
|
|
14
14
|
* Subdirectories are searched recursively.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import { readdirSync, readFileSync, statSync } from "node:fs";
|
|
18
|
-
import { basename, join } from "node:path";
|
|
17
|
+
import { readdirSync, readFileSync, type Stats, statSync } from "node:fs";
|
|
18
|
+
import { basename, dirname, join } from "node:path";
|
|
19
|
+
import { fileURLToPath } from "node:url";
|
|
19
20
|
import { parseFrontmatterLoosely } from "../lib/frontmatter.ts";
|
|
20
|
-
import {
|
|
21
|
+
import { projectConfigDir, userConfigDir } from "../lib/config-mode.ts";
|
|
22
|
+
import { SUBAGENT_HANDBACK } from "../lib/subagent-handback.ts";
|
|
21
23
|
import { normalizeToolName } from "../permissions/matcher.ts";
|
|
22
24
|
|
|
23
25
|
export interface AgentDefinition {
|
|
@@ -40,50 +42,113 @@ export interface AgentDefinition {
|
|
|
40
42
|
source: string;
|
|
41
43
|
}
|
|
42
44
|
|
|
43
|
-
|
|
45
|
+
/** Visit every `.md` file under `dir`, at any depth, with its stats. */
|
|
46
|
+
function walkMarkdownFiles(dir: string, visit: (path: string, stats: Stats) => void): void {
|
|
44
47
|
let entries: string[];
|
|
45
48
|
try {
|
|
46
49
|
entries = readdirSync(dir);
|
|
47
50
|
} catch {
|
|
48
|
-
return
|
|
51
|
+
return; // missing or unreadable directory: nothing to discover
|
|
49
52
|
}
|
|
50
53
|
for (const entry of entries) {
|
|
51
54
|
const full = join(dir, entry);
|
|
52
55
|
// A dangling symlink or an unreadable entry must not take the whole
|
|
53
56
|
// catalog (and every Agent call) down with it — skip it (review L1).
|
|
54
|
-
let
|
|
57
|
+
let stats: Stats;
|
|
55
58
|
try {
|
|
56
|
-
|
|
59
|
+
stats = statSync(full);
|
|
57
60
|
} catch {
|
|
58
61
|
continue;
|
|
59
62
|
}
|
|
60
|
-
if (isDirectory) {
|
|
61
|
-
|
|
63
|
+
if (stats.isDirectory()) {
|
|
64
|
+
walkMarkdownFiles(full, visit);
|
|
62
65
|
} else if (entry.endsWith(".md")) {
|
|
63
|
-
|
|
66
|
+
visit(full, stats);
|
|
64
67
|
}
|
|
65
68
|
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function collectMarkdownFiles(dir: string): string[] {
|
|
72
|
+
const out: string[] = [];
|
|
73
|
+
walkMarkdownFiles(dir, (path) => out.push(path));
|
|
66
74
|
return out;
|
|
67
75
|
}
|
|
68
76
|
|
|
77
|
+
/**
|
|
78
|
+
* A stamp of the agent files `discoverAgents` would read from these sources:
|
|
79
|
+
* each source, then each file's path, times and size. It changes when a file
|
|
80
|
+
* is added, removed, renamed or written, so a catalog built from the sources
|
|
81
|
+
* can be reused while the stamp holds, without reading or parsing any file.
|
|
82
|
+
*/
|
|
83
|
+
export function agentSourcesStamp(sources: Array<string | AgentSource>): string {
|
|
84
|
+
const parts: string[] = [];
|
|
85
|
+
for (const source of sources) {
|
|
86
|
+
const { dir, namespace } = typeof source === "string" ? { dir: source, namespace: undefined } : source;
|
|
87
|
+
parts.push(`${namespace ?? ""}@${dir}`);
|
|
88
|
+
walkMarkdownFiles(dir, (path, stats) => parts.push(`${path}:${stats.mtimeMs}:${stats.ctimeMs}:${stats.size}`));
|
|
89
|
+
}
|
|
90
|
+
return parts.join("\n");
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Split one frontmatter tool string the way Claude Code does: on commas and
|
|
95
|
+
* spaces, except inside a rule's parentheses, so `Bash(git push:*), Write` is
|
|
96
|
+
* two entries and `Agent(worker, researcher)` is one.
|
|
97
|
+
*/
|
|
98
|
+
function splitToolSpecs(text: string): string[] {
|
|
99
|
+
const specs: string[] = [];
|
|
100
|
+
let current = "";
|
|
101
|
+
let inParens = false;
|
|
102
|
+
for (const char of text) {
|
|
103
|
+
if (char === "(") inParens = true;
|
|
104
|
+
else if (char === ")") inParens = false;
|
|
105
|
+
else if ((char === "," || /\s/.test(char)) && !inParens) {
|
|
106
|
+
if (current.trim()) specs.push(current.trim());
|
|
107
|
+
current = "";
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
current += char;
|
|
111
|
+
}
|
|
112
|
+
if (current.trim()) specs.push(current.trim());
|
|
113
|
+
return specs;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* The tool a spec names. A rule-shaped entry (`Bash(git push:*)`) names its
|
|
118
|
+
* whole tool: Claude Code grants or removes the entire tool for it in an agent
|
|
119
|
+
* file, never only the rule's commands, so `disallowedTools: Bash(git push:*)`
|
|
120
|
+
* removes `bash`. Anything that is not `Name(…)` is taken as a plain name.
|
|
121
|
+
*/
|
|
122
|
+
function specToolName(spec: string): string {
|
|
123
|
+
const open = spec.indexOf("(");
|
|
124
|
+
return open > 0 && spec.endsWith(")") ? spec.slice(0, open) : spec;
|
|
125
|
+
}
|
|
126
|
+
|
|
69
127
|
/**
|
|
70
128
|
* A frontmatter tool list (comma string or YAML list) as pi tool names: Claude
|
|
71
129
|
* Code spellings map through the alias table (`Glob` → `find`, `WebFetch` →
|
|
72
130
|
* `web_fetch`, `Task` → `Agent`, …), pi names and `mcp__*` pass through,
|
|
73
|
-
* duplicates collapse.
|
|
131
|
+
* rule-shaped entries reduce to their tool, duplicates collapse. A list that
|
|
132
|
+
* contains `*` returns `["*"]`; `parseAgentFile` reads that as "all tools".
|
|
133
|
+
* Exported for tests.
|
|
74
134
|
*/
|
|
75
135
|
export function parseToolList(raw: unknown): string[] | undefined {
|
|
76
|
-
const
|
|
77
|
-
typeof raw === "string"
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
136
|
+
const entries =
|
|
137
|
+
typeof raw === "string" ? [raw] : Array.isArray(raw) ? raw.filter((t): t is string => typeof t === "string") : undefined;
|
|
138
|
+
const specs = entries?.flatMap(splitToolSpecs);
|
|
139
|
+
if (!specs || specs.length === 0) return undefined;
|
|
140
|
+
if (specs.includes("*")) return ["*"];
|
|
141
|
+
return [...new Set(specs.map((spec) => normalizeToolName(specToolName(spec))))];
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* An agent file's `tools` allowlist. Claude Code reads a list containing `*`
|
|
146
|
+
* as "all tools", the same as no list; kept as `["*"]` the allowlist matched
|
|
147
|
+
* no tool and every spawn failed.
|
|
148
|
+
*/
|
|
149
|
+
function parseAllowlist(raw: unknown): string[] | undefined {
|
|
150
|
+
const tools = parseToolList(raw);
|
|
151
|
+
return tools?.includes("*") ? undefined : tools;
|
|
87
152
|
}
|
|
88
153
|
|
|
89
154
|
export function parseAgentFile(path: string, content: string): AgentDefinition | undefined {
|
|
@@ -98,7 +163,7 @@ export function parseAgentFile(path: string, content: string): AgentDefinition |
|
|
|
98
163
|
return {
|
|
99
164
|
name,
|
|
100
165
|
description: typeof fm.description === "string" ? fm.description : "",
|
|
101
|
-
tools:
|
|
166
|
+
tools: parseAllowlist(fm.tools),
|
|
102
167
|
excludeTools: disallowed.length > 0 ? [...new Set(disallowed)] : undefined,
|
|
103
168
|
// "inherit" is Claude Code's way of saying "use the session model".
|
|
104
169
|
model: typeof fm.model === "string" && fm.model !== "inherit" ? fm.model : undefined,
|
|
@@ -109,11 +174,25 @@ export function parseAgentFile(path: string, content: string): AgentDefinition |
|
|
|
109
174
|
|
|
110
175
|
/**
|
|
111
176
|
* Lowest to highest precedence: the catalog bundled with this package, then the
|
|
112
|
-
* user's `~/.claude/agents`, then the project's `.claude/agents
|
|
113
|
-
*
|
|
177
|
+
* user's `~/.claude/agents`, then the project's `.claude/agents` (`~/.onecode`
|
|
178
|
+
* and `.onecode` in independent mode, lib/config-mode.ts). A user or project
|
|
179
|
+
* definition with the same name replaces a bundled one.
|
|
114
180
|
*/
|
|
115
181
|
export function agentDirs(cwd: string, home: string, bundled?: string): string[] {
|
|
116
|
-
return [...(bundled ? [bundled] : []), join(
|
|
182
|
+
return [...(bundled ? [bundled] : []), join(userConfigDir(home), "agents"), join(projectConfigDir(cwd), "agents")];
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/** The agent files the package ships (general-purpose, explore, plan, …). */
|
|
186
|
+
export const BUNDLED_AGENTS_DIR = join(dirname(fileURLToPath(import.meta.url)), "..", "..", "agents");
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Every agent-file source in rank order, as the Agent tool loads them:
|
|
190
|
+
* bundled, then plugin agents, then the user and project folders. Workflows
|
|
191
|
+
* resolve `agentType` from the same list (the code-defined guide is the Agent
|
|
192
|
+
* tool's alone).
|
|
193
|
+
*/
|
|
194
|
+
export function agentFileSources(cwd: string, home: string, pluginAgentDirs: readonly (string | AgentSource)[]): Array<string | AgentSource> {
|
|
195
|
+
return [BUNDLED_AGENTS_DIR, ...pluginAgentDirs, ...agentDirs(cwd, home)];
|
|
117
196
|
}
|
|
118
197
|
|
|
119
198
|
/** A directory whose agents are exposed as `<namespace>:<name>` (plugins). */
|
|
@@ -122,10 +201,19 @@ export interface AgentSource {
|
|
|
122
201
|
namespace?: string;
|
|
123
202
|
}
|
|
124
203
|
|
|
204
|
+
/** Agents defined in code (`one-code-guide`), taken as they are: never copied, so a lazy prompt stays lazy. */
|
|
205
|
+
export interface CodeAgents {
|
|
206
|
+
agents: readonly AgentDefinition[];
|
|
207
|
+
}
|
|
208
|
+
|
|
125
209
|
/** Later sources override earlier ones on name collisions. */
|
|
126
|
-
export function discoverAgents(sources: Array<string | AgentSource>): AgentDefinition[] {
|
|
210
|
+
export function discoverAgents(sources: Array<string | AgentSource | CodeAgents>): AgentDefinition[] {
|
|
127
211
|
const byName = new Map<string, AgentDefinition>();
|
|
128
212
|
for (const source of sources) {
|
|
213
|
+
if (typeof source !== "string" && "agents" in source) {
|
|
214
|
+
for (const agent of source.agents) byName.set(agent.name, agent);
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
129
217
|
const { dir, namespace } = typeof source === "string" ? { dir: source, namespace: undefined } : source;
|
|
130
218
|
for (const file of collectMarkdownFiles(dir)) {
|
|
131
219
|
try {
|
|
@@ -145,11 +233,12 @@ export function discoverAgents(sources: Array<string | AgentSource>): AgentDefin
|
|
|
145
233
|
* Tools a child cannot function without, re-added when an agent file's `tools`
|
|
146
234
|
* allowlist omits them: pi's allowlist filters built-ins, extension tools AND
|
|
147
235
|
* injected custom tools by exact name, so a CC-style `tools: Read, Grep` would
|
|
148
|
-
* otherwise also strip the child's report
|
|
149
|
-
* deferred-tool loader and the runtime's
|
|
150
|
-
* allowlist never strips its own plumbing
|
|
236
|
+
* otherwise also strip the child's report channels (`SendMessage` → main and
|
|
237
|
+
* the final `SubagentHandback`), its deferred-tool loader and the runtime's
|
|
238
|
+
* `structured_output`. Claude Code's allowlist never strips its own plumbing
|
|
239
|
+
* either.
|
|
151
240
|
*/
|
|
152
|
-
const ALLOWLIST_ESSENTIALS = ["SendMessage", "tool_search", "structured_output"];
|
|
241
|
+
const ALLOWLIST_ESSENTIALS = ["SendMessage", SUBAGENT_HANDBACK, "tool_search", "structured_output"];
|
|
153
242
|
|
|
154
243
|
/** Apply an agent's allowlist to pi's `tools` option, keeping the essentials. */
|
|
155
244
|
export function childToolAllowlist(tools: string[] | undefined): string[] | undefined {
|
|
@@ -168,3 +257,29 @@ export function usableAllowlistedTools(registered: string[], allowlist: string[]
|
|
|
168
257
|
const available = new Set(registered);
|
|
169
258
|
return allowlist.filter((name) => available.has(name));
|
|
170
259
|
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* pi's session tool options for a named agent: its allowlist with the child's
|
|
263
|
+
* plumbing re-added, and its denylist. The one builder both runners use (the
|
|
264
|
+
* subagent runner and the workflow runner), so an agent file means the same
|
|
265
|
+
* thing wherever it runs; the workflow runner once passed the raw allowlist and
|
|
266
|
+
* no denylist, which stripped `structured_output` and ignored `disallowedTools`
|
|
267
|
+
* (SUBAGENTS-WORKFLOWS-REVIEW-2026-09-26 H2, H3).
|
|
268
|
+
*/
|
|
269
|
+
export function agentToolOptions(agent: AgentDefinition | undefined): { tools?: string[]; excludeTools?: string[] } {
|
|
270
|
+
return { tools: childToolAllowlist(agent?.tools), excludeTools: agent?.excludeTools };
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* The fail-loud error for an agent whose `tools` allowlist matched no tool the
|
|
275
|
+
* session registered, or undefined when the agent is usable. pi drops unknown
|
|
276
|
+
* names silently, so without this the agent would run with no tools and
|
|
277
|
+
* "complete" with an excuse.
|
|
278
|
+
*/
|
|
279
|
+
export function unusableAllowlistError(agent: AgentDefinition | undefined, registered: string[]): string | undefined {
|
|
280
|
+
if (!agent?.tools || usableAllowlistedTools(registered, agent.tools).length > 0) return undefined;
|
|
281
|
+
return (
|
|
282
|
+
`Agent "${agent.name}" lists tools (${agent.tools.join(", ")}) that match no available tool. ` +
|
|
283
|
+
"Use Claude Code names (Read, Edit, Write, Bash, Grep, Glob, WebFetch, WebSearch, NotebookEdit, Skill, Agent, SendMessage) or pi names (read, edit, write, bash, grep, find, ls, …) in the agent file's `tools` list."
|
|
284
|
+
);
|
|
285
|
+
}
|
|
@@ -10,15 +10,14 @@
|
|
|
10
10
|
* not read: both project files live in the repository, and a checked-in `env`
|
|
11
11
|
* block must not get to pick which provider receives subagent tasks — the
|
|
12
12
|
* same containment rule as `autoMode` config.
|
|
13
|
-
* - `subagentModel` — One Code's own top-level setting
|
|
14
|
-
* `autoMode.classifierModel`. Wins over the env var when both are set,
|
|
13
|
+
* - `subagentModel` — One Code's own top-level setting. Wins over the env var when both are set,
|
|
15
14
|
* because it is the more specific statement of intent. It is One Code's key,
|
|
16
15
|
* not Claude Code's: it is written to and read from `~/.onecode/settings.json`
|
|
17
16
|
* (+ managed settings), never from `~/.claude`, where an old One Code build may
|
|
18
17
|
* have left a stale value the current session cannot reach. Claude Code's own
|
|
19
18
|
* `CLAUDE_CODE_SUBAGENT_MODEL` env block is still honoured from `~/.claude`
|
|
20
19
|
* (that key *is* Claude Code's). See "Own state, borrowed config" in
|
|
21
|
-
* docs/decisions/memory-state.md.
|
|
20
|
+
* working-docs/decisions/memory-state.md.
|
|
22
21
|
*
|
|
23
22
|
* The env var additionally applies only to Claude-family sessions (see
|
|
24
23
|
* `applicableSubagentDefault`): it is Claude Code's knob, and its typical
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
export const DELEGATION_STEER = [
|
|
19
|
-
|
|
20
|
-
'Make
|
|
21
|
-
"Search directly
|
|
22
|
-
"When the agent has answered, report its answer and move on — do not re-read the files it already covered.",
|
|
19
|
+
"Delegation policy: when a request requires reading MANY files (a codebase overview, how a feature works across modules, exploring unfamiliar code), do NOT sweep the files yourself.",
|
|
20
|
+
'Make one Agent tool call per independent question, with subagent_type: "explore" and the complete question as the task; for several independent questions, issue those calls together in one message. The agent searches in its own separate context and returns just the answer; reading file after file yourself fills your context and degrades your answer.',
|
|
21
|
+
"Search directly for a single targeted lookup: one known file or symbol, or a word one grep can find everywhere.",
|
|
22
|
+
"When the agent has answered, report its answer and move on — do not re-read the files it already covered, except one you are about to edit (an edit needs a read first).",
|
|
23
23
|
].join("\n");
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The fork's side of reading the parent's prompt cache (decisions/caching.md,
|
|
3
|
+
* "A call that inherits the session's context reads the session's cache").
|
|
4
|
+
*
|
|
5
|
+
* A fork's own session builds its requests from its own system prompt, tools
|
|
6
|
+
* and reminder stack, so every fork re-read the parent's whole transcript
|
|
7
|
+
* uncached: on a parent near a 1M-token window, the whole window per fork.
|
|
8
|
+
* This inline extension, loaded last in a fork's session, sends the parent's
|
|
9
|
+
* last captured request instead, with the fork's own messages after it:
|
|
10
|
+
*
|
|
11
|
+
* - `context_with_system` (it runs after every `context` handler, so the
|
|
12
|
+
* fork's reminder stack is already on the messages it drops) removes the
|
|
13
|
+
* messages the capture carries, leaving pi to convert only the fork's tail;
|
|
14
|
+
* - `before_provider_request` (inline extensions load after the path ones, so
|
|
15
|
+
* tool-search has already edited the body) replaces everything but the tail
|
|
16
|
+
* with the captured body (`forkRequestPayload`);
|
|
17
|
+
* - `before_provider_headers` sends the parent's session-affinity headers, so a
|
|
18
|
+
* gateway such as OpenRouter routes the fork to the host holding the cache.
|
|
19
|
+
*
|
|
20
|
+
* Both steps check the same thing first (the capture's model and its boundary
|
|
21
|
+
* message in this context); when either fails, or the tail leaves less than
|
|
22
|
+
* `MIN_REPLAY_OUTPUT_TOKENS` of the captured output room, the request goes out
|
|
23
|
+
* the ordinary way, whole, and uncached. That happens only for a fork that
|
|
24
|
+
* compacted its own history away, runs on another model, or has nearly
|
|
25
|
+
* filled the window.
|
|
26
|
+
*/
|
|
27
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
28
|
+
import { DEFER_CHANNEL } from "../lib/deferred.ts";
|
|
29
|
+
import { type AffinityModel, affinityHeaders, captureMatches, forkOutputRoom, forkRequestPayload, forkBaselineNames, MIN_REPLAY_OUTPUT_TOKENS, type RequestCapture, uncoveredMessages } from "../lib/request-replay.ts";
|
|
30
|
+
|
|
31
|
+
type ModelRef = { api?: string; provider?: string; id?: string };
|
|
32
|
+
|
|
33
|
+
/** The APIs whose fork splice (`forkRequestPayload`) handles the body's shape. */
|
|
34
|
+
const SPLICED_FORK_APIS: ReadonlySet<string> = new Set(["anthropic-messages", "openai-completions", "openai-responses", "azure-openai-responses", "openai-codex-responses"]);
|
|
35
|
+
|
|
36
|
+
export function forkCacheExtension(capture: RequestCapture) {
|
|
37
|
+
return (pi: ExtensionAPI) => {
|
|
38
|
+
// The fork advertises the parent's tools, where SendMessage is deferred
|
|
39
|
+
// (subagents/index.ts). Defer the fork's own SendMessage the same way, so a
|
|
40
|
+
// tool_search load reaches it: on a model without tool references the load
|
|
41
|
+
// appends it, and elsewhere the parent's compatible schema (to: "main")
|
|
42
|
+
// already declares it. Inline extensions load after tool-search.
|
|
43
|
+
pi.events.emit(DEFER_CHANNEL, { name: "SendMessage", keywords: ["message", "main", "report", "progress"] });
|
|
44
|
+
/** Set by the context step for the request it shaped; the payload step splices only then. */
|
|
45
|
+
let shaped = false;
|
|
46
|
+
/** The tool names of the fork's first request: anything added later was loaded during the run. */
|
|
47
|
+
let baseline: Set<string> | undefined;
|
|
48
|
+
|
|
49
|
+
pi.on("context_with_system", (event, ctx) => {
|
|
50
|
+
shaped = false;
|
|
51
|
+
const covers = capture.covers;
|
|
52
|
+
// Bedrock and Google nest their tools and need joined turns and the
|
|
53
|
+
// fork's own abort signal, which the fork splice does not handle: their
|
|
54
|
+
// forks go out whole instead.
|
|
55
|
+
if (!covers || !SPLICED_FORK_APIS.has(capture.api) || !captureMatches(capture, ctx.model as ModelRef | undefined)) return undefined;
|
|
56
|
+
const tail = uncoveredMessages(event.messages as { role: string; timestamp?: number }[], covers);
|
|
57
|
+
if (!tail) return undefined;
|
|
58
|
+
// Too little output room left after the prefix: send the fork whole
|
|
59
|
+
// (pi's overflow handling then compacts it) rather than a splice the
|
|
60
|
+
// window cannot hold. The messages' JSON overstates the wire tail.
|
|
61
|
+
const room = forkOutputRoom(capture, tail.filter((message) => message.role !== "system"));
|
|
62
|
+
if (room !== undefined && room < MIN_REPLAY_OUTPUT_TOKENS) return undefined;
|
|
63
|
+
shaped = true;
|
|
64
|
+
return { messages: tail as typeof event.messages };
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// Route to the parent's host: a gateway picks it by the session-affinity
|
|
68
|
+
// headers, and the parent's cache lives there. Harmless on a whole request.
|
|
69
|
+
pi.on("before_provider_headers", (event, ctx) => {
|
|
70
|
+
if (!capture.sessionId || !captureMatches(capture, ctx.model as ModelRef | undefined)) return;
|
|
71
|
+
Object.assign(event.headers, affinityHeaders(ctx.model as AffinityModel, capture.sessionId));
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
pi.on("before_provider_request", (event, ctx) => {
|
|
75
|
+
if (!shaped || !captureMatches(capture, ctx.model as ModelRef | undefined)) return undefined;
|
|
76
|
+
shaped = false;
|
|
77
|
+
const payload = event.payload as Record<string, unknown>;
|
|
78
|
+
baseline ??= forkBaselineNames(payload, capture.api);
|
|
79
|
+
return forkRequestPayload(capture, payload, baseline);
|
|
80
|
+
});
|
|
81
|
+
};
|
|
82
|
+
}
|