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
|
@@ -14,6 +14,9 @@
|
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
import { existsSync, readFileSync } from "node:fs";
|
|
17
|
+
import { ARGUMENT_HINT_CHANNEL, type ArgumentHint, type CommandHint, frontmatterCommandHint, hintForInput, PI_BUILTIN_HINTS } from "../lib/argument-hints.ts";
|
|
18
|
+
import { parseFrontmatterLoosely } from "../lib/frontmatter.ts";
|
|
19
|
+
import { promptTemplateFiles } from "../lib/skill-scan.ts";
|
|
17
20
|
import { modeCycleKey } from "../lib/keys.ts";
|
|
18
21
|
import os from "node:os";
|
|
19
22
|
import { fileURLToPath } from "node:url";
|
|
@@ -21,6 +24,8 @@ import { basename, dirname, join } from "node:path";
|
|
|
21
24
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
22
25
|
import { getAgentDir, SettingsManager, VERSION as PI_VERSION } from "@earendil-works/pi-coding-agent";
|
|
23
26
|
import { piVersionWarning } from "../lib/pi-version.ts";
|
|
27
|
+
import { handleCompactionKeep } from "./compaction-keep.ts";
|
|
28
|
+
import { handleReplacedBuiltins } from "./replaced-builtins.ts";
|
|
24
29
|
import { extensionVersion } from "../lib/package-version.ts";
|
|
25
30
|
import {
|
|
26
31
|
formatModel,
|
|
@@ -38,9 +43,11 @@ import {
|
|
|
38
43
|
shouldDefaultHideThinking,
|
|
39
44
|
type StartupSection,
|
|
40
45
|
} from "./startup.ts";
|
|
41
|
-
import { linesComponent, safeThemePaint, truncateLine } from "../lib/tui-render.ts";
|
|
46
|
+
import { linesComponent, safeThemeInverse, safeThemePaint, truncateLine } from "../lib/tui-render.ts";
|
|
47
|
+
import { AGENT_VIEW_CHANNEL, type AgentViewAnnouncement, type AgentViewTarget } from "../lib/agent-view.ts";
|
|
42
48
|
import { markAssistantMarkdown } from "./assistant-marker.ts";
|
|
43
49
|
import { PROMPT_PADDING, PromptEditor } from "./prompt-editor.ts";
|
|
50
|
+
import { sanitizeTitle } from "../lib/terminal-text.ts";
|
|
44
51
|
|
|
45
52
|
export { truncateLine };
|
|
46
53
|
|
|
@@ -138,6 +145,19 @@ export function sectionSummary(sections: StartupSection[], paint: (color: string
|
|
|
138
145
|
.join(paint("muted", " · "));
|
|
139
146
|
}
|
|
140
147
|
|
|
148
|
+
/** The mode line's words for each permission mode, so the banner never says "default" beside "manual mode on". */
|
|
149
|
+
const MODE_WORDS: Record<string, string> = {
|
|
150
|
+
default: "manual",
|
|
151
|
+
acceptEdits: "accept edits",
|
|
152
|
+
bypassPermissions: "bypass permissions",
|
|
153
|
+
dontAsk: "don't ask",
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
/** The banner's mode field: the permission display with the mode named as the mode line names it. */
|
|
157
|
+
export function bannerModeLabel(display: string): string {
|
|
158
|
+
return MODE_WORDS[display] ?? display;
|
|
159
|
+
}
|
|
160
|
+
|
|
141
161
|
/**
|
|
142
162
|
* Banner layout: the wordmark block, then a one-space-indented text column
|
|
143
163
|
* (tagline + version, context, hints, sections). Kept pure so the layout is
|
|
@@ -213,7 +233,11 @@ interface BrandingEditorUI {
|
|
|
213
233
|
* a pi-tui render change ever makes the marker misplace (cosmetic only — typing
|
|
214
234
|
* is never affected; see prompt-marker.ts).
|
|
215
235
|
*/
|
|
216
|
-
function installPromptMarker(
|
|
236
|
+
function installPromptMarker(
|
|
237
|
+
ctx: { hasUI: boolean; mode: string; ui: BrandingEditorUI; isIdle(): boolean; hasPendingMessages(): boolean },
|
|
238
|
+
argumentHints: ReadonlyMap<string, CommandHint>,
|
|
239
|
+
agentView: { target?: AgentViewTarget },
|
|
240
|
+
): void {
|
|
217
241
|
if (process.env.CC_NO_INPUT_MARKER === "1") return;
|
|
218
242
|
if (!ctx.hasUI || ctx.mode !== "tui") return;
|
|
219
243
|
const ui = ctx.ui;
|
|
@@ -223,7 +247,26 @@ function installPromptMarker(ctx: { hasUI: boolean; mode: string; ui: BrandingEd
|
|
|
223
247
|
// Bold makes the chevron read heavier than the input text beside it.
|
|
224
248
|
return `\x1b[1m${safeThemePaint(ui.theme)("accent", PROMPT_GLYPH)}\x1b[0m${" ".repeat(PROMPT_PADDING - 1)}`;
|
|
225
249
|
};
|
|
226
|
-
|
|
250
|
+
const renderHint = (text: string) => {
|
|
251
|
+
// While an agent is viewed the empty editor addresses it (lib/agent-view.ts).
|
|
252
|
+
const placeholder = text === "" && agentView.target ? agentView.target.placeholder : hintForInput(text, argumentHints);
|
|
253
|
+
return placeholder === undefined ? undefined : safeThemePaint(ui.theme)("dim", placeholder);
|
|
254
|
+
};
|
|
255
|
+
const badge = () => agentView.target?.badge;
|
|
256
|
+
const paintBadge = (label: string) => safeThemeInverse(ui.theme)(safeThemePaint(ui.theme)("accent", ` ${label} `));
|
|
257
|
+
// The editor can outlive this context across a session replacement; a stale
|
|
258
|
+
// context throws, and ↑ must still reach the editor then.
|
|
259
|
+
const queued = () => {
|
|
260
|
+
try {
|
|
261
|
+
return !ctx.isIdle() && ctx.hasPendingMessages();
|
|
262
|
+
} catch {
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
};
|
|
266
|
+
ui.setEditorComponent(
|
|
267
|
+
(tui: unknown, theme: unknown, keybindings: unknown) =>
|
|
268
|
+
new PromptEditor(tui as never, theme as never, keybindings as never, renderMarker, renderHint, badge, paintBadge, queued),
|
|
269
|
+
);
|
|
227
270
|
}
|
|
228
271
|
|
|
229
272
|
/**
|
|
@@ -268,6 +311,25 @@ function applyOutputPadDefault(): void {
|
|
|
268
311
|
}
|
|
269
312
|
|
|
270
313
|
export default function brandingExtension(pi: ExtensionAPI) {
|
|
314
|
+
/**
|
|
315
|
+
* pi's merged `quietStartup` (global settings with the project's
|
|
316
|
+
* `.pi/settings.json` over them), so the banner and pi agree on whether pi
|
|
317
|
+
* lists its own startup sections. `pi.getSettings()` is in pi 1.0.1; a pi
|
|
318
|
+
* near the 0.84.3 floor without it falls back to the global file alone.
|
|
319
|
+
*/
|
|
320
|
+
const effectiveQuietStartup = (agentDir: string): unknown => {
|
|
321
|
+
try {
|
|
322
|
+
if (typeof (pi as { getSettings?: unknown }).getSettings === "function") return pi.getSettings().quietStartup;
|
|
323
|
+
} catch {
|
|
324
|
+
// The banner must still install: fall back to the global file.
|
|
325
|
+
}
|
|
326
|
+
try {
|
|
327
|
+
return (JSON.parse(readFileSync(join(agentDir, "settings.json"), "utf8")) as { quietStartup?: unknown }).quietStartup;
|
|
328
|
+
} catch {
|
|
329
|
+
return undefined;
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
|
|
271
333
|
applyThinkingDefault();
|
|
272
334
|
applyOutputPadDefault();
|
|
273
335
|
// Mark each block of assistant prose with Claude Code's "●" bullet. Only
|
|
@@ -296,7 +358,9 @@ export default function brandingExtension(pi: ExtensionAPI) {
|
|
|
296
358
|
const retitle = (ctx: { hasUI: boolean; cwd: string; ui: { setTitle(title: string): void } }) => {
|
|
297
359
|
if (!live || !ctx.hasUI) return;
|
|
298
360
|
const name = pi.getSessionName?.()?.trim();
|
|
299
|
-
|
|
361
|
+
// pi writes the title inside its OSC 0 and strips only CR and LF; a BEL or
|
|
362
|
+
// ESC in the session name (any source) or the directory would end it early.
|
|
363
|
+
const title = sanitizeTitle(name ? `${NAME} - ${name} - ${basename(ctx.cwd)}` : NAME);
|
|
300
364
|
if (title === lastTitle) return; // agent_start fires every turn; write only on change
|
|
301
365
|
lastTitle = title;
|
|
302
366
|
ctx.ui.setTitle(title);
|
|
@@ -307,18 +371,76 @@ export default function brandingExtension(pi: ExtensionAPI) {
|
|
|
307
371
|
live = false;
|
|
308
372
|
});
|
|
309
373
|
|
|
310
|
-
|
|
374
|
+
// Commands' argument placeholders (lib/argument-hints.ts), drawn by the prompt editor.
|
|
375
|
+
// Declared before the CC_NO_BANNER return below: session_start reads it.
|
|
376
|
+
const argumentHints = new Map<string, CommandHint>(Object.entries(PI_BUILTIN_HINTS).map(([command, hint]) => [command, { hint }]));
|
|
377
|
+
// The agent the user is viewing, if any: the editor then targets it (lib/agent-view.ts).
|
|
378
|
+
const agentView: { target?: AgentViewTarget } = {};
|
|
379
|
+
pi.events.on(AGENT_VIEW_CHANNEL, (data) => {
|
|
380
|
+
agentView.target = (data as AgentViewAnnouncement | undefined)?.target;
|
|
381
|
+
});
|
|
382
|
+
pi.events.on(ARGUMENT_HINT_CHANNEL, (data) => {
|
|
383
|
+
const { command, ...hint } = data as ArgumentHint;
|
|
384
|
+
argumentHints.set(command, hint);
|
|
385
|
+
});
|
|
386
|
+
// pi's prompt templates and `/skill:` commands carry their file's
|
|
387
|
+
// `argument-hint` frontmatter. pi lists them only once a turn resolves them,
|
|
388
|
+
// so the template folders are scanned at session_start (the skill extension
|
|
389
|
+
// announces `/skill:` hints from its own scan) and pi's list read each turn.
|
|
390
|
+
// pi runs a built-in or extension command before a command file of the same
|
|
391
|
+
// name, so such a file's hint is never read.
|
|
392
|
+
const hintedFiles = new Set<string>();
|
|
393
|
+
const readFileHints = (files: { name: string; path: string }[], commands = pi.getCommands()) => {
|
|
394
|
+
const extensionCommands = new Set(commands.filter((c) => c.source === "extension").map((c) => c.name));
|
|
395
|
+
for (const { name, path } of files) {
|
|
396
|
+
if (hintedFiles.has(path)) continue;
|
|
397
|
+
if (Object.hasOwn(PI_BUILTIN_HINTS, name) || extensionCommands.has(name)) continue;
|
|
398
|
+
try {
|
|
399
|
+
const hint = frontmatterCommandHint(parseFrontmatterLoosely(readFileSync(path, "utf-8")).frontmatter);
|
|
400
|
+
if (hint) argumentHints.set(name, hint);
|
|
401
|
+
hintedFiles.add(path);
|
|
402
|
+
} catch {
|
|
403
|
+
// Unreadable (mid-replace, say): no hint now; a later scan retries it.
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
};
|
|
407
|
+
pi.on("before_agent_start", () => {
|
|
408
|
+
try {
|
|
409
|
+
const commands = pi.getCommands();
|
|
410
|
+
readFileHints(
|
|
411
|
+
commands.filter((c) => c.source !== "extension").map((c) => ({ name: c.name, path: c.sourceInfo.path })),
|
|
412
|
+
commands,
|
|
413
|
+
);
|
|
414
|
+
} catch {
|
|
415
|
+
// Not bound (a torn-down session): the next turn looks again.
|
|
416
|
+
}
|
|
417
|
+
});
|
|
418
|
+
pi.on("session_start", (event, ctx) => {
|
|
311
419
|
// pi's own write lands after this handler, so only the deferred write
|
|
312
420
|
// sticks; a new session may carry a name (resume), so forget the last.
|
|
313
421
|
lastTitle = undefined;
|
|
314
422
|
live = true;
|
|
315
423
|
setTimeout(() => retitle(ctx), 0).unref?.();
|
|
316
424
|
ctx.ui.setHiddenThinkingLabel(THINKING_LABEL);
|
|
317
|
-
installPromptMarker(ctx as unknown as
|
|
425
|
+
installPromptMarker(ctx as unknown as Parameters<typeof installPromptMarker>[0], argumentHints, agentView);
|
|
426
|
+
try {
|
|
427
|
+
readFileHints(promptTemplateFiles(ctx.cwd, os.homedir(), getAgentDir()));
|
|
428
|
+
} catch {
|
|
429
|
+
// Commands not bound: nothing was marked read, so the next turn reads pi's list.
|
|
430
|
+
}
|
|
318
431
|
// Soft drift guard: warn once at startup when the hosting pi is outside
|
|
319
432
|
// the range this release was tested against (see lib/pi-version.ts).
|
|
320
433
|
const versionWarning = piVersionWarning(PI_VERSION);
|
|
321
434
|
if (versionWarning) ctx.ui.notify(versionWarning, "warning");
|
|
435
|
+
// pi 0.99 skips its built-in tool search and MCP for ours and warns at
|
|
436
|
+
// every start, advising the user to remove One Code: offer to turn them
|
|
437
|
+
// off once, else answer with the notice (replaced-builtins.ts). Only
|
|
438
|
+
// when pi resolves its built-ins again (startup, /reload), not on a
|
|
439
|
+
// /new, resume or fork, which re-run this handler too. Not awaited: a
|
|
440
|
+
// dialog must not hold up startup. The compaction keep-window question
|
|
441
|
+
// (compaction-keep.ts) follows it, so the two dialogs never overlap.
|
|
442
|
+
const reason = (event as { reason?: string }).reason ?? "startup";
|
|
443
|
+
if (reason === "startup" || reason === "reload") void handleReplacedBuiltins(ctx).then(() => handleCompactionKeep(ctx));
|
|
322
444
|
});
|
|
323
445
|
|
|
324
446
|
if (process.env.CC_NO_BANNER === "1") return;
|
|
@@ -363,9 +485,11 @@ export default function brandingExtension(pi: ExtensionAPI) {
|
|
|
363
485
|
// instead (minus the internal [Extensions] noise).
|
|
364
486
|
const home = os.homedir();
|
|
365
487
|
// Resolve pi's live agent dir (honours PI_CODING_AGENT_DIR) so an
|
|
366
|
-
// isolated one-code app reads its own
|
|
488
|
+
// isolated one-code app reads its own skills, never ~/.pi.
|
|
367
489
|
const agentDir = getAgentDir();
|
|
368
|
-
|
|
490
|
+
// Use pi's effective settings, including project overrides, so the two
|
|
491
|
+
// listings agree on whether quiet startup is enabled.
|
|
492
|
+
const sections = quietStartupEnabled(effectiveQuietStartup(agentDir))
|
|
369
493
|
? collectStartupSections(ctx.cwd, home, join(dirname(fileURLToPath(import.meta.url)), "..", "..", "themes"), agentDir)
|
|
370
494
|
: undefined;
|
|
371
495
|
|
|
@@ -387,7 +511,7 @@ export default function brandingExtension(pi: ExtensionAPI) {
|
|
|
387
511
|
version,
|
|
388
512
|
model: modelLabel ?? "none",
|
|
389
513
|
cwd: ctx.cwd,
|
|
390
|
-
mode: permissionModeDisplay(permissionStatus ?? { mode: "default", paused: false }),
|
|
514
|
+
mode: bannerModeLabel(permissionModeDisplay(permissionStatus ?? { mode: "default", paused: false })),
|
|
391
515
|
subagents:
|
|
392
516
|
modelLabel === undefined
|
|
393
517
|
? "none"
|
|
@@ -3,14 +3,19 @@
|
|
|
3
3
|
*
|
|
4
4
|
* pi's editor has no prompt marker and no option for one, but `CustomEditor` is
|
|
5
5
|
* the sanctioned base for a replacement (it already wires every app keybinding
|
|
6
|
-
* through handleInput
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* through handleInput). We reserve a two-column left gutter and paint the
|
|
7
|
+
* marker into it — see prompt-marker.ts for why that is cursor-safe — draw a
|
|
8
|
+
* slash command's argument hint after the cursor (lib/argument-hints.ts), and
|
|
9
|
+
* let ↑ restore queued messages through pi's dequeue action (queued-edit.ts). Registered via `ctx.ui.setEditorComponent`; this file is thin
|
|
9
10
|
* wiring over the pure `applyPromptMarker`.
|
|
10
11
|
*/
|
|
11
12
|
|
|
12
13
|
import { CustomEditor } from "@earendil-works/pi-coding-agent";
|
|
14
|
+
import { applyBorderBadge, fitBadge } from "../lib/agent-view.ts";
|
|
15
|
+
import { applyArgumentHint } from "../lib/argument-hints.ts";
|
|
16
|
+
import { visibleWidth } from "../lib/text-width.ts";
|
|
13
17
|
import { applyPromptMarker } from "./prompt-marker.ts";
|
|
18
|
+
import { upEditsQueue } from "./queued-edit.ts";
|
|
14
19
|
|
|
15
20
|
/** Width of the left gutter, and therefore the visible width the marker must fill. */
|
|
16
21
|
export const PROMPT_PADDING = 2;
|
|
@@ -20,10 +25,45 @@ type EditorArgs = ConstructorParameters<typeof CustomEditor>;
|
|
|
20
25
|
export class PromptEditor extends CustomEditor {
|
|
21
26
|
/** Re-read per render so the marker follows live theme changes. */
|
|
22
27
|
#renderMarker: () => string;
|
|
28
|
+
/** The painted argument placeholder for the current input, if it is a hinted command. */
|
|
29
|
+
#renderHint: (text: string) => string | undefined;
|
|
30
|
+
/** The viewed agent's top-border label (plain text), or undefined on main (lib/agent-view.ts). */
|
|
31
|
+
#badge: () => string | undefined;
|
|
32
|
+
/** Paints the fitted badge label as a chip, one space of padding on each side. */
|
|
33
|
+
#paintBadge: (label: string) => string;
|
|
34
|
+
/** Whether a message waits in pi's queue mid-turn (queued-edit.ts). */
|
|
35
|
+
#queued: () => boolean;
|
|
36
|
+
#keys: EditorArgs[2];
|
|
37
|
+
/** The width pi wraps the text at, from the last render (pi's own formula). */
|
|
38
|
+
#layoutWidth = Number.POSITIVE_INFINITY;
|
|
23
39
|
|
|
24
|
-
constructor(
|
|
25
|
-
|
|
40
|
+
constructor(
|
|
41
|
+
tui: EditorArgs[0],
|
|
42
|
+
theme: EditorArgs[1],
|
|
43
|
+
keybindings: EditorArgs[2],
|
|
44
|
+
renderMarker: () => string,
|
|
45
|
+
renderHint: (text: string) => string | undefined = () => undefined,
|
|
46
|
+
badge: () => string | undefined = () => undefined,
|
|
47
|
+
paintBadge: (label: string) => string = (label) => label,
|
|
48
|
+
queued: () => boolean = () => false,
|
|
49
|
+
) {
|
|
50
|
+
super(tui, theme, keybindings, { paddingX: PROMPT_PADDING, embedWorkingStatus: true });
|
|
26
51
|
this.#renderMarker = renderMarker;
|
|
52
|
+
this.#renderHint = renderHint;
|
|
53
|
+
this.#badge = badge;
|
|
54
|
+
this.#paintBadge = paintBadge;
|
|
55
|
+
this.#queued = queued;
|
|
56
|
+
this.#keys = keybindings;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** ↑ on the first line restores queued messages, as in Claude Code (queued-edit.ts). */
|
|
60
|
+
handleInput(data: string): void {
|
|
61
|
+
const dequeue = this.actionHandlers.get("app.message.dequeue");
|
|
62
|
+
if (dequeue && this.#keys.matches(data, "tui.editor.cursorUp") && upEditsQueue(this, this.#queued(), this.#layoutWidth)) {
|
|
63
|
+
dequeue();
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
super.handleInput(data);
|
|
27
67
|
}
|
|
28
68
|
|
|
29
69
|
/**
|
|
@@ -37,6 +77,13 @@ export class PromptEditor extends CustomEditor {
|
|
|
37
77
|
}
|
|
38
78
|
|
|
39
79
|
render(width: number): string[] {
|
|
40
|
-
|
|
80
|
+
const paddingX = Math.min(PROMPT_PADDING, Math.max(0, Math.floor((width - 1) / 2)));
|
|
81
|
+
this.#layoutWidth = Math.max(1, width - paddingX * 2 - (paddingX ? 0 : 1));
|
|
82
|
+
let lines = applyPromptMarker(super.render(width), PROMPT_PADDING, this.#renderMarker());
|
|
83
|
+
const hint = this.#renderHint(this.getText());
|
|
84
|
+
if (hint) lines = applyArgumentHint(lines, hint);
|
|
85
|
+
const label = this.#badge();
|
|
86
|
+
const fitted = label ? fitBadge(label, width) : "";
|
|
87
|
+
return fitted ? applyBorderBadge(lines, this.#paintBadge(fitted), visibleWidth(fitted) + 2, this.borderColor("─")) : lines;
|
|
41
88
|
}
|
|
42
89
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code's key for editing queued messages: plain ↑. With a message
|
|
3
|
+
* queued mid-turn, ↑ moves every queued message into the editor instead of
|
|
4
|
+
* walking history, but only with the cursor on the draft's first line (lower
|
|
5
|
+
* lines need ↑ to move the cursor) and no autocomplete list open (↑ moves in
|
|
6
|
+
* the list). pi binds the same restore only to alt+up, which not every
|
|
7
|
+
* terminal sends: macOS Terminal's terminfo (nsterm) maps option+left and
|
|
8
|
+
* option+right but no modified up arrow. Pure: `prompt-editor.ts` calls pi's
|
|
9
|
+
* own dequeue action, so the alt+up binding keeps working alongside.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { visibleWidth } from "../lib/text-width.ts";
|
|
13
|
+
|
|
14
|
+
export interface QueueEditEditor {
|
|
15
|
+
getCursor(): { line: number; col: number };
|
|
16
|
+
getLines(): string[];
|
|
17
|
+
isShowingAutocomplete(): boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Whether a plain ↑ restores the queued messages rather than reaching the
|
|
22
|
+
* editor. Only on a first line that fits one row of `layoutWidth`: pi's
|
|
23
|
+
* public API does not say which visual row the cursor is on, so on a wrapped
|
|
24
|
+
* first line ↑ is left to pi (it moves the cursor) and alt+up restores.
|
|
25
|
+
*/
|
|
26
|
+
export function upEditsQueue(editor: QueueEditEditor, queued: boolean, layoutWidth: number): boolean {
|
|
27
|
+
if (!queued) return false;
|
|
28
|
+
if (editor.isShowingAutocomplete()) return false;
|
|
29
|
+
if (editor.getCursor().line !== 0) return false;
|
|
30
|
+
return visibleWidth(editor.getLines()[0] ?? "") <= layoutWidth;
|
|
31
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pi 0.99's built-in tool search and MCP, at startup (lib/replaced-builtins.mjs
|
|
3
|
+
* has the rule; decisions/tools.md "pi's built-in tool search and MCP").
|
|
4
|
+
*
|
|
5
|
+
* On the user's own pi, while the user's settings leave a built-in on, One
|
|
6
|
+
* Code asks once whether to turn them off, explaining why. "Yes" writes the
|
|
7
|
+
* `-builtin:<name>` entries through pi's own SettingsManager (a locked write
|
|
8
|
+
* of the `extensions` field only, so pi's in-memory settings keep theirs).
|
|
9
|
+
* "No" is remembered in `~/.onecode/settings.json` and never asked again;
|
|
10
|
+
* Escape asks again next start. Without a yes, the one-line notice answers
|
|
11
|
+
* pi's warning instead. Under the bundled app, which turns them off itself,
|
|
12
|
+
* a built-in left on is the user's own `+` entry, so only the notice shows.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import os from "node:os";
|
|
16
|
+
import { type ExtensionContext, getAgentDir, SettingsManager, VERSION as PI_VERSION } from "@earendil-works/pi-coding-agent";
|
|
17
|
+
import { configCommand, installKind, replacedBuiltinsView } from "../doctor/builtins.ts";
|
|
18
|
+
import { tildify } from "../lib/paths.ts";
|
|
19
|
+
import { declined, recordDeclined } from "./declined.ts";
|
|
20
|
+
import { replacedBuiltinsNotice, TURN_OFF_NO, TURN_OFF_YES, turnOffPrompt, withBuiltinsTurnedOff } from "../lib/replaced-builtins.mjs";
|
|
21
|
+
|
|
22
|
+
/** `~/.onecode/settings.json` key: the user answered "No" to the question. */
|
|
23
|
+
export const DECLINED_KEY = "piBuiltinsTurnOffDeclined";
|
|
24
|
+
|
|
25
|
+
/** Ask, or show the notice, for the built-ins the settings leave on. Never throws. */
|
|
26
|
+
export async function handleReplacedBuiltins(ctx: ExtensionContext): Promise<void> {
|
|
27
|
+
try {
|
|
28
|
+
const cwd = ctx.cwd;
|
|
29
|
+
const agentDir = getAgentDir();
|
|
30
|
+
const settings = () => SettingsManager.create(cwd, agentDir);
|
|
31
|
+
const view = replacedBuiltinsView(PI_VERSION, settings, { agentDir, cwd });
|
|
32
|
+
if (!view || view.left.length === 0) return;
|
|
33
|
+
const install = installKind();
|
|
34
|
+
const command = configCommand(install);
|
|
35
|
+
const notice = () => {
|
|
36
|
+
const text = replacedBuiltinsNotice(view.left, command);
|
|
37
|
+
if (text) ctx.ui.notify(text, "info");
|
|
38
|
+
};
|
|
39
|
+
// Only the user's own file is ours to offer: a project's `+builtin` entry stays.
|
|
40
|
+
const userScoped = view.left.filter((builtin) => builtin.scope === "user");
|
|
41
|
+
if (install === "app" || !ctx.hasUI || userScoped.length === 0 || declined(DECLINED_KEY)) return notice();
|
|
42
|
+
|
|
43
|
+
const shown = tildify(view.paths.user, os.homedir());
|
|
44
|
+
const choice = await ctx.ui.select(turnOffPrompt(userScoped, shown, command), [TURN_OFF_YES, TURN_OFF_NO]);
|
|
45
|
+
if (choice === TURN_OFF_YES) {
|
|
46
|
+
const manager = settings();
|
|
47
|
+
manager.setExtensionPaths(withBuiltinsTurnedOff(manager.getGlobalSettings().extensions, userScoped.map((builtin) => builtin.name)) as string[]);
|
|
48
|
+
await manager.flush();
|
|
49
|
+
const turnedOff = `Turned off pi's built-in ${userScoped.map((builtin) => builtin.name).join(" and ")} in ${shown}.`;
|
|
50
|
+
// A project's `+builtin` entry still wins over the user's file, so its warning stays.
|
|
51
|
+
const projectScoped = view.left.filter((builtin) => builtin.scope === "project");
|
|
52
|
+
const rest =
|
|
53
|
+
projectScoped.length === 0
|
|
54
|
+
? "pi's warnings stop from the next start."
|
|
55
|
+
: `This project's settings keep ${projectScoped.map((builtin) => builtin.name).join(" and ")} on, so pi still warns about ${projectScoped.length > 1 ? "them" : "it"}; run /doctor for that change.`;
|
|
56
|
+
ctx.ui.notify(`${turnedOff} ${rest}`, "info");
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (choice === TURN_OFF_NO) recordDeclined(DECLINED_KEY);
|
|
60
|
+
notice();
|
|
61
|
+
} catch (error) {
|
|
62
|
+
try {
|
|
63
|
+
ctx.ui.notify(`Could not turn off pi's built-in tool search and MCP: ${(error as Error).message}. Run /doctor for the settings change.`, "warning");
|
|
64
|
+
} catch {
|
|
65
|
+
// The session ended while the dialog was open: nothing is left to tell.
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Compact startup sections for the banner: Context, Skills, Themes.
|
|
3
3
|
*
|
|
4
4
|
* pi's own startup listing has no per-section switch — hiding the noisy
|
|
5
|
-
* [Extensions] block (20 internal module names) means `quietStartup
|
|
6
|
-
*
|
|
5
|
+
* [Extensions] block (20 internal module names) means `quietStartup`, which
|
|
6
|
+
* hides the whole listing. So when quiet startup is on, the banner shows its
|
|
7
7
|
* own compact versions of the sections that ARE useful. pi's resourceLoader
|
|
8
8
|
* is not exposed to extensions, so these are re-derived the same way our
|
|
9
9
|
* other extensions derive them (claude-compat's skill dirs, pi's git-root
|
|
@@ -12,11 +12,14 @@
|
|
|
12
12
|
* PI_CODING_AGENT_DIR isolation).
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import { existsSync, readdirSync
|
|
16
|
-
import { basename,
|
|
17
|
-
import
|
|
15
|
+
import { existsSync, readdirSync } from "node:fs";
|
|
16
|
+
import { basename, join, relative } from "node:path";
|
|
17
|
+
import os from "node:os";
|
|
18
|
+
import { projectInstructionFiles } from "../lib/claude-context.ts";
|
|
19
|
+
import { projectConfigDir, userConfigDir } from "../lib/config-mode.ts";
|
|
20
|
+
import { BUNDLED_SKILLS_DIR, scanSkills } from "../lib/skill-scan.ts";
|
|
18
21
|
import { defaultDiscoverRoots, discoverPlugins } from "../lib/plugins.ts";
|
|
19
|
-
import {
|
|
22
|
+
import { oneCodeStateDir } from "../lib/paths.ts";
|
|
20
23
|
|
|
21
24
|
export interface StartupSection {
|
|
22
25
|
label: string;
|
|
@@ -25,69 +28,29 @@ export interface StartupSection {
|
|
|
25
28
|
|
|
26
29
|
/**
|
|
27
30
|
* The project context files One Code actually gathers, from cwd up to the git
|
|
28
|
-
* root (or just cwd outside a repo), for the startup
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* AGENTS.md is listed only when it's really in play, not whenever it exists.
|
|
31
|
+
* root (or just cwd outside a repo), nearest directory first, for the startup
|
|
32
|
+
* banner. The same discovery and rule the blocks use (lib/claude-context.ts),
|
|
33
|
+
* so an AGENTS.md is listed only when it is really in play.
|
|
32
34
|
*/
|
|
33
|
-
export function contextFileNames(cwd: string): string[] {
|
|
34
|
-
|
|
35
|
-
const found: string[] = [];
|
|
36
|
-
let dir = cwd;
|
|
37
|
-
while (true) {
|
|
38
|
-
const rel = (name: string) => relative(cwd, join(dir, name)) || name;
|
|
39
|
-
const present = (name: string) => existsSync(join(dir, name));
|
|
40
|
-
// CLAUDE.md is primary; AGENTS.md stands in only when there is no CLAUDE.md.
|
|
41
|
-
if (present("CLAUDE.md")) found.push(rel("CLAUDE.md"));
|
|
42
|
-
else if (present("AGENTS.md")) found.push(rel("AGENTS.md"));
|
|
43
|
-
if (present("CLAUDE.local.md")) found.push(rel("CLAUDE.local.md"));
|
|
44
|
-
for (const name of ["ONECODE.md", "onecode.md", "One Code.md"]) {
|
|
45
|
-
if (present(name)) {
|
|
46
|
-
found.push(rel(name));
|
|
47
|
-
break;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
if (dir === stop) break;
|
|
51
|
-
const parent = dirname(dir);
|
|
52
|
-
if (parent === dir) break;
|
|
53
|
-
dir = parent;
|
|
54
|
-
}
|
|
55
|
-
return found;
|
|
35
|
+
export function contextFileNames(cwd: string, home: string = os.homedir()): string[] {
|
|
36
|
+
return projectInstructionFiles({ cwd, home, homeOneCodeDir: oneCodeStateDir(process.env, home) }).map((path) => relative(cwd, path) || basename(path));
|
|
56
37
|
}
|
|
57
38
|
|
|
58
39
|
/**
|
|
59
|
-
* Skills across the same sources our extensions feed to pi
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
40
|
+
* Skills across the same sources our extensions feed to pi (lib/skill-scan.ts
|
|
41
|
+
* scanSkills: pi's own user dir, the mode's skill folders, the bundled
|
|
42
|
+
* catalog, installed plugins), each name once: the set `/skills` lists and
|
|
43
|
+
* `/doctor` counts.
|
|
63
44
|
*/
|
|
64
|
-
export function skillNames(cwd: string, home: string, agentDir: string): string[] {
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
join(claudeUserDir(home), "skills"),
|
|
68
|
-
join(agentDir, "skills"),
|
|
69
|
-
];
|
|
70
|
-
const names = new Set<string>();
|
|
71
|
-
for (const dir of dirs) {
|
|
72
|
-
if (!existsSync(dir)) continue;
|
|
73
|
-
try {
|
|
74
|
-
for (const entry of readdirSync(dir)) {
|
|
75
|
-
if (existsSync(join(dir, entry, "SKILL.md"))) names.add(entry);
|
|
76
|
-
}
|
|
77
|
-
} catch {
|
|
78
|
-
// Unreadable dir: skip, same as pi would.
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
for (const skill of discoverPlugins(defaultDiscoverRoots(agentDir, cwd, home)).skills) {
|
|
82
|
-
names.add(skill.name);
|
|
83
|
-
}
|
|
84
|
-
return [...names].sort((a, b) => a.localeCompare(b));
|
|
45
|
+
export function skillNames(cwd: string, home: string, agentDir: string, bundledDir: string = BUNDLED_SKILLS_DIR): string[] {
|
|
46
|
+
const plugins = discoverPlugins(defaultDiscoverRoots(agentDir, cwd, home)).skills;
|
|
47
|
+
return [...new Set(scanSkills(cwd, home, agentDir, plugins, bundledDir).map((skill) => skill.name))].sort((a, b) => a.localeCompare(b));
|
|
85
48
|
}
|
|
86
49
|
|
|
87
|
-
/** Saved workflow names from the
|
|
50
|
+
/** Saved workflow names from the mode's workflow dirs (project shadows user). */
|
|
88
51
|
export function workflowNames(cwd: string, home: string): string[] {
|
|
89
52
|
const names = new Set<string>();
|
|
90
|
-
for (const dir of [join(cwd, "
|
|
53
|
+
for (const dir of [join(projectConfigDir(cwd), "workflows"), join(userConfigDir(home), "workflows")]) {
|
|
91
54
|
if (!existsSync(dir)) continue;
|
|
92
55
|
try {
|
|
93
56
|
for (const entry of readdirSync(dir)) {
|
|
@@ -146,20 +109,19 @@ export function shouldDefaultFlushOutputPad(settingsRaw: string | undefined): bo
|
|
|
146
109
|
}
|
|
147
110
|
}
|
|
148
111
|
|
|
149
|
-
/**
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
}
|
|
112
|
+
/**
|
|
113
|
+
* True when pi's own startup listing is silenced, so ours should render instead:
|
|
114
|
+
* `quietStartup: true`, or pi 1.0's `"header"`, which keeps pi's header and
|
|
115
|
+
* still hides the listing. The caller supplies pi's effective, merged value.
|
|
116
|
+
*/
|
|
117
|
+
export function quietStartupEnabled(value: unknown): boolean {
|
|
118
|
+
return value === true || value === "header";
|
|
157
119
|
}
|
|
158
120
|
|
|
159
|
-
export function collectStartupSections(cwd: string, home: string, packageThemesDir: string, agentDir: string): StartupSection[] {
|
|
121
|
+
export function collectStartupSections(cwd: string, home: string, packageThemesDir: string, agentDir: string, bundledSkillsDir: string = BUNDLED_SKILLS_DIR): StartupSection[] {
|
|
160
122
|
const sections: StartupSection[] = [
|
|
161
|
-
{ label: "context", items: contextFileNames(cwd) },
|
|
162
|
-
{ label: "skills", items: skillNames(cwd, home, agentDir) },
|
|
123
|
+
{ label: "context", items: contextFileNames(cwd, home) },
|
|
124
|
+
{ label: "skills", items: skillNames(cwd, home, agentDir, bundledSkillsDir) },
|
|
163
125
|
{ label: "workflows", items: workflowNames(cwd, home) },
|
|
164
126
|
{ label: "themes", items: themeNames(packageThemesDir) },
|
|
165
127
|
];
|