@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
|
@@ -179,6 +179,109 @@ async function assertDirectoryNotSymlink(directoryPath: string): Promise<void> {
|
|
|
179
179
|
}
|
|
180
180
|
}
|
|
181
181
|
|
|
182
|
+
/** Group-write and world-write bits. Either one lets another user rename the session directory. */
|
|
183
|
+
const GROUP_OR_WORLD_WRITABLE = 0o022;
|
|
184
|
+
|
|
185
|
+
interface DirectoryIdentityStat {
|
|
186
|
+
isDirectory(): boolean;
|
|
187
|
+
isSymbolicLink(): boolean;
|
|
188
|
+
dev: number;
|
|
189
|
+
ino: number;
|
|
190
|
+
uid: number;
|
|
191
|
+
mode: number;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
interface ManagedRootIdentity {
|
|
195
|
+
readonly dev: number;
|
|
196
|
+
readonly ino: number;
|
|
197
|
+
readonly uid: number;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function isUnsafeDirectory(stat: DirectoryIdentityStat): boolean {
|
|
201
|
+
return !stat.isDirectory() || stat.isSymbolicLink();
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function managedRootIdentity(stat: DirectoryIdentityStat): ManagedRootIdentity {
|
|
205
|
+
return { dev: stat.dev, ino: stat.ino, uid: stat.uid };
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function sameManagedRoot(stat: DirectoryIdentityStat, recorded: ManagedRootIdentity): boolean {
|
|
209
|
+
if (isUnsafeDirectory(stat) || stat.dev !== recorded.dev || stat.ino !== recorded.ino) return false;
|
|
210
|
+
// A later chmod to 0755 keeps the same directory. Only a writable bit, a new
|
|
211
|
+
// inode, or a different owner means the root was replaced or opened up.
|
|
212
|
+
if (process.platform === "win32") return true;
|
|
213
|
+
return stat.uid === recorded.uid && (stat.mode & GROUP_OR_WORLD_WRITABLE) === 0;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* An existing managed session directory is adopted only when this user owns it
|
|
218
|
+
* and the group and world cannot write it. Windows has no POSIX owner bits.
|
|
219
|
+
*/
|
|
220
|
+
function assertAdoptedManagedRoot(stat: DirectoryIdentityStat): void {
|
|
221
|
+
if (isUnsafeDirectory(stat)) throw new Error("Unsafe local:// root");
|
|
222
|
+
if (process.platform === "win32") return;
|
|
223
|
+
const uid = process.getuid?.();
|
|
224
|
+
if (uid === undefined || stat.uid !== uid || (stat.mode & GROUP_OR_WORLD_WRITABLE) !== 0) {
|
|
225
|
+
throw new Error("Unsafe local:// root");
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function assertManagedParentSync(localRoot: string): void {
|
|
230
|
+
let parentStat: fsSync.Stats;
|
|
231
|
+
try {
|
|
232
|
+
parentStat = fsSync.lstatSync(path.dirname(localRoot));
|
|
233
|
+
} catch {
|
|
234
|
+
throw new Error("Unsafe local:// root");
|
|
235
|
+
}
|
|
236
|
+
assertAdoptedManagedRoot(parentStat);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Keep a pinned root unless a changed inode is validated as a settled
|
|
241
|
+
* recreation. A root created by this call may be rebound after migration.
|
|
242
|
+
*/
|
|
243
|
+
function acceptManagedRootForInit(
|
|
244
|
+
localRoot: string,
|
|
245
|
+
rootStat: DirectoryIdentityStat,
|
|
246
|
+
recorded: ManagedRootIdentity | undefined,
|
|
247
|
+
adoptedExisting: boolean,
|
|
248
|
+
): void {
|
|
249
|
+
if (recorded && adoptedExisting) {
|
|
250
|
+
if (sameManagedRoot(rootStat, recorded)) return;
|
|
251
|
+
const pending = pendingCreatedRoots.get(localRoot);
|
|
252
|
+
if (pending && sameManagedRoot(rootStat, pending)) return;
|
|
253
|
+
if (isSettledRecreatedManagedRoot(localRoot, rootStat)) return;
|
|
254
|
+
throw new Error("Unsafe local:// root");
|
|
255
|
+
}
|
|
256
|
+
if (recorded || adoptedExisting) {
|
|
257
|
+
assertAdoptedManagedRoot(rootStat);
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
if (isUnsafeDirectory(rootStat)) throw new Error("Unsafe local:// root");
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* A pinned root whose inode changed is still ours when a gjc initializer
|
|
265
|
+
* completed it: the temp sweeper (or `gjc gc`) removed the directory and
|
|
266
|
+
* another process for the same session recreated it, writing a settled
|
|
267
|
+
* migration marker. POSIX owner and write-bit checks on the root and parent
|
|
268
|
+
* protect this exception. Windows changed-inode adoption stays fail-closed
|
|
269
|
+
* until this path validates the replacement's identity and ACLs.
|
|
270
|
+
*/
|
|
271
|
+
function isSettledRecreatedManagedRoot(localRoot: string, rootStat: DirectoryIdentityStat): boolean {
|
|
272
|
+
if (process.platform === "win32") return false;
|
|
273
|
+
try {
|
|
274
|
+
assertAdoptedManagedRoot(rootStat);
|
|
275
|
+
assertManagedParentSync(localRoot);
|
|
276
|
+
const marker = path.join(localRoot, LEGACY_MIGRATION_MARKER);
|
|
277
|
+
const markerStat = fsSync.lstatSync(marker);
|
|
278
|
+
if (!markerStat.isFile() || markerStat.isSymbolicLink()) return false;
|
|
279
|
+
return isSettledMigrationMarkerValue(fsSync.readFileSync(marker, "utf8"));
|
|
280
|
+
} catch {
|
|
281
|
+
return false;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
182
285
|
const LEGACY_MIGRATION_MARKER = ".gjc-local-legacy-migrated-v1";
|
|
183
286
|
const MAX_LEGACY_LOCAL_BYTES = 64 * 1024 * 1024;
|
|
184
287
|
|
|
@@ -508,9 +611,33 @@ async function migrateLegacyLocal(
|
|
|
508
611
|
}
|
|
509
612
|
}
|
|
510
613
|
|
|
511
|
-
const initializedLocalRoots = new
|
|
614
|
+
const initializedLocalRoots = new Map<string, ManagedRootIdentity>();
|
|
615
|
+
/** A directory this process created and has not finished migrating. */
|
|
616
|
+
const pendingCreatedRoots = new Map<string, ManagedRootIdentity>();
|
|
512
617
|
const initializingLocalRoots = new Map<string, Promise<string>>();
|
|
513
618
|
|
|
619
|
+
function assertRememberedManagedRoot(localRoot: string, recorded: ManagedRootIdentity): void {
|
|
620
|
+
let stat: fsSync.Stats;
|
|
621
|
+
try {
|
|
622
|
+
stat = fsSync.lstatSync(localRoot);
|
|
623
|
+
} catch {
|
|
624
|
+
throw new Error("Unsafe local:// root");
|
|
625
|
+
}
|
|
626
|
+
if (!sameManagedRoot(stat, recorded)) throw new Error("Unsafe local:// root");
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
function rememberManagedRoot(localRoot: string, expected: ManagedRootIdentity): void {
|
|
630
|
+
let stat: fsSync.Stats;
|
|
631
|
+
try {
|
|
632
|
+
stat = fsSync.lstatSync(localRoot);
|
|
633
|
+
} catch {
|
|
634
|
+
throw new Error("Unsafe local:// root");
|
|
635
|
+
}
|
|
636
|
+
if (!sameManagedRoot(stat, expected)) throw new Error("Unsafe local:// root");
|
|
637
|
+
initializedLocalRoots.set(localRoot, managedRootIdentity(stat));
|
|
638
|
+
pendingCreatedRoots.delete(localRoot);
|
|
639
|
+
}
|
|
640
|
+
|
|
514
641
|
/**
|
|
515
642
|
* Completes the mandatory legacy migration gate for a local root.
|
|
516
643
|
* Call and await this before using the synchronous path resolver for reads or writes.
|
|
@@ -559,16 +686,21 @@ async function initializeManagedLocalRoot(options: LocalProtocolOptions, localRo
|
|
|
559
686
|
|
|
560
687
|
await fs.mkdir(scratchParent, { recursive: true, mode: 0o700 });
|
|
561
688
|
await assertDirectoryNotSymlink(scratchParent);
|
|
689
|
+
assertAdoptedManagedRoot(await fs.lstat(scratchParent));
|
|
690
|
+
let adoptedExisting = false;
|
|
562
691
|
try {
|
|
563
692
|
await fs.mkdir(localRoot, { mode: 0o700 });
|
|
564
693
|
} catch (error) {
|
|
565
694
|
if (error instanceof Error && "code" in error && error.code === "EEXIST") {
|
|
566
|
-
|
|
695
|
+
adoptedExisting = true;
|
|
567
696
|
} else {
|
|
568
697
|
throw error;
|
|
569
698
|
}
|
|
570
699
|
}
|
|
571
|
-
await
|
|
700
|
+
const rootStat = await fs.lstat(localRoot);
|
|
701
|
+
const recorded = initializedLocalRoots.get(localRoot);
|
|
702
|
+
acceptManagedRootForInit(localRoot, rootStat, recorded, adoptedExisting);
|
|
703
|
+
if (!adoptedExisting) pendingCreatedRoots.set(localRoot, managedRootIdentity(rootStat));
|
|
572
704
|
await migrateLegacyLocal(options, localRoot, scratchParent);
|
|
573
705
|
|
|
574
706
|
const resolvedScratchParent = await fs.realpath(scratchParent);
|
|
@@ -577,7 +709,10 @@ async function initializeManagedLocalRoot(options: LocalProtocolOptions, localRo
|
|
|
577
709
|
if (resolvedLocalRoot === resolvedScratchParent) {
|
|
578
710
|
throw new Error("Unsafe local:// root");
|
|
579
711
|
}
|
|
580
|
-
|
|
712
|
+
// Key the lexical path the sync resolver checks. realpath(/var -> /private/var)
|
|
713
|
+
// is a different string for the same directory, so caching only the real path
|
|
714
|
+
// let a later rename-swap skip this identity check.
|
|
715
|
+
rememberManagedRoot(localRoot, managedRootIdentity(rootStat));
|
|
581
716
|
return resolvedLocalRoot;
|
|
582
717
|
}
|
|
583
718
|
|
|
@@ -587,18 +722,41 @@ function initializeLocalRootSyncWhenLegacyAbsent(options: LocalProtocolOptions,
|
|
|
587
722
|
initializeExplicitLocalRootSync(explicitRoot);
|
|
588
723
|
return;
|
|
589
724
|
}
|
|
590
|
-
|
|
725
|
+
const recorded = initializedLocalRoots.get(localRoot);
|
|
726
|
+
if (recorded) {
|
|
727
|
+
assertManagedParentSync(localRoot);
|
|
728
|
+
let present: fsSync.Stats | undefined;
|
|
729
|
+
try {
|
|
730
|
+
present = fsSync.lstatSync(localRoot);
|
|
731
|
+
} catch (error) {
|
|
732
|
+
if (!isEnoent(error)) throw new Error("Unsafe local:// root");
|
|
733
|
+
}
|
|
734
|
+
if (present) {
|
|
735
|
+
if (sameManagedRoot(present, recorded)) {
|
|
736
|
+
assertRememberedManagedRoot(localRoot, recorded);
|
|
737
|
+
return;
|
|
738
|
+
}
|
|
739
|
+
const pending = pendingCreatedRoots.get(localRoot);
|
|
740
|
+
if (!(pending && sameManagedRoot(present, pending)) && !isSettledRecreatedManagedRoot(localRoot, present)) {
|
|
741
|
+
throw new Error("Unsafe local:// root");
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
}
|
|
591
745
|
const scratchParent = path.dirname(localRoot);
|
|
592
746
|
fsSync.mkdirSync(scratchParent, { recursive: true, mode: 0o700 });
|
|
593
747
|
const parentStat = fsSync.lstatSync(scratchParent);
|
|
594
748
|
if (!parentStat.isDirectory() || parentStat.isSymbolicLink()) throw new Error("Unsafe local:// root");
|
|
749
|
+
assertAdoptedManagedRoot(parentStat);
|
|
750
|
+
let adoptedExisting = false;
|
|
595
751
|
try {
|
|
596
752
|
fsSync.mkdirSync(localRoot, { mode: 0o700 });
|
|
597
753
|
} catch (error) {
|
|
598
754
|
if ((error as NodeJS.ErrnoException).code !== "EEXIST") throw error;
|
|
755
|
+
adoptedExisting = true;
|
|
599
756
|
}
|
|
600
757
|
const rootStat = fsSync.lstatSync(localRoot);
|
|
601
|
-
|
|
758
|
+
acceptManagedRootForInit(localRoot, rootStat, recorded, adoptedExisting);
|
|
759
|
+
if (!adoptedExisting) pendingCreatedRoots.set(localRoot, managedRootIdentity(rootStat));
|
|
602
760
|
const marker = path.join(localRoot, LEGACY_MIGRATION_MARKER);
|
|
603
761
|
try {
|
|
604
762
|
// Accept exactly the marker states the async gate treats as settled. A
|
|
@@ -608,7 +766,7 @@ function initializeLocalRootSyncWhenLegacyAbsent(options: LocalProtocolOptions,
|
|
|
608
766
|
// async gate had already completed.
|
|
609
767
|
if (!isSettledMigrationMarkerValue(fsSync.readFileSync(marker, "utf8")))
|
|
610
768
|
throw new Error("Unsafe local:// migration marker");
|
|
611
|
-
|
|
769
|
+
rememberManagedRoot(localRoot, managedRootIdentity(rootStat));
|
|
612
770
|
return;
|
|
613
771
|
} catch (error) {
|
|
614
772
|
if (!isEnoent(error)) throw error;
|
|
@@ -629,7 +787,7 @@ function initializeLocalRootSyncWhenLegacyAbsent(options: LocalProtocolOptions,
|
|
|
629
787
|
if (!isSettledMigrationMarkerValue(fsSync.readFileSync(marker, "utf8")))
|
|
630
788
|
throw new Error("Unsafe local:// migration marker");
|
|
631
789
|
}
|
|
632
|
-
|
|
790
|
+
rememberManagedRoot(localRoot, managedRootIdentity(rootStat));
|
|
633
791
|
}
|
|
634
792
|
|
|
635
793
|
export function resolveLocalRoot(options: LocalProtocolOptions): string {
|
|
@@ -696,6 +854,7 @@ export class LocalProtocolHandler implements ProtocolHandler {
|
|
|
696
854
|
LocalProtocolHandler.#override = undefined;
|
|
697
855
|
LocalProtocolHandler.#ownedOverrides = [];
|
|
698
856
|
initializedLocalRoots.clear();
|
|
857
|
+
pendingCreatedRoots.clear();
|
|
699
858
|
initializingLocalRoots.clear();
|
|
700
859
|
}
|
|
701
860
|
|
|
@@ -21,6 +21,8 @@ export interface InternalResource {
|
|
|
21
21
|
size?: number;
|
|
22
22
|
/** Underlying filesystem path (for debugging, not exposed to agent) */
|
|
23
23
|
sourcePath?: string;
|
|
24
|
+
/** True when model-facing reads must wrap the selected content as untrusted. */
|
|
25
|
+
untrusted?: boolean;
|
|
24
26
|
/** Additional notes about resolution */
|
|
25
27
|
notes?: string[];
|
|
26
28
|
/**
|
package/src/lsp/client.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isEnoent, isKnownSinkPeerClosedError, logger, untilAborted } from "@gajae-code/utils";
|
|
2
|
+
import { projectSafeSpawnEnv } from "@gajae-code/utils/shell-config";
|
|
2
3
|
import { formatCrashDiagnosticNotice, writeCrashReport } from "../debug/crash-diagnostics";
|
|
3
4
|
import { registerResourceOwner, spawnOwnedProcess } from "../runtime/process-lifecycle";
|
|
4
5
|
import { ToolAbortError, throwIfAborted } from "../tools/tool-errors";
|
|
@@ -538,7 +539,7 @@ export async function getOrCreateClient(config: ServerConfig, cwd: string, initT
|
|
|
538
539
|
const owner = spawnOwnedProcess([command, ...args], {
|
|
539
540
|
cwd,
|
|
540
541
|
stdin: "pipe",
|
|
541
|
-
env:
|
|
542
|
+
env: { ...projectSafeSpawnEnv(), ...env },
|
|
542
543
|
name: `lsp:${config.command}`,
|
|
543
544
|
});
|
|
544
545
|
const proc = owner.child;
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Uses Biome's CLI with JSON output instead of LSP (which has stale diagnostics issues).
|
|
4
4
|
*/
|
|
5
5
|
import path from "node:path";
|
|
6
|
+
import { projectSafeSpawnEnv } from "@gajae-code/utils/shell-config";
|
|
6
7
|
import type { Diagnostic, DiagnosticSeverity, LinterClient, ServerConfig } from "../../lsp/types";
|
|
7
8
|
|
|
8
9
|
// =============================================================================
|
|
@@ -84,6 +85,7 @@ async function runBiome(
|
|
|
84
85
|
try {
|
|
85
86
|
const proc = Bun.spawn([command, ...args], {
|
|
86
87
|
cwd,
|
|
88
|
+
env: projectSafeSpawnEnv(),
|
|
87
89
|
stdout: "pipe",
|
|
88
90
|
stderr: "pipe",
|
|
89
91
|
windowsHide: true,
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* SwiftLint CLI-based linter client.
|
|
3
3
|
* Parses SwiftLint's JSON reporter output into LSP Diagnostic format.
|
|
4
4
|
*/
|
|
5
|
+
import { projectSafeSpawnEnv } from "@gajae-code/utils/shell-config";
|
|
5
6
|
import type { Diagnostic, DiagnosticSeverity, LinterClient, ServerConfig } from "../../lsp/types";
|
|
6
7
|
|
|
7
8
|
/** Shape of a single violation from `swiftlint lint --reporter json`. */
|
|
@@ -36,6 +37,7 @@ async function runSwiftLint(
|
|
|
36
37
|
try {
|
|
37
38
|
const proc = Bun.spawn([command, ...args], {
|
|
38
39
|
cwd,
|
|
40
|
+
env: projectSafeSpawnEnv(),
|
|
39
41
|
stdout: "pipe",
|
|
40
42
|
stderr: "pipe",
|
|
41
43
|
windowsHide: true,
|
package/src/lsp/index.ts
CHANGED
|
@@ -77,6 +77,7 @@ import {
|
|
|
77
77
|
symbolKindToIcon,
|
|
78
78
|
uriToFile,
|
|
79
79
|
} from "./utils";
|
|
80
|
+
import { assertInsideWorkspace } from "./workspace-path";
|
|
80
81
|
|
|
81
82
|
export type { LspServerStatus } from "./client";
|
|
82
83
|
export type { LspToolDetails } from "./types";
|
|
@@ -347,6 +348,17 @@ interface FileRenamePair {
|
|
|
347
348
|
* For files this is a single pair. For directories this walks every regular file underneath
|
|
348
349
|
* and produces a parallel pair anchored at the new directory root.
|
|
349
350
|
*/
|
|
351
|
+
/**
|
|
352
|
+
* POSIX `/` contains every absolute path, and the shared helper's prefix for
|
|
353
|
+
* it is `//`, so skip containment there. A Windows drive root is only that
|
|
354
|
+
* volume, so it is checked. Any other platform root keeps the previous skip.
|
|
355
|
+
*/
|
|
356
|
+
function workspaceRootSkipsContainment(root: string): boolean {
|
|
357
|
+
if (root === "/") return true;
|
|
358
|
+
if (/^[A-Za-z]:[\\/]$/.test(root)) return false;
|
|
359
|
+
return root === path.parse(root).root;
|
|
360
|
+
}
|
|
361
|
+
|
|
350
362
|
async function enumerateRenamePairs(
|
|
351
363
|
source: string,
|
|
352
364
|
dest: string,
|
|
@@ -1525,6 +1537,23 @@ export class LspTool implements AgentTool<typeof lspSchema, LspToolDetails, Them
|
|
|
1525
1537
|
}
|
|
1526
1538
|
}
|
|
1527
1539
|
|
|
1540
|
+
// Reject every path this rename will write before the first write. Check the
|
|
1541
|
+
// caller signal after each await, including the last one.
|
|
1542
|
+
const cwd = this.session.cwd;
|
|
1543
|
+
throwIfAborted(signal);
|
|
1544
|
+
const workspaceRoot = await fs.promises.realpath(cwd);
|
|
1545
|
+
throwIfAborted(signal);
|
|
1546
|
+
if (!workspaceRootSkipsContainment(workspaceRoot)) {
|
|
1547
|
+
await assertInsideWorkspace(cwd, source);
|
|
1548
|
+
throwIfAborted(signal);
|
|
1549
|
+
await assertInsideWorkspace(cwd, dest);
|
|
1550
|
+
throwIfAborted(signal);
|
|
1551
|
+
for (const uri of acceptedByUri.keys()) {
|
|
1552
|
+
await assertInsideWorkspace(cwd, uriToFile(uri));
|
|
1553
|
+
throwIfAborted(signal);
|
|
1554
|
+
}
|
|
1555
|
+
}
|
|
1556
|
+
|
|
1528
1557
|
for (const [uri, bucket] of acceptedByUri) {
|
|
1529
1558
|
const filePath = uriToFile(uri);
|
|
1530
1559
|
await applyTextEdits(filePath, bucket.edits);
|
|
@@ -6,7 +6,30 @@ function isEnoent(error: unknown): boolean {
|
|
|
6
6
|
return (error as NodeJS.ErrnoException).code === "ENOENT";
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
+
/** Drive-letter root such as `C:\`. A UNC share root is not a drive root. */
|
|
10
|
+
function windowsDriveLetter(root: string): string | null {
|
|
11
|
+
const match = /^([A-Za-z]):[\\/]$/.exec(root);
|
|
12
|
+
return match ? match[1].toLowerCase() : null;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* A Windows drive root already ends in a separator. Prefixing another one
|
|
17
|
+
* (`C:\` + `\`) matches nothing on that volume, so compare the drive letter.
|
|
18
|
+
* Same-volume paths stay inside, including `\\?\C:\`. Other drives and UNC
|
|
19
|
+
* shares do not.
|
|
20
|
+
*/
|
|
21
|
+
function sameWindowsDrive(driveRoot: string, candidate: string): boolean {
|
|
22
|
+
const letter = windowsDriveLetter(driveRoot);
|
|
23
|
+
if (!letter) return false;
|
|
24
|
+
const normalized = candidate.replace(/\//g, "\\");
|
|
25
|
+
const extended = /^\\\\\?\\([A-Za-z]):\\/.exec(normalized);
|
|
26
|
+
if (extended) return extended[1].toLowerCase() === letter;
|
|
27
|
+
if (normalized.startsWith("\\\\")) return false;
|
|
28
|
+
return path.win32.parse(normalized).root.toLowerCase() === `${letter}:\\`;
|
|
29
|
+
}
|
|
30
|
+
|
|
9
31
|
function escapes(root: string, candidate: string): boolean {
|
|
32
|
+
if (windowsDriveLetter(root)) return !sameWindowsDrive(root, candidate);
|
|
10
33
|
return candidate !== root && !candidate.startsWith(`${root}${path.sep}`);
|
|
11
34
|
}
|
|
12
35
|
|