one-code-extension 0.4.1 → 0.5.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 +32 -23
- package/docs/guide/doctor.md +20 -13
- package/docs/guide/hooks.md +18 -3
- package/docs/guide/installation.md +27 -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 +123 -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 +515 -0
- package/extensions/background/index.ts +514 -236
- package/extensions/background/loop-fire.ts +136 -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 +52 -0
- package/extensions/background/wakeup.ts +159 -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 +88 -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 +229 -71
- package/extensions/btw/panel.ts +228 -100
- package/extensions/btw/prompt.ts +41 -4
- package/extensions/claude-compat/index.ts +7 -11
- package/extensions/claude-context/index.ts +446 -58
- package/extensions/compaction/cut.ts +157 -0
- package/extensions/compaction/index.ts +216 -75
- package/extensions/compaction/kept-thinking.ts +62 -0
- package/extensions/compaction/prompt.ts +15 -12
- package/extensions/context-budget/index.ts +24 -5
- package/extensions/context-management/index.ts +25 -0
- 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 +72 -19
- 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 +337 -26
- package/extensions/file-tracker/replay.ts +96 -10
- package/extensions/file-tracker/restore.ts +63 -0
- package/extensions/file-tracker/results.ts +66 -0
- package/extensions/file-tracker/shell-reads.ts +211 -0
- package/extensions/file-tracker/tracker.ts +32 -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 +198 -31
- package/extensions/hooks/matcher.ts +3 -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 +13 -5
- 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/lib/agent-cron.ts +130 -0
- package/extensions/lib/agent-loader.ts +15 -1
- package/extensions/lib/agent-view.ts +85 -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 +42 -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 +78 -0
- package/extensions/lib/context-stack.ts +81 -0
- package/extensions/lib/deferred.ts +219 -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/local-command.ts +47 -13
- 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 +174 -0
- package/extensions/lib/model-catalog/models-dev.json +18297 -0
- package/extensions/lib/model-catalog/openrouter.json +5252 -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 +308 -64
- 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 +21 -2
- package/extensions/lib/plan-mode-channels.ts +20 -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/process-tree.ts +131 -8
- package/extensions/lib/prompt-options.ts +82 -0
- package/extensions/lib/queued-delivery.ts +44 -0
- package/extensions/lib/reminders.ts +364 -58
- package/extensions/lib/replaced-builtins.mjs +199 -0
- package/extensions/lib/replay-call.ts +70 -0
- package/extensions/lib/request-replay.ts +439 -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 +13 -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 +113 -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 +149 -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 +143 -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 +70 -4
- 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 +87 -5
- 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 +209 -71
- 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 +151 -67
- 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/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 +1300 -381
- package/extensions/permissions/matcher.ts +425 -74
- package/extensions/permissions/modes.ts +6 -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 +156 -69
- package/extensions/plan-mode/reminder.ts +89 -21
- 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 +61 -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 +12 -7
- package/extensions/recap/index.ts +65 -60
- 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/code-review.ts +97 -0
- package/extensions/skill/index.ts +421 -101
- package/extensions/skill/invoke.ts +128 -18
- 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 +116 -23
- package/extensions/subagents/announce.ts +69 -0
- package/extensions/subagents/default-model.ts +2 -3
- package/extensions/subagents/delegation-steer.ts +4 -4
- package/extensions/subagents/fork-cache.ts +76 -0
- package/extensions/subagents/guide-agent.ts +189 -0
- package/extensions/subagents/hand-back-review.ts +3 -0
- package/extensions/subagents/index.ts +1493 -824
- package/extensions/subagents/live-runs.ts +26 -6
- package/extensions/subagents/model-select.ts +38 -25
- package/extensions/subagents/outcome.ts +2 -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/runner.ts +108 -80
- package/extensions/subagents/runs.ts +39 -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 +131 -47
- package/extensions/system-prompt/template.ts +24 -50
- 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 +175 -13
- 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/announce.ts +16 -0
- package/extensions/tool-search/index.ts +189 -41
- 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 +105 -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 +145 -162
- package/extensions/workflow/records.ts +1 -0
- package/extensions/workflow/run-manager.ts +29 -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 +121 -39
- package/extensions/worktree/powershell-guards.ts +167 -0
- package/extensions/worktree/rewrite.ts +14 -16
- package/package.json +18 -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
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Claude Code's `
|
|
3
|
-
*
|
|
2
|
+
* Claude Code's `# gitStatus` section — part of the context reminder on the
|
|
3
|
+
* first user message (lib/claude-context.ts buildContextBlock) in a git repo,
|
|
4
|
+
* identical across model tiers, and a one-time snapshot:
|
|
4
5
|
* CC states it is "the git status at the start of the conversation" and "will not
|
|
5
6
|
* update during the conversation", so it is computed once per session and frozen.
|
|
6
7
|
*
|
|
@@ -11,11 +12,18 @@
|
|
|
11
12
|
* the status and the log are whole-output `.trim()`ed — which is why a leading
|
|
12
13
|
* `??`/` M` porcelain line renders flush-left in the capture.
|
|
13
14
|
*
|
|
15
|
+
* Bounded the way Claude Code bounds it: the status is clipped at 2,000
|
|
16
|
+
* characters with Claude Code's note, a clean tree reads `(clean)`, an empty
|
|
17
|
+
* user name drops the `Git user:` line, and a `git status` that fails or hangs
|
|
18
|
+
* past the timeout drops the whole block, as Claude Code does on a failed
|
|
19
|
+
* snapshot.
|
|
20
|
+
*
|
|
14
21
|
* The module is pure apart from `defaultRunner`; `collectGitStatus` takes an
|
|
15
22
|
* injectable runner so the git commands can be faked in unit tests.
|
|
16
23
|
*/
|
|
17
24
|
|
|
18
25
|
import { execFileSync } from "node:child_process";
|
|
26
|
+
import { HARNESS_GIT_CONFIG } from "./git.ts";
|
|
19
27
|
|
|
20
28
|
export interface GitSnapshot {
|
|
21
29
|
branch: string;
|
|
@@ -28,9 +36,27 @@ export interface GitSnapshot {
|
|
|
28
36
|
}
|
|
29
37
|
|
|
30
38
|
const HEADER =
|
|
31
|
-
"gitStatus
|
|
39
|
+
"# gitStatus\nThis is the git status at the start of the conversation. " +
|
|
32
40
|
"Note that this status is a snapshot in time, and will not update during the conversation.";
|
|
33
41
|
|
|
42
|
+
/** The main session's system-prompt extension claims the snapshot on this channel; a child session never does. */
|
|
43
|
+
export const GIT_SNAPSHOT_OWNER_CHANNEL = "one-code:git-snapshot-owner";
|
|
44
|
+
|
|
45
|
+
/** Claude Code's limit on the status inside the block, in characters. */
|
|
46
|
+
export const GIT_STATUS_MAX_CHARS = 2000;
|
|
47
|
+
|
|
48
|
+
/** Each git command's time limit: a hung `git status` (a network filesystem) must not block the first turn. */
|
|
49
|
+
export const GIT_TIMEOUT_MS = 10_000;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* The status as the block carries it: cut at 2,000 characters with Claude
|
|
53
|
+
* Code's note, which names the shell tool the model has.
|
|
54
|
+
*/
|
|
55
|
+
export function clipGitStatus(status: string, shellTool = "bash"): string {
|
|
56
|
+
if (status.length <= GIT_STATUS_MAX_CHARS) return status;
|
|
57
|
+
return `${status.substring(0, GIT_STATUS_MAX_CHARS)}\n... (truncated because it exceeds 2k characters. If you need more information, run "git status" using ${shellTool})`;
|
|
58
|
+
}
|
|
59
|
+
|
|
34
60
|
/** Assemble CC's block from a snapshot. Pure; byte-exact against the captures. */
|
|
35
61
|
export function formatGitStatus(s: GitSnapshot): string {
|
|
36
62
|
return [
|
|
@@ -40,10 +66,9 @@ export function formatGitStatus(s: GitSnapshot): string {
|
|
|
40
66
|
"",
|
|
41
67
|
`Main branch (you will usually use this for PRs): ${s.mainBranch}`,
|
|
42
68
|
"",
|
|
43
|
-
`Git user: ${s.user}`,
|
|
44
|
-
"",
|
|
69
|
+
...(s.user ? [`Git user: ${s.user}`, ""] : []),
|
|
45
70
|
"Status:",
|
|
46
|
-
s.status,
|
|
71
|
+
s.status || "(clean)",
|
|
47
72
|
"",
|
|
48
73
|
"Recent commits:",
|
|
49
74
|
s.commits,
|
|
@@ -56,7 +81,14 @@ export type GitRunner = (args: string[]) => string | null;
|
|
|
56
81
|
function defaultRunner(cwd: string): GitRunner {
|
|
57
82
|
return (args) => {
|
|
58
83
|
try {
|
|
59
|
-
return execFileSync("git",
|
|
84
|
+
return execFileSync("git", [...HARNESS_GIT_CONFIG, ...args], {
|
|
85
|
+
cwd,
|
|
86
|
+
encoding: "utf8",
|
|
87
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
88
|
+
timeout: GIT_TIMEOUT_MS,
|
|
89
|
+
// A status over the 1 MiB default would fail instead of being clipped.
|
|
90
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
91
|
+
}).trim();
|
|
60
92
|
} catch {
|
|
61
93
|
return null;
|
|
62
94
|
}
|
|
@@ -75,19 +107,25 @@ function resolveMainBranch(run: GitRunner, branch: string): string {
|
|
|
75
107
|
|
|
76
108
|
/**
|
|
77
109
|
* CC's `gitStatus:` block for `cwd`, or null when `cwd` is not inside a git work
|
|
78
|
-
* tree
|
|
79
|
-
*
|
|
110
|
+
* tree or `git status` fails (or times out): an empty status would claim a
|
|
111
|
+
* clean tree. Other command failures degrade to empty fields rather than
|
|
112
|
+
* dropping the whole block. `shellTool` is the tool the clip note tells the
|
|
113
|
+
* model to run `git status` with.
|
|
80
114
|
*/
|
|
81
|
-
export function collectGitStatus(cwd: string, runner?: GitRunner): string | null {
|
|
115
|
+
export function collectGitStatus(cwd: string, runner?: GitRunner, shellTool = "bash"): string | null {
|
|
82
116
|
const run = runner ?? defaultRunner(cwd);
|
|
83
117
|
if (run(["rev-parse", "--is-inside-work-tree"]) !== "true") return null;
|
|
84
118
|
|
|
85
119
|
const branch = run(["branch", "--show-current"]) ?? "";
|
|
120
|
+
const mainBranch = resolveMainBranch(run, branch);
|
|
121
|
+
const user = run(["config", "user.name"]) ?? "";
|
|
122
|
+
const status = run(["status", "--porcelain"]);
|
|
123
|
+
if (status === null) return null;
|
|
86
124
|
return formatGitStatus({
|
|
87
125
|
branch,
|
|
88
|
-
mainBranch
|
|
89
|
-
user
|
|
90
|
-
status:
|
|
126
|
+
mainBranch,
|
|
127
|
+
user,
|
|
128
|
+
status: clipGitStatus(status, shellTool),
|
|
91
129
|
commits: run(["log", "-5", "--format=%h %s"]) ?? "",
|
|
92
130
|
});
|
|
93
131
|
}
|
package/extensions/lib/git.ts
CHANGED
|
@@ -1,24 +1,56 @@
|
|
|
1
1
|
/** Shared git helpers — pure functions only (safe to import across extensions). */
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Global options for every git command the harness runs on its own (startup
|
|
5
|
+
* git status, the classifier's git status line, consent checks, worktree
|
|
6
|
+
* bookkeeping). git honours the checkout's own `.git/config`, and
|
|
7
|
+
* `core.fsmonitor` there names a
|
|
8
|
+
* program that `status` and other index reads run — so a directory whose
|
|
9
|
+
* `.git` came from an archive or a copied tree would run it the moment One
|
|
10
|
+
* Code starts in it, before any prompt (SECURITY-REVIEW-2026-09-23 M5).
|
|
11
|
+
* `--no-optional-locks` stops `status` rewriting the index, which would run the
|
|
12
|
+
* checkout's `post-index-change` hook. The model's own git commands are judged
|
|
13
|
+
* by the permission gate instead (auto-mode/git-checkout-programs.ts).
|
|
14
|
+
*/
|
|
15
|
+
export const HARNESS_GIT_CONFIG: readonly string[] = ["-c", "core.fsmonitor=false", "--no-optional-locks"];
|
|
16
|
+
|
|
3
17
|
import { execFile } from "node:child_process";
|
|
4
18
|
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
19
|
+
import { devNull } from "node:os";
|
|
5
20
|
import { basename, dirname, isAbsolute, join, resolve } from "node:path";
|
|
21
|
+
import { comparablePath, tryRealpath } from "./paths.ts";
|
|
22
|
+
|
|
23
|
+
/** Harness worktree bookkeeping must not execute repository hooks before the tool permission gate. */
|
|
24
|
+
export const HARNESS_GIT_NO_HOOKS: readonly string[] = ["-c", `core.hooksPath=${devNull}`];
|
|
6
25
|
|
|
7
26
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* ground-truth line after a `git status` call (permissions/index.ts).
|
|
27
|
+
* `git status` output for `cwd` with the given arguments, or undefined when
|
|
28
|
+
* git could not say (not a repo, git missing, timeout). Asynchronous so the
|
|
29
|
+
* tool_call hook it runs from does not stall the event loop; used for the
|
|
30
|
+
* classifier transcript's gitStatus line (auto-mode/git-status-meta.ts).
|
|
13
31
|
*/
|
|
14
|
-
export function
|
|
32
|
+
export function gitStatusOutput(cwd: string, args: readonly string[]): Promise<string | undefined> {
|
|
15
33
|
return new Promise((resolvePromise) => {
|
|
16
|
-
execFile("git", [
|
|
17
|
-
resolvePromise(error ? undefined : stdout
|
|
34
|
+
execFile("git", [...HARNESS_GIT_CONFIG, ...args], { cwd, encoding: "utf8", timeout: 5_000, windowsHide: true }, (error, stdout) => {
|
|
35
|
+
resolvePromise(error ? undefined : stdout);
|
|
18
36
|
});
|
|
19
37
|
});
|
|
20
38
|
}
|
|
21
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Every worktree of the repository `cwd` belongs to (`git worktree list`),
|
|
42
|
+
* main checkout included, in native resolved form; undefined when git could
|
|
43
|
+
* not list them. The worktree guards refuse git aimed at any of them.
|
|
44
|
+
*/
|
|
45
|
+
export async function repositoryWorktrees(cwd: string): Promise<string[] | undefined> {
|
|
46
|
+
const out = await gitStatusOutput(cwd, ["worktree", "list", "--porcelain"]);
|
|
47
|
+
if (out === undefined) return undefined;
|
|
48
|
+
return out
|
|
49
|
+
.split("\n")
|
|
50
|
+
.filter((line) => line.startsWith("worktree "))
|
|
51
|
+
.map((line) => resolve(line.slice("worktree ".length)));
|
|
52
|
+
}
|
|
53
|
+
|
|
22
54
|
/**
|
|
23
55
|
* The nearest checkout root at or above `startDir`: the directory holding a
|
|
24
56
|
* `.git` entry (a directory for a main checkout, a file for a linked worktree
|
|
@@ -50,23 +82,53 @@ export function findProjectRoot(startDir: string): string | undefined {
|
|
|
50
82
|
return linkedWorktreeMainRoot(root) ?? root;
|
|
51
83
|
}
|
|
52
84
|
|
|
53
|
-
/**
|
|
54
|
-
|
|
85
|
+
/**
|
|
86
|
+
* The git dir a checkout root's `.git` FILE points at (a linked worktree or a
|
|
87
|
+
* submodule: `gitdir: <path>`), absolute; undefined when `.git` is a directory,
|
|
88
|
+
* missing, or unreadable.
|
|
89
|
+
*/
|
|
90
|
+
export function gitdirFileTarget(root: string): string | undefined {
|
|
55
91
|
const dotGit = join(root, ".git");
|
|
56
|
-
let gitdir: string;
|
|
57
92
|
try {
|
|
58
93
|
if (!statSync(dotGit).isFile()) return undefined;
|
|
59
94
|
const match = /^gitdir:\s*(.+?)\s*$/m.exec(readFileSync(dotGit, "utf-8"));
|
|
60
95
|
if (!match) return undefined;
|
|
61
|
-
|
|
96
|
+
// resolve in both cases: git writes `C:/…` on Windows, and callers compare native paths.
|
|
97
|
+
return isAbsolute(match[1]) ? resolve(match[1]) : resolve(root, match[1]);
|
|
62
98
|
} catch {
|
|
63
99
|
return undefined;
|
|
64
100
|
}
|
|
65
|
-
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* For a linked worktree root, the main checkout it belongs to; undefined
|
|
105
|
+
* otherwise. Exported for tests. The `.git` file alone proves nothing: an
|
|
106
|
+
* archive or copied tree can carry `gitdir: /trusted/.git/worktrees/x` and so
|
|
107
|
+
* borrow that repository's identity (its settings and remembered consent). git
|
|
108
|
+
* records the way back in `<gitdir>/gitdir`, so only a worktree that record
|
|
109
|
+
* names is inherited.
|
|
110
|
+
*/
|
|
111
|
+
export function linkedWorktreeMainRoot(root: string): string | undefined {
|
|
112
|
+
const absolute = gitdirFileTarget(root);
|
|
113
|
+
if (!absolute) return undefined;
|
|
66
114
|
// <main>/.git/worktrees/<name> → <main>. A submodule's gitdir points into
|
|
67
115
|
// <super>/.git/modules/<name> and is left alone.
|
|
68
116
|
const worktrees = dirname(absolute);
|
|
69
117
|
const mainDotGit = dirname(worktrees);
|
|
70
118
|
if (basename(worktrees) !== "worktrees" || basename(mainDotGit) !== ".git") return undefined;
|
|
119
|
+
if (!pointsBack(absolute, root)) return undefined;
|
|
71
120
|
return dirname(mainDotGit);
|
|
72
121
|
}
|
|
122
|
+
|
|
123
|
+
/** Whether the worktree record `gitdir` names `<root>/.git` (absolute, or relative to the record with `worktree.useRelativePaths`). */
|
|
124
|
+
function pointsBack(gitdir: string, root: string): boolean {
|
|
125
|
+
try {
|
|
126
|
+
const recorded = readFileSync(join(gitdir, "gitdir"), "utf-8").trim();
|
|
127
|
+
if (!recorded) return false;
|
|
128
|
+
const target = isAbsolute(recorded) ? resolve(recorded) : resolve(gitdir, recorded);
|
|
129
|
+
const dotGit = join(root, ".git");
|
|
130
|
+
return comparablePath(tryRealpath(target) ?? target) === comparablePath(tryRealpath(dotGit) ?? dotGit);
|
|
131
|
+
} catch {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2017 Max Brunsfeld
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
Binary file
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where the documentation the `one-code-guide` agent reads lives on this
|
|
3
|
+
* machine: One Code's own user guide (`docs/guide/`, shipped in the npm
|
|
4
|
+
* package next to `extensions/`) and the running pi's `docs/` and `examples/`
|
|
5
|
+
* (pi's `getDocsPath()`/`getExamplesPath()`, which name the host pi's copies in
|
|
6
|
+
* both install shapes; findings §6).
|
|
7
|
+
*
|
|
8
|
+
* The permissions extension makes these directories readable without a prompt
|
|
9
|
+
* (never writable), so the guide agent can read them on any model tier.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { existsSync } from "node:fs";
|
|
13
|
+
import { dirname, join } from "node:path";
|
|
14
|
+
import { fileURLToPath } from "node:url";
|
|
15
|
+
import { getDocsPath, getExamplesPath } from "@earendil-works/pi-coding-agent";
|
|
16
|
+
|
|
17
|
+
/** One Code's user guide, `<package>/docs/guide`; its `README.md` is the index. */
|
|
18
|
+
export const ONE_CODE_GUIDE_DIR = join(dirname(fileURLToPath(import.meta.url)), "..", "..", "docs", "guide");
|
|
19
|
+
|
|
20
|
+
export interface GuideDocs {
|
|
21
|
+
/** One Code's user guide. */
|
|
22
|
+
guide: string;
|
|
23
|
+
/** The running pi's docs (extensions, packages, settings, …); undefined when not found. */
|
|
24
|
+
piDocs?: string;
|
|
25
|
+
/** The running pi's examples (extensions among them); undefined when not found. */
|
|
26
|
+
piExamples?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function existing(read: () => string): string | undefined {
|
|
30
|
+
try {
|
|
31
|
+
const dir = read();
|
|
32
|
+
return existsSync(dir) ? dir : undefined;
|
|
33
|
+
} catch {
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function guideDocs(): GuideDocs {
|
|
39
|
+
return { guide: ONE_CODE_GUIDE_DIR, piDocs: existing(getDocsPath), piExamples: existing(getExamplesPath) };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** The directories that exist, for the permission gate's read-only roots. */
|
|
43
|
+
export function guideDocsDirs(docs: GuideDocs = guideDocs()): string[] {
|
|
44
|
+
return [existsSync(docs.guide) ? docs.guide : undefined, docs.piDocs, docs.piExamples].filter((dir): dir is string => !!dir);
|
|
45
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Output from a command in a one-shot run (`-p`, `--mode json`), where
|
|
3
|
+
* `ctx.ui.notify` is a no-op: pi wires no UI context there, so a message sent
|
|
4
|
+
* through it vanishes and the command exits silently.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* A user-facing notice: a TUI/RPC toast where there is UI, otherwise stderr.
|
|
11
|
+
* `console.error` never corrupts the `--mode json` event stream on stdout.
|
|
12
|
+
*/
|
|
13
|
+
export function notifyOrPrint(ctx: Pick<ExtensionContext, "hasUI" | "ui">, message: string, level: "info" | "warning" | "error"): void {
|
|
14
|
+
if (ctx.hasUI) ctx.ui.notify(message, level);
|
|
15
|
+
else console.error(message);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Whether the session can show a custom TUI component: a panel opened through
|
|
20
|
+
* `ctx.ui.custom`, or a component widget. RPC has UI but forwards only dialogs,
|
|
21
|
+
* notices and string-array widgets: its `custom()` resolves undefined and a
|
|
22
|
+
* component factory vanishes, so a command falls back to text there.
|
|
23
|
+
*/
|
|
24
|
+
export function canShowCustomUi(ctx: Pick<ExtensionContext, "hasUI" | "mode">): boolean {
|
|
25
|
+
return ctx.hasUI && ctx.mode !== "rpc";
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** The line saying a command whose panel cannot open in RPC shows a read-only listing instead. */
|
|
29
|
+
export function rpcReadOnlyText(command: string, manage: string): string {
|
|
30
|
+
return `${command} in RPC is read-only; use the TUI to ${manage}.`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** In RPC, say that a command whose panel cannot open shows a read-only listing instead. */
|
|
34
|
+
export function notifyRpcReadOnly(ctx: Pick<ExtensionContext, "mode" | "ui">, command: string, manage: string): string | undefined {
|
|
35
|
+
if (ctx.mode !== "rpc") return undefined;
|
|
36
|
+
const text = rpcReadOnlyText(command, manage);
|
|
37
|
+
ctx.ui.notify(text, "info");
|
|
38
|
+
// Returned so a command reporting its result can include it.
|
|
39
|
+
return text;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** A command's answer in a one-shot run: stdout in print mode, stderr in json mode (stdout is the event stream there). */
|
|
43
|
+
export function printAnswer(ctx: Pick<ExtensionContext, "mode">, text: string): void {
|
|
44
|
+
if (ctx.mode === "print") console.log(text);
|
|
45
|
+
else console.error(text);
|
|
46
|
+
}
|
|
@@ -22,28 +22,28 @@ import type { InlineExtension } from "@earendil-works/pi-coding-agent";
|
|
|
22
22
|
import { applyPostToolUseOutcome } from "../hooks/protocol.ts";
|
|
23
23
|
import type { ChildHookCall, HookBridge } from "../hooks/subagent-bridge.ts";
|
|
24
24
|
import { REMINDER_CHANNEL } from "./reminders.ts";
|
|
25
|
+
import { SUBAGENT_HANDBACK } from "./subagent-handback.ts";
|
|
25
26
|
|
|
26
27
|
/** Tools the runtime itself injects; never run hooks for them. */
|
|
27
|
-
const DEFAULT_INTERNAL_TOOLS = new Set(["structured_output"]);
|
|
28
|
+
const DEFAULT_INTERNAL_TOOLS = new Set(["structured_output", SUBAGENT_HANDBACK]);
|
|
28
29
|
|
|
29
30
|
export interface HookGateOptions {
|
|
30
31
|
/** The child's agent type for the payload's `agent_type`, resolved per session id by the runner. */
|
|
31
32
|
agentTypeOf?: (sessionId: string | undefined) => string | undefined;
|
|
32
|
-
neverGate?: Set<string>;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
export function hookGateFactory(getBridge: () => HookBridge | undefined, options: HookGateOptions = {}): InlineExtension {
|
|
36
|
-
const neverGate = options.neverGate ?? DEFAULT_INTERNAL_TOOLS;
|
|
37
36
|
return {
|
|
38
37
|
name: "agent-hook-gate",
|
|
39
38
|
hidden: true,
|
|
40
39
|
factory: (pi) => {
|
|
41
|
-
const describe = (toolName: string, input: unknown, ctx: { cwd?: string; sessionManager?: { getSessionId?: () => string; getSessionFile?: () => string | undefined } } | undefined, fallbackCwd: string): ChildHookCall => {
|
|
40
|
+
const describe = (toolName: string, input: unknown, ctx: { cwd?: string; signal?: AbortSignal; sessionManager?: { getSessionId?: () => string; getSessionFile?: () => string | undefined } } | undefined, fallbackCwd: string): ChildHookCall => {
|
|
42
41
|
const sessionId = ctx?.sessionManager?.getSessionId?.();
|
|
43
42
|
return {
|
|
44
43
|
toolName,
|
|
45
44
|
input: (input ?? {}) as Record<string, unknown>,
|
|
46
45
|
cwd: ctx?.cwd ?? fallbackCwd,
|
|
46
|
+
signal: ctx?.signal,
|
|
47
47
|
sessionId,
|
|
48
48
|
transcriptPath: ctx?.sessionManager?.getSessionFile?.() ?? undefined,
|
|
49
49
|
agentType: options.agentTypeOf?.(sessionId),
|
|
@@ -51,7 +51,7 @@ export function hookGateFactory(getBridge: () => HookBridge | undefined, options
|
|
|
51
51
|
};
|
|
52
52
|
|
|
53
53
|
pi.on("tool_call", async (event, ctx) => {
|
|
54
|
-
if (
|
|
54
|
+
if (DEFAULT_INTERNAL_TOOLS.has(event.toolName)) return undefined;
|
|
55
55
|
try {
|
|
56
56
|
const bridge = getBridge();
|
|
57
57
|
if (!bridge) return undefined;
|
|
@@ -67,7 +67,7 @@ export function hookGateFactory(getBridge: () => HookBridge | undefined, options
|
|
|
67
67
|
});
|
|
68
68
|
|
|
69
69
|
pi.on("tool_result", async (event, ctx) => {
|
|
70
|
-
if (
|
|
70
|
+
if (DEFAULT_INTERNAL_TOOLS.has(event.toolName)) return undefined;
|
|
71
71
|
try {
|
|
72
72
|
const bridge = getBridge();
|
|
73
73
|
if (!bridge) return undefined;
|
|
@@ -78,7 +78,7 @@ export function hookGateFactory(getBridge: () => HookBridge | undefined, options
|
|
|
78
78
|
});
|
|
79
79
|
// Same assembly as the parent's tool_result handler; the parent already
|
|
80
80
|
// framed additionalContext as a <system-reminder>.
|
|
81
|
-
const content = applyPostToolUseOutcome(event.content, outcome);
|
|
81
|
+
const content = applyPostToolUseOutcome(event.content, outcome, event.toolName);
|
|
82
82
|
if (!content) return undefined;
|
|
83
83
|
return { content, isError: event.isError };
|
|
84
84
|
} catch {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* message with EMPTY content, `stopReason: "error"` and `errorMessage: "This
|
|
17
17
|
* operation was aborted"` — the fetch layer's AbortError, not pi's "aborted"
|
|
18
18
|
* label (measured over RPC on pi 0.85.0, STEERING-REVIEW-2026-09-05 L1;
|
|
19
|
-
* upstream ask docs/upstream_prs.md #18). The run's abort signal is still the
|
|
19
|
+
* upstream ask working-docs/upstream_prs.md #18). The run's abort signal is still the
|
|
20
20
|
* ground truth, and `ctx.signal` at `agent_end` is that signal (pi's
|
|
21
21
|
* `activeRun` outlives the event), so callers pass `ctx.signal?.aborted` and
|
|
22
22
|
* an `error` stop on an aborted run reads as "aborted": the user stopped the
|
|
@@ -34,6 +34,19 @@
|
|
|
34
34
|
* carry the outcome over from the runs' `agent_end`. Findings §3.
|
|
35
35
|
*/
|
|
36
36
|
|
|
37
|
+
/** A one-shot command failed before its user turn could settle (no agent_end to classify). */
|
|
38
|
+
export const ONE_SHOT_COMMAND_FAILED_CHANNEL = "one-code:one-shot-command-failed";
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The harness stopped the current turn as a failure (a broken provider stream,
|
|
42
|
+
* a classifier that cannot judge). Emit it before `ctx.abort()`: the run then
|
|
43
|
+
* ends `aborted`, which alone reads as a user cancel and exits 0.
|
|
44
|
+
*/
|
|
45
|
+
export const TURN_FAILED_CHANNEL = "one-code:turn-failed";
|
|
46
|
+
export interface TurnFailedEvent {
|
|
47
|
+
reason: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
37
50
|
/** How the last assistant message of a run ended. */
|
|
38
51
|
export type RunOutcome = "ok" | "aborted" | "error";
|
|
39
52
|
|
|
@@ -48,7 +61,10 @@ export interface RunMessage {
|
|
|
48
61
|
* "ok". `signalAborted` is the run's abort signal at `agent_end`
|
|
49
62
|
* (`ctx.signal?.aborted`): it turns an `error` stop into "aborted" (see the
|
|
50
63
|
* header) and leaves a completed stop alone — a signal aborted after the final
|
|
51
|
-
* message landed did not interrupt anything.
|
|
64
|
+
* message landed did not interrupt anything. A run ends on a tool call only
|
|
65
|
+
* when its batch terminates the loop; with the signal aborted that is a turn
|
|
66
|
+
* the user stopped before the model replied (a rejection without a reason,
|
|
67
|
+
* permissions/index.ts), so it is "aborted" too.
|
|
52
68
|
*/
|
|
53
69
|
export function runOutcome(messages: ReadonlyArray<RunMessage> | undefined, signalAborted = false): RunOutcome {
|
|
54
70
|
if (!messages) return "ok";
|
|
@@ -56,8 +72,8 @@ export function runOutcome(messages: ReadonlyArray<RunMessage> | undefined, sign
|
|
|
56
72
|
const message = messages[i];
|
|
57
73
|
if (message.role !== "assistant") continue;
|
|
58
74
|
if (message.stopReason === "aborted") return "aborted";
|
|
59
|
-
if (message.stopReason === "error"
|
|
60
|
-
return "ok";
|
|
75
|
+
if (signalAborted && (message.stopReason === "error" || message.stopReason === "toolUse")) return "aborted";
|
|
76
|
+
return message.stopReason === "error" ? "error" : "ok";
|
|
61
77
|
}
|
|
62
78
|
return "ok";
|
|
63
79
|
}
|