@gajae-code/coding-agent 0.18.11 → 0.19.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/CHANGELOG.md +760 -0
- package/dist/types/async/job-manager.d.ts +7 -3
- package/dist/types/async/result-formatting.d.ts +2 -0
- package/dist/types/autoresearch/git.d.ts +1 -1
- package/dist/types/capability/fs.d.ts +2 -2
- package/dist/types/capability/rule.d.ts +7 -2
- package/dist/types/cli/accounts-cli.d.ts +2 -2
- package/dist/types/cli/append-system-prompt.d.ts +6 -0
- package/dist/types/cli/args.d.ts +7 -2
- package/dist/types/cli/customize-doctor-precedence.d.ts +16 -0
- package/dist/types/cli/customize-doctor.d.ts +4 -3
- package/dist/types/cli/doctor/install-repairs.d.ts +4 -1
- package/dist/types/cli/install-activation.d.ts +10 -4
- package/dist/types/cli/public-command-errors.d.ts +2 -0
- package/dist/types/cli/root-flags.d.ts +0 -12
- package/dist/types/cli/update-cli.d.ts +21 -3
- package/dist/types/cli-main.d.ts +0 -6
- package/dist/types/cli-ordinary.d.ts +2 -2
- package/dist/types/commands/accounts.d.ts +2 -1
- package/dist/types/commands/launch.d.ts +0 -6
- package/dist/types/commands/migrate.d.ts +1 -1
- package/dist/types/commands/sdk.d.ts +13 -0
- package/dist/types/commit/changelog/index.d.ts +1 -0
- package/dist/types/commit/map-reduce/index.d.ts +4 -4
- package/dist/types/config/autorouting-tier-map.d.ts +53 -1
- package/dist/types/config/config-hot-reload-trust.d.ts +12 -0
- package/dist/types/config/config-hot-reload.d.ts +44 -0
- package/dist/types/config/file-lock.d.ts +52 -3
- package/dist/types/config/model-discovery-manager.d.ts +2 -0
- package/dist/types/config/model-profile-activation.d.ts +79 -9
- package/dist/types/config/model-registry.d.ts +72 -8
- package/dist/types/config/model-resolver.d.ts +7 -4
- package/dist/types/config/models-config-schema.d.ts +10 -0
- package/dist/types/config/settings-schema.d.ts +57 -4
- package/dist/types/config/settings.d.ts +33 -1
- package/dist/types/coordinator-mcp/server.d.ts +4 -0
- package/dist/types/customization/import.d.ts +2 -0
- package/dist/types/customization/types.d.ts +1 -1
- package/dist/types/dap/config.d.ts +8 -4
- package/dist/types/dap/session.d.ts +11 -2
- package/dist/types/debug/system-info.d.ts +6 -1
- package/dist/types/discovery/helpers.d.ts +7 -2
- package/dist/types/discovery/mcp-compat.d.ts +3 -1
- package/dist/types/edit/index.d.ts +5 -0
- package/dist/types/edit/modes/patch.d.ts +14 -0
- package/dist/types/edit/modes/replace.d.ts +3 -0
- package/dist/types/eval/py/runtime.d.ts +9 -0
- package/dist/types/exec/bash-executor.d.ts +12 -0
- package/dist/types/export/ttsr.d.ts +19 -0
- package/dist/types/extensibility/extensions/types.d.ts +5 -1
- package/dist/types/extensibility/slash-commands.d.ts +1 -0
- package/dist/types/gjc-runtime/managed-owner-admission.d.ts +3 -0
- package/dist/types/gjc-runtime/ralplan-current-final.d.ts +54 -0
- package/dist/types/gjc-runtime/ralplan-runtime.d.ts +5 -0
- package/dist/types/gjc-runtime/session-state-lock.d.ts +2 -0
- package/dist/types/gjc-runtime/state-runtime.d.ts +0 -2
- package/dist/types/gjc-runtime/tmux-sessions.d.ts +24 -0
- package/dist/types/gjc-runtime/ultragoal-change-set.d.ts +6 -0
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +1 -0
- package/dist/types/harness-control-plane/receipt-spool.d.ts +4 -0
- package/dist/types/hindsight/content.d.ts +5 -6
- package/dist/types/internal-urls/types.d.ts +2 -0
- package/dist/types/lsp/clients/swiftlint-client.d.ts +0 -4
- package/dist/types/main.d.ts +23 -18
- package/dist/types/migrate/action-planner.d.ts +10 -1
- package/dist/types/migrate/adapters/codex.d.ts +2 -1
- package/dist/types/migrate/adapters/index.d.ts +42 -1
- package/dist/types/migrate/executor.d.ts +3 -1
- package/dist/types/migrate/hook-module.d.ts +23 -0
- package/dist/types/migrate/report.d.ts +2 -1
- package/dist/types/migrate/types.d.ts +82 -3
- package/dist/types/modes/components/agent-dashboard.d.ts +1 -1
- package/dist/types/modes/components/model-selector.d.ts +43 -0
- package/dist/types/modes/components/settings-selector.d.ts +6 -0
- package/dist/types/modes/controllers/selector-controller.d.ts +2 -0
- package/dist/types/modes/prompt-suggestion-controller.d.ts +1 -1
- package/dist/types/modes/theme/theme.d.ts +1 -0
- package/dist/types/modes/utils/host-status.d.ts +15 -11
- package/dist/types/runtime-mcp/content-limits.d.ts +4 -0
- package/dist/types/runtime-mcp/manager.d.ts +7 -0
- package/dist/types/runtime-mcp/plugin-mcp-name-filter.d.ts +22 -0
- package/dist/types/runtime-mcp/project-host-values.d.ts +11 -5
- package/dist/types/runtime-mcp/tool-bridge.d.ts +4 -0
- package/dist/types/sdk/broker/broker-exit.d.ts +3 -3
- package/dist/types/sdk/broker/broker.d.ts +29 -2
- package/dist/types/sdk/broker/daemon-entry.d.ts +11 -1
- package/dist/types/sdk/broker/doctor-restart.d.ts +1 -1
- package/dist/types/sdk/broker/ensure.d.ts +141 -9
- package/dist/types/sdk/broker/hop.d.ts +45 -0
- package/dist/types/sdk/broker/lifecycle-ledger.d.ts +18 -10
- package/dist/types/sdk/broker/lifecycle.d.ts +22 -0
- package/dist/types/sdk/broker/lock-host-identity.d.ts +5 -0
- package/dist/types/sdk/broker/session-index.d.ts +6 -1
- package/dist/types/sdk/broker/transport.d.ts +2 -0
- package/dist/types/sdk/bus/chat-command-policy.d.ts +2 -1
- package/dist/types/sdk/bus/index.d.ts +44 -0
- package/dist/types/sdk/bus/reconciliation-store.d.ts +10 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +9 -1
- package/dist/types/sdk/bus/telegram-daemon.d.ts +2 -0
- package/dist/types/sdk/bus/threaded-render.d.ts +2 -1
- package/dist/types/sdk/cli/session-cli.d.ts +0 -1
- package/dist/types/sdk/host/control/operations.d.ts +5 -1
- package/dist/types/sdk/host/events.d.ts +4 -0
- package/dist/types/sdk/host/host.d.ts +2 -1
- package/dist/types/sdk/host/prompt-image-upload.d.ts +43 -0
- package/dist/types/sdk/host/session-runtime.d.ts +40 -8
- package/dist/types/sdk/host/surface-policy.d.ts +2 -1
- package/dist/types/sdk/lifecycle/service.d.ts +12 -0
- package/dist/types/sdk/prompt-deadline-flush.d.ts +42 -4
- package/dist/types/sdk/prompt-deadline-manager.d.ts +2 -0
- package/dist/types/sdk/prompt-status.d.ts +11 -4
- package/dist/types/sdk/protocol/adapter-validation.d.ts +10 -4
- package/dist/types/sdk/reconciliation-extensions.d.ts +1 -1
- package/dist/types/sdk/session-list.d.ts +1 -1
- package/dist/types/session/agent-session.d.ts +107 -9
- package/dist/types/session/internal/managed-session-scope.d.ts +2 -2
- package/dist/types/session/internal/managed-session-storage.d.ts +1 -1
- package/dist/types/session/internal/native-publish-outcome.d.ts +1 -1
- package/dist/types/session/messages.d.ts +5 -1
- package/dist/types/session/session-manager.d.ts +29 -3
- package/dist/types/session/startup-auth-config.d.ts +24 -2
- package/dist/types/session/streaming-output.d.ts +11 -0
- package/dist/types/session/terminal-abort.d.ts +3 -1
- package/dist/types/session-import/service.d.ts +1 -1
- package/dist/types/skill-state/workflow-mutation-guard.d.ts +20 -4
- package/dist/types/slash-commands/helpers/mcp.d.ts +5 -0
- package/dist/types/slash-commands/helpers/provider-auth-status.d.ts +8 -0
- package/dist/types/ssh/ssh-executor.d.ts +8 -1
- package/dist/types/system-prompt.d.ts +3 -2
- package/dist/types/task/executor.d.ts +19 -2
- package/dist/types/task/role-body.d.ts +11 -0
- package/dist/types/tools/ast-edit-write-path.d.ts +10 -0
- package/dist/types/tools/atomic-file-write.d.ts +9 -7
- package/dist/types/tools/awaiting-input.d.ts +28 -0
- package/dist/types/tools/bash-allowed-prefixes.d.ts +17 -0
- package/dist/types/tools/bash-skill-urls.d.ts +4 -0
- package/dist/types/tools/bash.d.ts +7 -0
- package/dist/types/tools/descriptors.d.ts +15 -2
- package/dist/types/tools/fetch.d.ts +7 -1
- package/dist/types/tools/index.d.ts +2 -0
- package/dist/types/tools/irc.d.ts +5 -3
- package/dist/types/tools/python.d.ts +1 -1
- package/dist/types/tools/report-issue.d.ts +41 -0
- package/dist/types/tools/subagent.d.ts +23 -0
- package/dist/types/tools/tmux-self-injection-guard.d.ts +2 -0
- package/dist/types/tools/ultragoal-ask-guard.d.ts +1 -1
- package/dist/types/tools/write.d.ts +2 -0
- package/dist/types/utils/file-mentions.d.ts +5 -0
- package/dist/types/utils/image-limits.d.ts +7 -0
- package/dist/types/utils/image-loading.d.ts +0 -1
- package/dist/types/utils/open.d.ts +0 -1
- package/dist/types/utils/pasted-image-loading.d.ts +1 -5
- package/dist/types/utils/prompt-suggestion.d.ts +2 -2
- package/dist/types/utils/shell-snapshot.d.ts +2 -0
- package/dist/types/utils/title-generator.d.ts +13 -3
- package/dist/types/web/scrapers/types.d.ts +8 -1
- package/dist/types/web/search/providers/codex.d.ts +6 -7
- package/dist/types/web/search/providers/insane.d.ts +7 -1
- package/dist/types/web/search/providers/searxng.d.ts +5 -0
- package/package.json +10 -9
- package/scripts/acp-conformance-agent.ts +12 -2
- package/scripts/build-binary.ts +2 -1
- package/scripts/capture-subagent-compact-panel-showcase.ts +105 -0
- package/scripts/generate-docs-index.ts +8 -1
- package/scripts/generate-sdk-operation-inventory.ts +38 -4
- package/src/async/job-manager.ts +356 -56
- package/src/async/result-formatting.ts +40 -0
- package/src/autoresearch/git.ts +9 -2
- package/src/autoresearch/prompts/prompt-setup.md +1 -1
- package/src/capability/fs.ts +58 -22
- package/src/capability/index.ts +2 -2
- package/src/capability/rule.ts +11 -2
- package/src/cli/accounts-cli.ts +176 -8
- package/src/cli/append-system-prompt.ts +12 -0
- package/src/cli/args.ts +11 -7
- package/src/cli/auth-broker-cli.ts +21 -11
- package/src/cli/customize-doctor-precedence.ts +31 -0
- package/src/cli/customize-doctor.ts +49 -39
- package/src/cli/doctor/install-repairs.ts +35 -5
- package/src/cli/fast-help.ts +1 -3
- package/src/cli/install-activation.ts +47 -4
- package/src/cli/migrate-cli.ts +19 -6
- package/src/cli/public-command-errors.ts +6 -0
- package/src/cli/root-flags.ts +2 -4
- package/src/cli/stats-cli.ts +9 -5
- package/src/cli/update-cli.ts +471 -13
- package/src/cli-ordinary.ts +7 -2
- package/src/commands/accounts.ts +10 -5
- package/src/commands/harness.ts +25 -15
- package/src/commands/migrate.ts +3 -3
- package/src/commands/sdk.ts +277 -50
- package/src/commands/ultragoal.ts +16 -8
- package/src/commit/agentic/agent.ts +6 -6
- package/src/commit/analysis/conventional.ts +14 -5
- package/src/commit/changelog/index.ts +39 -1
- package/src/commit/map-reduce/index.ts +7 -7
- package/src/commit/message.ts +10 -3
- package/src/commit/pipeline.ts +12 -12
- package/src/config/autorouting-tier-map.ts +50 -1
- package/src/config/config-file.ts +106 -3
- package/src/config/config-hot-reload-trust.ts +148 -0
- package/src/config/config-hot-reload.ts +742 -0
- package/src/config/file-lock.ts +1615 -328
- package/src/config/keybindings.ts +154 -7
- package/src/config/model-bindings-applier.ts +85 -47
- package/src/config/model-discovery-manager.ts +10 -0
- package/src/config/model-profile-activation.ts +889 -148
- package/src/config/model-registry.ts +1706 -205
- package/src/config/model-resolver.ts +52 -22
- package/src/config/models-config-schema.ts +6 -0
- package/src/config/settings-schema.ts +73 -4
- package/src/config/settings.ts +460 -24
- package/src/coordinator-mcp/policy.ts +26 -1
- package/src/coordinator-mcp/server.ts +37 -2
- package/src/crash/sanitize.ts +7 -1
- package/src/customization/import.ts +279 -8
- package/src/customization/inventory.ts +24 -8
- package/src/customization/types.ts +1 -0
- package/src/dap/client.ts +3 -2
- package/src/dap/config.ts +31 -11
- package/src/dap/defaults.json +1 -1
- package/src/dap/session.ts +161 -36
- package/src/debug/crash-diagnostics.ts +89 -6
- package/src/debug/report-bundle.ts +90 -2
- package/src/debug/system-info.ts +8 -3
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/shared/base-url.ts +21 -7
- package/src/discovery/agents-md.ts +1 -1
- package/src/discovery/builtin.ts +4 -3
- package/src/discovery/helpers.ts +25 -16
- package/src/discovery/mcp-compat.ts +120 -17
- package/src/edit/apply-patch/index.ts +12 -1
- package/src/edit/index.ts +204 -22
- package/src/edit/modes/patch.ts +214 -8
- package/src/edit/modes/replace.ts +136 -0
- package/src/eval/js/context-manager.ts +29 -3
- package/src/eval/js/worker-entry.ts +51 -18
- package/src/eval/py/executor.ts +14 -4
- package/src/eval/py/runner.py +144 -5
- package/src/eval/py/runtime.ts +44 -4
- package/src/exec/bash-executor.ts +81 -4
- package/src/exec/bash-shell-guardian.ts +4 -1
- package/src/exec/bash-shell-supervisor.ts +8 -4
- package/src/exec/isolated-shell.ts +5 -1
- package/src/exec/non-interactive-env.ts +0 -1
- package/src/export/html/index.ts +86 -6
- package/src/export/ttsr.ts +176 -1
- package/src/extensibility/custom-tools/wrapper.ts +3 -1
- package/src/extensibility/extensions/loader.ts +10 -1
- package/src/extensibility/extensions/ouroboros-ooo-bridge.ts +63 -1
- package/src/extensibility/extensions/types.ts +5 -1
- package/src/extensibility/hooks/loader.ts +10 -2
- package/src/extensibility/plugins/marketplace/fetcher.ts +2 -2
- package/src/extensibility/plugins/marketplace/manager.ts +36 -10
- package/src/extensibility/slash-commands.ts +5 -0
- package/src/gjc-runtime/gc-runtime.ts +37 -7
- package/src/gjc-runtime/launch-tmux.ts +30 -15
- package/src/gjc-runtime/launch-worktree.test.ts +148 -0
- package/src/gjc-runtime/launch-worktree.ts +101 -14
- package/src/gjc-runtime/managed-owner-admission.ts +46 -2
- package/src/gjc-runtime/ralplan-current-final.ts +294 -0
- package/src/gjc-runtime/ralplan-runtime.ts +95 -1
- package/src/gjc-runtime/session-resolution.ts +38 -6
- package/src/gjc-runtime/session-state-lock.ts +59 -14
- package/src/gjc-runtime/state-runtime.ts +23 -19
- package/src/gjc-runtime/state-writer.ts +109 -5
- package/src/gjc-runtime/tmux-sessions.ts +93 -13
- package/src/gjc-runtime/ultragoal-change-set.ts +90 -11
- package/src/gjc-runtime/ultragoal-guard.ts +9 -1
- package/src/gjc-runtime/ultragoal-runtime.ts +15 -5
- package/src/harness-control-plane/finalize.ts +11 -0
- package/src/harness-control-plane/receipt-spool.ts +105 -28
- package/src/harness-control-plane/storage.ts +124 -6
- package/src/hindsight/content.ts +116 -16
- package/src/hindsight/mental-models.ts +22 -10
- package/src/hindsight/state.ts +7 -4
- package/src/hooks/native-skill-hook.ts +17 -12
- package/src/internal-urls/artifact-protocol.ts +3 -1
- package/src/internal-urls/docs-index.generated.ts +23 -22
- package/src/internal-urls/local-protocol.ts +167 -8
- package/src/internal-urls/types.ts +2 -0
- package/src/lsp/client.ts +2 -1
- package/src/lsp/clients/biome-client.ts +2 -0
- package/src/lsp/clients/swiftlint-client.ts +2 -0
- package/src/lsp/index.ts +29 -0
- package/src/lsp/workspace-path.ts +23 -0
- package/src/main.ts +330 -92
- package/src/memories/index.ts +25 -2
- package/src/migrate/action-planner.ts +574 -2
- package/src/migrate/adapters/claude-code.ts +162 -5
- package/src/migrate/adapters/codex.ts +77 -7
- package/src/migrate/adapters/index.ts +258 -5
- package/src/migrate/adapters/opencode.ts +10 -1
- package/src/migrate/executor.ts +222 -7
- package/src/migrate/hook-module.ts +193 -0
- package/src/migrate/report.ts +63 -2
- package/src/migrate/types.ts +84 -4
- package/src/modes/DESIGN.md +51 -0
- package/src/modes/acp/acp-agent.ts +10 -1
- package/src/modes/acp/permission-mode.ts +18 -1
- package/src/modes/components/agent-dashboard.ts +20 -4
- package/src/modes/components/assistant-message.ts +55 -1
- package/src/modes/components/customization/customization-dashboard.ts +7 -0
- package/src/modes/components/customization/import-wizard.ts +29 -3
- package/src/modes/components/model-selector.ts +157 -103
- package/src/modes/components/settings-selector.ts +103 -37
- package/src/modes/components/welcome.ts +3 -1
- package/src/modes/controllers/command-controller.ts +300 -9
- package/src/modes/controllers/event-controller.ts +1 -1
- package/src/modes/controllers/extension-ui-controller.ts +31 -1
- package/src/modes/controllers/goal-mode-controller.ts +79 -10
- package/src/modes/controllers/input-controller.ts +2 -0
- package/src/modes/controllers/plan-mode-controller.ts +66 -11
- package/src/modes/controllers/runtime-mcp-command-controller.ts +7 -6
- package/src/modes/controllers/selector-controller.ts +76 -7
- package/src/modes/interactive-mode.ts +123 -4
- package/src/modes/prompt-suggestion-controller.ts +1 -1
- package/src/modes/runtime-init.ts +5 -1
- package/src/modes/theme/theme.ts +15 -0
- package/src/modes/utils/host-status.ts +21 -10
- package/src/prompts/agent-fragments/browser-aside.md +2 -2
- package/src/prompts/system/irc-incoming.md +3 -1
- package/src/prompts/tools/debug.md +1 -1
- package/src/prompts/tools/irc.md +1 -1
- package/src/prompts/tools/read.md +1 -1
- package/src/prompts/tools/report-issue.md +13 -0
- package/src/prompts/tools/task.md +1 -1
- package/src/runtime-credential-selector.ts +2 -2
- package/src/runtime-mcp/content-limits.ts +7 -0
- package/src/runtime-mcp/manager-pool.test.ts +5 -4
- package/src/runtime-mcp/manager.ts +40 -3
- package/src/runtime-mcp/oauth-flow.ts +32 -6
- package/src/runtime-mcp/plugin-mcp-name-filter.ts +62 -0
- package/src/runtime-mcp/project-host-values.ts +12 -8
- package/src/runtime-mcp/render.ts +16 -1
- package/src/runtime-mcp/tool-bridge.ts +194 -21
- package/src/runtime-mcp/transports/stdio.ts +2 -1
- package/src/sdk/broker/broker-exit.ts +10 -5
- package/src/sdk/broker/broker.ts +484 -85
- package/src/sdk/broker/daemon-entry.ts +338 -116
- package/src/sdk/broker/doctor-restart.ts +2 -1
- package/src/sdk/broker/ensure.ts +1214 -268
- package/src/sdk/broker/hop.ts +286 -0
- package/src/sdk/broker/lifecycle-ledger.ts +38 -11
- package/src/sdk/broker/lifecycle.ts +102 -6
- package/src/sdk/broker/lock-host-identity.ts +29 -0
- package/src/sdk/broker/session-index.ts +91 -16
- package/src/sdk/broker/transport.ts +17 -1
- package/src/sdk/bus/chat-command-policy.ts +16 -3
- package/src/sdk/bus/chat-daemon-control.ts +2 -2
- package/src/sdk/bus/index.ts +460 -35
- package/src/sdk/bus/reconciliation-store.ts +201 -8
- package/src/sdk/bus/session-control.ts +2 -0
- package/src/sdk/bus/slack-daemon.ts +105 -9
- package/src/sdk/bus/telegram-daemon-contract.ts +9 -1
- package/src/sdk/bus/telegram-daemon.ts +10 -2
- package/src/sdk/bus/threaded-render.ts +20 -1
- package/src/sdk/cli/session-cli.ts +23 -6
- package/src/sdk/host/control/dispatch.ts +13 -1
- package/src/sdk/host/control/operations.ts +10 -1
- package/src/sdk/host/events.ts +67 -4
- package/src/sdk/host/host.ts +8 -2
- package/src/sdk/host/prompt-image-upload.ts +438 -0
- package/src/sdk/host/sdk-surface-parity.test.ts +15 -0
- package/src/sdk/host/session-runtime.test.ts +1737 -129
- package/src/sdk/host/session-runtime.ts +684 -83
- package/src/sdk/host/surface-policy.ts +4 -0
- package/src/sdk/host/websocket-transport.lifecycle.test.ts +90 -2
- package/src/sdk/host/websocket-transport.ts +19 -7
- package/src/sdk/lifecycle/service.ts +15 -1
- package/src/sdk/prompt-deadline-flush.ts +78 -5
- package/src/sdk/prompt-deadline-manager.ts +68 -14
- package/src/sdk/prompt-status.ts +6 -4
- package/src/sdk/protocol/adapter-validation.ts +81 -12
- package/src/sdk/protocol/operation-inventory.generated.json +261 -2
- package/src/sdk/protocol/operation-registry.ts +33 -3
- package/src/sdk/reconciliation-extensions.ts +1 -0
- package/src/sdk/session-list.ts +1 -0
- package/src/sdk/session.ts +237 -97
- package/src/session/agent-session.ts +2726 -479
- package/src/session/history-storage.ts +182 -12
- package/src/session/internal/managed-session-scope.ts +173 -57
- package/src/session/internal/managed-session-storage.ts +85 -12
- package/src/session/internal/native-publish-outcome.ts +5 -1
- package/src/session/messages.ts +47 -6
- package/src/session/session-manager.ts +326 -19
- package/src/session/startup-auth-config.ts +116 -8
- package/src/session/streaming-output.ts +262 -4
- package/src/session/terminal-abort.ts +14 -2
- package/src/session-import/redact.ts +53 -2
- package/src/session-import/service.ts +1 -0
- package/src/skill-state/workflow-mutation-guard.ts +2145 -206
- package/src/slash-commands/builtin-registry.ts +21 -6
- package/src/slash-commands/helpers/credential-switch.ts +10 -5
- package/src/slash-commands/helpers/mcp.ts +11 -3
- package/src/slash-commands/helpers/provider-auth-status.ts +456 -0
- package/src/ssh/ssh-executor.ts +9 -2
- package/src/stt/recorder.ts +26 -9
- package/src/system-prompt.ts +61 -16
- package/src/task/executor.ts +115 -20
- package/src/task/index.ts +389 -175
- package/src/task/role-body.ts +84 -0
- package/src/task/token-log-mode.test.ts +162 -0
- package/src/task/token-log.ts +91 -2
- package/src/tools/archive-reader.ts +650 -37
- package/src/tools/ask.ts +1 -0
- package/src/tools/ast-edit-write-path.ts +64 -0
- package/src/tools/ast-edit.ts +18 -1
- package/src/tools/ast-grep.ts +7 -2
- package/src/tools/atomic-file-write.ts +46 -15
- package/src/tools/auto-generated-guard.ts +15 -3
- package/src/tools/awaiting-input.ts +114 -0
- package/src/tools/bash-allowed-prefixes.ts +214 -6
- package/src/tools/bash-interactive.ts +14 -2
- package/src/tools/bash-skill-urls.ts +58 -5
- package/src/tools/bash.ts +113 -26
- package/src/tools/browser/tab-worker.ts +39 -13
- package/src/tools/browser.ts +17 -7
- package/src/tools/cron.ts +10 -1
- package/src/tools/debug.ts +16 -8
- package/src/tools/descriptors.test.ts +44 -0
- package/src/tools/descriptors.ts +50 -6
- package/src/tools/eval.ts +15 -0
- package/src/tools/fetch.ts +93 -4
- package/src/tools/gh.ts +27 -12
- package/src/tools/image-gen.ts +20 -6
- package/src/tools/index.ts +2 -0
- package/src/tools/irc.ts +5 -3
- package/src/tools/monitor.ts +9 -1
- package/src/tools/output-meta.ts +74 -5
- package/src/tools/python.ts +1 -1
- package/src/tools/read.ts +26 -37
- package/src/tools/recipe/runner.ts +23 -12
- package/src/tools/render-utils.ts +2 -2
- package/src/tools/report-issue.ts +184 -0
- package/src/tools/search.ts +3 -2
- package/src/tools/ssh.ts +274 -8
- package/src/tools/subagent-render.ts +114 -12
- package/src/tools/subagent.ts +118 -5
- package/src/tools/tmux-self-injection-guard.ts +3301 -122
- package/src/tools/todo-write.ts +41 -3
- package/src/tools/tool-catalog.generated.ts +32 -4
- package/src/tools/ultragoal-ask-guard.ts +13 -1
- package/src/tools/write.ts +42 -3
- package/src/tui/tree-list.ts +15 -1
- package/src/utils/commit-message-generator.ts +12 -4
- package/src/utils/external-editor.ts +21 -7
- package/src/utils/file-mentions.ts +75 -7
- package/src/utils/git.ts +38 -7
- package/src/utils/image-limits.ts +8 -0
- package/src/utils/image-loading.ts +1 -1
- package/src/utils/open.ts +73 -4
- package/src/utils/pasted-image-loading.ts +9 -8
- package/src/utils/prompt-suggestion.ts +5 -4
- package/src/utils/shell-snapshot.ts +9 -1
- package/src/utils/title-generator.ts +72 -22
- package/src/web/scrapers/index.ts +3 -1
- package/src/web/scrapers/types.ts +8 -0
- package/src/web/scrapers/youtube.ts +3 -2
- package/src/web/search/index.ts +2 -1
- package/src/web/search/providers/codex.ts +29 -32
- package/src/web/search/providers/insane.ts +91 -28
- package/src/web/search/providers/searxng.ts +62 -10
package/src/discovery/helpers.ts
CHANGED
|
@@ -202,14 +202,24 @@ export function getProjectPath(ctx: LoadContext, source: SourceId, subpath: stri
|
|
|
202
202
|
}
|
|
203
203
|
|
|
204
204
|
/** Build the filesystem authority for a provider read. */
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
205
|
+
type DiscoveryReadContext = Pick<
|
|
206
|
+
LoadContext,
|
|
207
|
+
"home" | "isolatedHome" | "userAgentDir" | "homeIdentity" | "userAgentIdentity" | "bypassCache"
|
|
208
|
+
> & {
|
|
209
|
+
repoRoot?: string | null;
|
|
210
|
+
cwd?: string;
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
export function getReadOptions(ctx: DiscoveryReadContext, scope: ReadScope): ReadFileOptions | undefined {
|
|
214
|
+
if (!ctx.isolatedHome) {
|
|
215
|
+
const boundary = scope === "project" ? (ctx.repoRoot ?? ctx.cwd) : undefined;
|
|
216
|
+
if (!boundary) return ctx.bypassCache ? { bypassCache: true } : undefined;
|
|
217
|
+
return {
|
|
218
|
+
...(ctx.bypassCache ? { bypassCache: true as const } : {}),
|
|
219
|
+
containmentRoot: boundary,
|
|
220
|
+
scope,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
213
223
|
return {
|
|
214
224
|
isolatedHome: true,
|
|
215
225
|
home: ctx.home,
|
|
@@ -222,15 +232,14 @@ export function getReadOptions(
|
|
|
222
232
|
}
|
|
223
233
|
|
|
224
234
|
export async function getReadOptionsForContainment(
|
|
225
|
-
ctx:
|
|
226
|
-
LoadContext,
|
|
227
|
-
"home" | "isolatedHome" | "userAgentDir" | "homeIdentity" | "userAgentIdentity" | "bypassCache"
|
|
228
|
-
>,
|
|
235
|
+
ctx: DiscoveryReadContext,
|
|
229
236
|
scope: ReadScope,
|
|
230
237
|
containmentRoot?: string,
|
|
231
238
|
): Promise<ReadFileOptions | undefined> {
|
|
232
239
|
const options = getReadOptions(ctx, scope);
|
|
233
|
-
|
|
240
|
+
// Ordinary reads keep the repository boundary from getReadOptions. The extra
|
|
241
|
+
// root is an isolated-home constraint and was not applied on this path before.
|
|
242
|
+
if (!ctx.isolatedHome || !options || !containmentRoot) return options;
|
|
234
243
|
const containmentRootIdentity = await capturePathIdentity(containmentRoot);
|
|
235
244
|
if (!containmentRootIdentity) return undefined;
|
|
236
245
|
return { ...options, containmentRoot, containmentRootIdentity };
|
|
@@ -298,7 +307,7 @@ export function buildRuleFromMarkdown(
|
|
|
298
307
|
},
|
|
299
308
|
): Rule {
|
|
300
309
|
const { frontmatter, body } = parseFrontmatter(content, { source: filePath });
|
|
301
|
-
const { condition, scope } = parseRuleConditionAndScope(frontmatter as RuleFrontmatter);
|
|
310
|
+
const { condition, astCondition, scope } = parseRuleConditionAndScope(frontmatter as RuleFrontmatter);
|
|
302
311
|
|
|
303
312
|
let globs: string[] | undefined;
|
|
304
313
|
if (Array.isArray(frontmatter.globs)) {
|
|
@@ -329,6 +338,7 @@ export function buildRuleFromMarkdown(
|
|
|
329
338
|
alwaysApply: frontmatter.alwaysApply === true,
|
|
330
339
|
description: typeof frontmatter.description === "string" ? frontmatter.description : undefined,
|
|
331
340
|
condition,
|
|
341
|
+
astCondition,
|
|
332
342
|
scope,
|
|
333
343
|
interruptMode,
|
|
334
344
|
repeatMode,
|
|
@@ -1005,8 +1015,7 @@ export async function readContainedFile(
|
|
|
1005
1015
|
rootIdentity = capturedRoot;
|
|
1006
1016
|
if (
|
|
1007
1017
|
expectedRootIdentity !== undefined &&
|
|
1008
|
-
(rootIdentity.dev !==
|
|
1009
|
-
rootIdentity.ino !== BigInt(expectedRootIdentity.ino))
|
|
1018
|
+
(rootIdentity.dev !== expectedRootIdentity.dev || rootIdentity.ino !== expectedRootIdentity.ino)
|
|
1010
1019
|
)
|
|
1011
1020
|
return null;
|
|
1012
1021
|
await SkillDiscoveryTestHooks.afterContainedRootValidated?.(root);
|
|
@@ -110,23 +110,63 @@ interface CodexMcpServerConfig {
|
|
|
110
110
|
command?: string;
|
|
111
111
|
args?: string[];
|
|
112
112
|
env?: Record<string, string>;
|
|
113
|
-
|
|
113
|
+
/** List of env-var names, or `{ name }` entries. Not a value table. */
|
|
114
|
+
env_vars?: unknown;
|
|
114
115
|
url?: string;
|
|
115
116
|
http_headers?: Record<string, string>;
|
|
116
|
-
|
|
117
|
-
|
|
117
|
+
/** Header name to env-var name. Not a header value. */
|
|
118
|
+
env_http_headers?: unknown;
|
|
119
|
+
/** Env-var name whose value is the bearer token. Not the token. */
|
|
120
|
+
bearer_token_env_var?: unknown;
|
|
118
121
|
cwd?: string;
|
|
119
122
|
startup_timeout_sec?: number;
|
|
120
123
|
tool_timeout_sec?: number;
|
|
121
124
|
}
|
|
122
125
|
|
|
126
|
+
/** POSIX env-var name. Rejects values that are not names so they are not stored. */
|
|
127
|
+
function isEnvVarName(value: string): boolean {
|
|
128
|
+
return /^[A-Za-z_][A-Za-z0-9_]*$/.test(value);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** `${NAME}` keeps the indirection. Callers must not read the process environment. */
|
|
132
|
+
function envVarReference(name: string): string {
|
|
133
|
+
return `\${${name}}`;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function codexEnvVarEntry(entry: unknown): { name: string; source: string | undefined } | undefined {
|
|
137
|
+
if (typeof entry === "string") return isEnvVarName(entry) ? { name: entry, source: undefined } : undefined;
|
|
138
|
+
if (isRecord(entry) && typeof entry.name === "string" && isEnvVarName(entry.name)) {
|
|
139
|
+
return { name: entry.name, source: typeof entry.source === "string" ? entry.source : undefined };
|
|
140
|
+
}
|
|
141
|
+
return undefined;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/** Codex remote-executor sources have no local GJC equivalent. */
|
|
145
|
+
function isUnsupportedEnvSource(source: string | undefined): boolean {
|
|
146
|
+
return source !== undefined && source !== "local";
|
|
147
|
+
}
|
|
148
|
+
|
|
123
149
|
/**
|
|
124
150
|
* Extract normalized MCP servers from a Codex `config.toml` `[mcp_servers.*]`
|
|
125
151
|
* section. Codex's config does not carry an `enabled` concept; imported servers
|
|
126
152
|
* default to autoload (startup) behavior after import. Bounded to the supplied
|
|
127
153
|
* content: no filesystem scanning, no user-home reads.
|
|
154
|
+
*
|
|
155
|
+
* `env_vars`, `env_http_headers`, and `bearer_token_env_var` name variables.
|
|
156
|
+
* The process environment is not read. A local name is stored as `${NAME}`
|
|
157
|
+
* only when the destination keeps operator config. A project destination omits
|
|
158
|
+
* the reference: project mcp.json is expanded on a later run, and a name such
|
|
159
|
+
* as `CI_JOB_JWT_V2` is not treated as sensitive, so persisting it would
|
|
160
|
+
* forward a host value. The source level is metadata and does not decide this.
|
|
161
|
+
* A static `env` or `http_headers` value is copied. An entry whose source is
|
|
162
|
+
* not `local` is skipped.
|
|
128
163
|
*/
|
|
129
|
-
function extractCodexMcpServers(
|
|
164
|
+
function extractCodexMcpServers(
|
|
165
|
+
toml: Record<string, unknown>,
|
|
166
|
+
warnings: string[],
|
|
167
|
+
sourcePath: string,
|
|
168
|
+
omitEnvReferences: boolean,
|
|
169
|
+
): Record<string, Partial<MCPServer>> {
|
|
130
170
|
if (!toml.mcp_servers || !isRecord(toml.mcp_servers)) return {};
|
|
131
171
|
|
|
132
172
|
const codexServers = toml.mcp_servers as Record<string, CodexMcpServerConfig>;
|
|
@@ -146,11 +186,38 @@ function extractCodexMcpServers(toml: Record<string, unknown>): Record<string, P
|
|
|
146
186
|
};
|
|
147
187
|
|
|
148
188
|
const env: Record<string, string> = { ...(isStringRecord(serverConfig.env) ? serverConfig.env : {}) };
|
|
149
|
-
if (Array.isArray(serverConfig.env_vars)) {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
189
|
+
if (serverConfig.env_vars !== undefined && !Array.isArray(serverConfig.env_vars)) {
|
|
190
|
+
warnings.push(
|
|
191
|
+
`skipped env_vars for "${name}" in ${sourcePath} because it is not a list of environment variable names`,
|
|
192
|
+
);
|
|
193
|
+
} else if (Array.isArray(serverConfig.env_vars)) {
|
|
194
|
+
for (const entry of serverConfig.env_vars) {
|
|
195
|
+
const parsed = codexEnvVarEntry(entry);
|
|
196
|
+
if (!parsed) {
|
|
197
|
+
warnings.push(
|
|
198
|
+
`skipped env_vars entry for "${name}" in ${sourcePath} because it is not an environment variable name`,
|
|
199
|
+
);
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
if (isUnsupportedEnvSource(parsed.source)) {
|
|
203
|
+
warnings.push(
|
|
204
|
+
`skipped env_vars entry ${parsed.name} for "${name}" in ${sourcePath} because source "${parsed.source}" is not executed locally`,
|
|
205
|
+
);
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
if (Object.hasOwn(env, parsed.name)) {
|
|
209
|
+
warnings.push(
|
|
210
|
+
`kept static env ${parsed.name} for "${name}" in ${sourcePath} and did not read the environment`,
|
|
211
|
+
);
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
if (omitEnvReferences) {
|
|
215
|
+
warnings.push(
|
|
216
|
+
`skipped project-scope environment reference ${parsed.name} for "${name}" in ${sourcePath} so a later load cannot expand a host value`,
|
|
217
|
+
);
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
220
|
+
env[parsed.name] = envVarReference(parsed.name);
|
|
154
221
|
}
|
|
155
222
|
}
|
|
156
223
|
if (Object.keys(env).length > 0) server.env = env;
|
|
@@ -158,16 +225,50 @@ function extractCodexMcpServers(toml: Record<string, unknown>): Record<string, P
|
|
|
158
225
|
const headers: Record<string, string> = {
|
|
159
226
|
...(isStringRecord(serverConfig.http_headers) ? serverConfig.http_headers : {}),
|
|
160
227
|
};
|
|
161
|
-
if (isRecord(serverConfig.env_http_headers)) {
|
|
228
|
+
if (serverConfig.env_http_headers !== undefined && !isRecord(serverConfig.env_http_headers)) {
|
|
229
|
+
warnings.push(
|
|
230
|
+
`skipped env_http_headers for "${name}" in ${sourcePath} because it is not a table of environment variable names`,
|
|
231
|
+
);
|
|
232
|
+
} else if (isRecord(serverConfig.env_http_headers)) {
|
|
162
233
|
for (const [headerName, envVarName] of Object.entries(serverConfig.env_http_headers)) {
|
|
163
|
-
if (typeof envVarName !== "string")
|
|
164
|
-
|
|
165
|
-
|
|
234
|
+
if (typeof envVarName !== "string" || !isEnvVarName(envVarName)) {
|
|
235
|
+
warnings.push(
|
|
236
|
+
`skipped env_http_headers entry for "${name}" in ${sourcePath} because its value is not an environment variable name`,
|
|
237
|
+
);
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
if (Object.hasOwn(headers, headerName)) {
|
|
241
|
+
warnings.push(
|
|
242
|
+
`kept static header ${headerName} for "${name}" in ${sourcePath} and did not read ${envVarName}`,
|
|
243
|
+
);
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
246
|
+
if (omitEnvReferences) {
|
|
247
|
+
warnings.push(
|
|
248
|
+
`skipped project-scope environment reference ${envVarName} for "${name}" in ${sourcePath} so a later load cannot expand a host value`,
|
|
249
|
+
);
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
headers[headerName] = envVarReference(envVarName);
|
|
166
253
|
}
|
|
167
254
|
}
|
|
168
|
-
if (
|
|
169
|
-
const
|
|
170
|
-
if (
|
|
255
|
+
if (serverConfig.bearer_token_env_var !== undefined) {
|
|
256
|
+
const bearerName = serverConfig.bearer_token_env_var;
|
|
257
|
+
if (typeof bearerName !== "string" || !isEnvVarName(bearerName)) {
|
|
258
|
+
warnings.push(
|
|
259
|
+
`skipped bearer_token_env_var for "${name}" in ${sourcePath} because it is not an environment variable name`,
|
|
260
|
+
);
|
|
261
|
+
} else if (Object.hasOwn(headers, "Authorization")) {
|
|
262
|
+
warnings.push(
|
|
263
|
+
`kept static Authorization for "${name}" in ${sourcePath} and did not read bearer_token_env_var ${bearerName}`,
|
|
264
|
+
);
|
|
265
|
+
} else if (omitEnvReferences) {
|
|
266
|
+
warnings.push(
|
|
267
|
+
`skipped project-scope environment reference ${bearerName} for "${name}" in ${sourcePath} so a later load cannot expand a host value`,
|
|
268
|
+
);
|
|
269
|
+
} else {
|
|
270
|
+
headers.Authorization = `Bearer ${envVarReference(bearerName)}`;
|
|
271
|
+
}
|
|
171
272
|
}
|
|
172
273
|
if (Object.keys(headers).length > 0) server.headers = headers;
|
|
173
274
|
|
|
@@ -192,6 +293,7 @@ export function normalizeCodexMcpToml(
|
|
|
192
293
|
content: string,
|
|
193
294
|
sourcePath: string,
|
|
194
295
|
level: "project" | "user" = "project",
|
|
296
|
+
options?: { omitEnvReferences?: boolean },
|
|
195
297
|
): MCPCompatNormalizeResult {
|
|
196
298
|
const items: MCPServer[] = [];
|
|
197
299
|
const warnings: string[] = [];
|
|
@@ -212,7 +314,8 @@ export function normalizeCodexMcpToml(
|
|
|
212
314
|
}
|
|
213
315
|
}
|
|
214
316
|
}
|
|
215
|
-
const
|
|
317
|
+
const omitEnvReferences = options?.omitEnvReferences ?? level === "project";
|
|
318
|
+
const servers = extractCodexMcpServers(parsed, warnings, sourcePath, omitEnvReferences);
|
|
216
319
|
for (const [name, config] of Object.entries(servers)) {
|
|
217
320
|
items.push({
|
|
218
321
|
name,
|
|
@@ -12,7 +12,13 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
import { ApplyPatchError } from "../diff";
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
type ApplyPatchOptions,
|
|
17
|
+
type ApplyPatchResult,
|
|
18
|
+
applyPatch,
|
|
19
|
+
type PatchInput,
|
|
20
|
+
preflightPatchMkdir,
|
|
21
|
+
} from "../modes/patch";
|
|
16
22
|
import { parseApplyPatch } from "./parser";
|
|
17
23
|
|
|
18
24
|
export * from "./parser";
|
|
@@ -48,6 +54,11 @@ export async function applyCodexPatch(patchText: string, options: ApplyPatchOpti
|
|
|
48
54
|
deleted: [] as string[],
|
|
49
55
|
};
|
|
50
56
|
|
|
57
|
+
// Containment is checked for every hunk before the first write. A later
|
|
58
|
+
// I/O failure still leaves earlier hunks applied, per spec §6.1.
|
|
59
|
+
for (const hunk of hunks) {
|
|
60
|
+
await preflightPatchMkdir(hunk, options);
|
|
61
|
+
}
|
|
51
62
|
for (const hunk of hunks) {
|
|
52
63
|
const result = await applyPatch(hunk, options);
|
|
53
64
|
results.push(result);
|
package/src/edit/index.ts
CHANGED
|
@@ -3,9 +3,12 @@ import { prompt } from "@gajae-code/utils";
|
|
|
3
3
|
import type * as z from "zod/v4";
|
|
4
4
|
import {
|
|
5
5
|
executeHashlineSingle,
|
|
6
|
+
type HashlineEdit,
|
|
6
7
|
HashlineMismatchError,
|
|
7
8
|
type HashlineParams,
|
|
8
9
|
hashlineEditParamsSchema,
|
|
10
|
+
parseHashline,
|
|
11
|
+
splitHashlineInputs,
|
|
9
12
|
} from "../hashline";
|
|
10
13
|
import hashlineGrammarTemplate from "../hashline/grammar.lark" with { type: "text" };
|
|
11
14
|
import { resolveHashlineGrammarPlaceholders } from "../hashline/hash";
|
|
@@ -21,13 +24,28 @@ import hashlineDescription from "../prompts/tools/hashline.md" with { type: "tex
|
|
|
21
24
|
import patchDescription from "../prompts/tools/patch.md" with { type: "text" };
|
|
22
25
|
import replaceDescription from "../prompts/tools/replace.md" with { type: "text" };
|
|
23
26
|
import type { ToolSession } from "../tools";
|
|
27
|
+
import { assertEditableFile } from "../tools/auto-generated-guard";
|
|
28
|
+
import { resolvePlanPath } from "../tools/plan-mode-guard";
|
|
24
29
|
import { VimTool, vimSchema } from "../tools/vim";
|
|
25
30
|
import { type EditMode, resolveEditMode, resolveForcedEnvEditMode } from "../utils/edit-mode";
|
|
26
31
|
import type { VimToolDetails } from "../vim/types";
|
|
27
|
-
import {
|
|
32
|
+
import { normalizeCreateContent } from "./diff";
|
|
33
|
+
import {
|
|
34
|
+
type ApplyPatchEntry,
|
|
35
|
+
type ApplyPatchParams,
|
|
36
|
+
applyPatchSchema,
|
|
37
|
+
expandApplyPatchToEntries,
|
|
38
|
+
expandApplyPatchToPreviewEntries,
|
|
39
|
+
} from "./modes/apply-patch";
|
|
28
40
|
import applyPatchGrammar from "./modes/apply-patch.lark" with { type: "text" };
|
|
29
|
-
import {
|
|
30
|
-
|
|
41
|
+
import {
|
|
42
|
+
executePatchSingle,
|
|
43
|
+
type PatchEditEntry,
|
|
44
|
+
type PatchParams,
|
|
45
|
+
patchEditEntrySchema,
|
|
46
|
+
patchEditSchema,
|
|
47
|
+
} from "./modes/patch";
|
|
48
|
+
import { executeReplaceEntries, type ReplaceEditEntry, type ReplaceParams, replaceEditSchema } from "./modes/replace";
|
|
31
49
|
import { type EditToolDetails, type EditToolPerFileResult, getLspBatchRequest, type LspBatchRequest } from "./renderer";
|
|
32
50
|
|
|
33
51
|
export { DEFAULT_EDIT_MODE, type EditMode, normalizeEditMode } from "../utils/edit-mode";
|
|
@@ -57,6 +75,12 @@ type VimParams = z.infer<typeof vimSchema>;
|
|
|
57
75
|
type EditParams = ReplaceParams | PatchParams | HashlineParams | VimParams | ApplyPatchParams;
|
|
58
76
|
type EditToolResultDetails = EditToolDetails | VimToolDetails;
|
|
59
77
|
|
|
78
|
+
/** Diff bodies introduce only `+` rows, not unified-diff file headers. */
|
|
79
|
+
function addedPatchDigest(diff: string): string | undefined {
|
|
80
|
+
const added = diff.split("\n").filter(line => line.startsWith("+") && !line.startsWith("+++ "));
|
|
81
|
+
return added.length > 0 ? added.map(line => line.slice(1)).join("\n") : undefined;
|
|
82
|
+
}
|
|
83
|
+
|
|
60
84
|
const UNSAFE_EDIT_SUMMARY_PATH =
|
|
61
85
|
/(?:\b(?:https?|wss?):\/\/|\b(?:api[-_ ]?key|access[-_ ]?token|bearer|secret|password)\b|\b(?:sk|pk|rk)-[A-Za-z0-9_-]{12,})/i;
|
|
62
86
|
|
|
@@ -167,6 +191,56 @@ function createEditWritethrough(session: ToolSession): WritethroughCallback {
|
|
|
167
191
|
return enableLsp ? createLspWritethrough(session.cwd, { enableFormat, enableDiagnostics }) : writethroughNoop;
|
|
168
192
|
}
|
|
169
193
|
|
|
194
|
+
type PatchGuardFailure = { path: string; errorText: string };
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Refuse a generated source or rename destination before any entry writes.
|
|
198
|
+
* A single entry still throws. Several entries return the per-entry errors
|
|
199
|
+
* the patch aggregators already use, and the caller writes nothing.
|
|
200
|
+
*/
|
|
201
|
+
async function collectPatchGuardFailures(
|
|
202
|
+
session: ToolSession,
|
|
203
|
+
entries: { path: string; rename?: string }[],
|
|
204
|
+
signal?: AbortSignal,
|
|
205
|
+
): Promise<PatchGuardFailure[] | undefined> {
|
|
206
|
+
const failures: PatchGuardFailure[] = [];
|
|
207
|
+
const aggregate = entries.length > 1;
|
|
208
|
+
for (const entry of entries) {
|
|
209
|
+
signal?.throwIfAborted();
|
|
210
|
+
try {
|
|
211
|
+
const resolvedPath = resolvePlanPath(session, entry.path);
|
|
212
|
+
await assertEditableFile(resolvedPath, entry.path, session.settings);
|
|
213
|
+
signal?.throwIfAborted();
|
|
214
|
+
if (!entry.rename) continue;
|
|
215
|
+
const resolvedRename = resolvePlanPath(session, entry.rename);
|
|
216
|
+
if (resolvedRename === resolvedPath) continue;
|
|
217
|
+
await assertEditableFile(resolvedRename, entry.rename, session.settings);
|
|
218
|
+
signal?.throwIfAborted();
|
|
219
|
+
} catch (err) {
|
|
220
|
+
signal?.throwIfAborted();
|
|
221
|
+
if (!aggregate || (err instanceof Error && err.name === "AbortError")) throw err;
|
|
222
|
+
failures.push({ path: entry.path, errorText: err instanceof Error ? err.message : String(err) });
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return failures.length > 0 ? failures : undefined;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function refusedPatchEntriesResult(
|
|
229
|
+
failures: PatchGuardFailure[],
|
|
230
|
+
details: { path?: string; perFileResults?: EditToolPerFileResult[] },
|
|
231
|
+
): AgentToolResult<EditToolDetails, TInput> {
|
|
232
|
+
return {
|
|
233
|
+
content: [
|
|
234
|
+
{
|
|
235
|
+
type: "text",
|
|
236
|
+
text: failures.map(failure => `Error editing ${failure.path}: ${failure.errorText}`).join("\n"),
|
|
237
|
+
},
|
|
238
|
+
],
|
|
239
|
+
details: { diff: "", ...details },
|
|
240
|
+
isError: true,
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
|
|
170
244
|
/** Run apply_patch file operations and aggregate their multi-file result. */
|
|
171
245
|
async function executeApplyPatchPerFile(
|
|
172
246
|
fileEntries: {
|
|
@@ -364,6 +438,96 @@ export class EditTool implements AgentTool<TInput> {
|
|
|
364
438
|
return this.#getModeDefinition().parameters;
|
|
365
439
|
}
|
|
366
440
|
|
|
441
|
+
matcherDigest(args: unknown): string | undefined {
|
|
442
|
+
const digest = this.matcherEntries(args)
|
|
443
|
+
?.map(entry => entry.digest)
|
|
444
|
+
.filter(Boolean)
|
|
445
|
+
.join("\n");
|
|
446
|
+
return digest || undefined;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
matcherEntries(args: unknown): readonly { path: string; digest: string }[] | undefined {
|
|
450
|
+
try {
|
|
451
|
+
if (!args || typeof args !== "object" || Array.isArray(args)) return undefined;
|
|
452
|
+
const record = args as Record<string, unknown>;
|
|
453
|
+
const digests = new Map<string, string>();
|
|
454
|
+
const add = (path: string, digest: string | undefined) => {
|
|
455
|
+
if (!path || digest === undefined) return;
|
|
456
|
+
const current = digests.get(path);
|
|
457
|
+
digests.set(path, current === undefined ? digest : `${current}\n${digest}`);
|
|
458
|
+
};
|
|
459
|
+
|
|
460
|
+
switch (this.mode) {
|
|
461
|
+
case "replace": {
|
|
462
|
+
if (typeof record.path !== "string" || !Array.isArray(record.edits)) return undefined;
|
|
463
|
+
for (const entry of record.edits) {
|
|
464
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) return undefined;
|
|
465
|
+
const text = (entry as Record<string, unknown>).new_text;
|
|
466
|
+
if (text !== undefined && typeof text !== "string") return undefined;
|
|
467
|
+
add(record.path, text);
|
|
468
|
+
}
|
|
469
|
+
break;
|
|
470
|
+
}
|
|
471
|
+
case "patch": {
|
|
472
|
+
if (typeof record.path !== "string" || !Array.isArray(record.edits)) return undefined;
|
|
473
|
+
for (const entry of record.edits) {
|
|
474
|
+
const parsed = patchEditEntrySchema.safeParse(entry);
|
|
475
|
+
if (!parsed.success) return undefined;
|
|
476
|
+
const { diff, op, rename } = parsed.data;
|
|
477
|
+
if (op === "delete" || diff === undefined) continue;
|
|
478
|
+
// A create body is digested exactly as the writer will persist it.
|
|
479
|
+
add(rename ?? record.path, op === "create" ? normalizeCreateContent(diff) : addedPatchDigest(diff));
|
|
480
|
+
}
|
|
481
|
+
break;
|
|
482
|
+
}
|
|
483
|
+
case "hashline": {
|
|
484
|
+
const parsed = hashlineEditParamsSchema.safeParse(args);
|
|
485
|
+
if (!parsed.success) return undefined;
|
|
486
|
+
for (const section of splitHashlineInputs(parsed.data.input, {
|
|
487
|
+
path: parsed.data.path,
|
|
488
|
+
cwd: this.session.cwd,
|
|
489
|
+
})) {
|
|
490
|
+
// A section still streaming (e.g. a trailing op with no anchor yet)
|
|
491
|
+
// does not parse; it contributes nothing, but earlier complete
|
|
492
|
+
// sections keep their entries (as pi-edit's hashline inspect does).
|
|
493
|
+
let edits: HashlineEdit[];
|
|
494
|
+
try {
|
|
495
|
+
edits = parseHashline(section.diff);
|
|
496
|
+
} catch {
|
|
497
|
+
continue;
|
|
498
|
+
}
|
|
499
|
+
const inserted = edits.filter(edit => edit.kind === "insert");
|
|
500
|
+
if (inserted.length > 0) add(section.path, inserted.map(edit => edit.text).join("\n"));
|
|
501
|
+
}
|
|
502
|
+
break;
|
|
503
|
+
}
|
|
504
|
+
case "apply_patch": {
|
|
505
|
+
const parsed = applyPatchSchema.safeParse(args);
|
|
506
|
+
if (!parsed.success) return undefined;
|
|
507
|
+
let entries: ApplyPatchEntry[];
|
|
508
|
+
try {
|
|
509
|
+
entries = expandApplyPatchToEntries(parsed.data);
|
|
510
|
+
} catch {
|
|
511
|
+
entries = expandApplyPatchToPreviewEntries(parsed.data);
|
|
512
|
+
}
|
|
513
|
+
for (const entry of entries) {
|
|
514
|
+
if (entry.op === "delete" || entry.diff === undefined) continue;
|
|
515
|
+
// The envelope parser already strips Add File prefixes.
|
|
516
|
+
add(entry.rename ?? entry.path, entry.op === "create" ? entry.diff : addedPatchDigest(entry.diff));
|
|
517
|
+
}
|
|
518
|
+
break;
|
|
519
|
+
}
|
|
520
|
+
case "vim":
|
|
521
|
+
return undefined;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
return digests.size > 0 ? Array.from(digests, ([path, digest]) => ({ path, digest })) : undefined;
|
|
525
|
+
} catch {
|
|
526
|
+
// Streamed arguments can be incomplete or malformed in any mode.
|
|
527
|
+
return undefined;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
367
531
|
/**
|
|
368
532
|
* When in `apply_patch` mode, expose the OpenAI code backend Lark grammar so providers
|
|
369
533
|
* that support OpenAI-style custom tools can emit a grammar-constrained
|
|
@@ -403,7 +567,7 @@ export class EditTool implements AgentTool<TInput> {
|
|
|
403
567
|
patch: {
|
|
404
568
|
description: () => prompt.render(patchDescription),
|
|
405
569
|
parameters: patchEditSchema,
|
|
406
|
-
execute: (
|
|
570
|
+
execute: async (
|
|
407
571
|
tool: EditTool,
|
|
408
572
|
params: EditParams,
|
|
409
573
|
signal: AbortSignal | undefined,
|
|
@@ -411,7 +575,14 @@ export class EditTool implements AgentTool<TInput> {
|
|
|
411
575
|
onUpdate?: (partialResult: AgentToolResult<EditToolDetails, TInput>) => void,
|
|
412
576
|
) => {
|
|
413
577
|
const { edits, path } = params as PatchParams;
|
|
414
|
-
const
|
|
578
|
+
const patchEdits = edits as PatchEditEntry[];
|
|
579
|
+
const guardFailures = await collectPatchGuardFailures(
|
|
580
|
+
tool.session,
|
|
581
|
+
patchEdits.map(entry => ({ path, rename: entry.rename })),
|
|
582
|
+
signal,
|
|
583
|
+
);
|
|
584
|
+
if (guardFailures) return refusedPatchEntriesResult(guardFailures, { path });
|
|
585
|
+
const runs = patchEdits.map(
|
|
415
586
|
entry => (br: LspBatchRequest | undefined) =>
|
|
416
587
|
executePatchSingle({
|
|
417
588
|
session: tool.session,
|
|
@@ -431,7 +602,7 @@ export class EditTool implements AgentTool<TInput> {
|
|
|
431
602
|
apply_patch: {
|
|
432
603
|
description: () => prompt.render(applyPatchDescription),
|
|
433
604
|
parameters: applyPatchSchema,
|
|
434
|
-
execute: (
|
|
605
|
+
execute: async (
|
|
435
606
|
tool: EditTool,
|
|
436
607
|
params: EditParams,
|
|
437
608
|
signal: AbortSignal | undefined,
|
|
@@ -439,6 +610,21 @@ export class EditTool implements AgentTool<TInput> {
|
|
|
439
610
|
onUpdate?: (partialResult: AgentToolResult<EditToolDetails, TInput>) => void,
|
|
440
611
|
) => {
|
|
441
612
|
const entries = expandApplyPatchToEntries(params as ApplyPatchParams);
|
|
613
|
+
const guardFailures = await collectPatchGuardFailures(
|
|
614
|
+
tool.session,
|
|
615
|
+
entries.map(entry => ({ path: entry.path, rename: entry.rename })),
|
|
616
|
+
signal,
|
|
617
|
+
);
|
|
618
|
+
if (guardFailures) {
|
|
619
|
+
return refusedPatchEntriesResult(guardFailures, {
|
|
620
|
+
perFileResults: guardFailures.map(failure => ({
|
|
621
|
+
path: failure.path,
|
|
622
|
+
diff: "",
|
|
623
|
+
isError: true,
|
|
624
|
+
errorText: failure.errorText,
|
|
625
|
+
})),
|
|
626
|
+
});
|
|
627
|
+
}
|
|
442
628
|
const perFile = entries.map(entry => {
|
|
443
629
|
const { path, ...patchParams } = entry;
|
|
444
630
|
return {
|
|
@@ -490,24 +676,20 @@ export class EditTool implements AgentTool<TInput> {
|
|
|
490
676
|
params: EditParams,
|
|
491
677
|
signal: AbortSignal | undefined,
|
|
492
678
|
batchRequest: LspBatchRequest | undefined,
|
|
493
|
-
|
|
679
|
+
_onUpdate?: (partialResult: AgentToolResult<EditToolDetails, TInput>) => void,
|
|
494
680
|
) => {
|
|
495
681
|
const { edits, path } = params as ReplaceParams;
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
beginDeferredDiagnosticsForPath: p => tool.#beginDeferredDiagnosticsForPath(p),
|
|
508
|
-
}),
|
|
509
|
-
);
|
|
510
|
-
return executeSinglePathEntries(path, runs, batchRequest, onUpdate);
|
|
682
|
+
return executeReplaceEntries({
|
|
683
|
+
session: tool.session,
|
|
684
|
+
path,
|
|
685
|
+
edits: edits as ReplaceEditEntry[],
|
|
686
|
+
signal,
|
|
687
|
+
batchRequest,
|
|
688
|
+
allowFuzzy: tool.#allowFuzzy,
|
|
689
|
+
fuzzyThreshold: tool.#fuzzyThreshold,
|
|
690
|
+
writethrough: tool.#writethrough,
|
|
691
|
+
beginDeferredDiagnosticsForPath: p => tool.#beginDeferredDiagnosticsForPath(p),
|
|
692
|
+
});
|
|
511
693
|
},
|
|
512
694
|
},
|
|
513
695
|
vim: {
|