salmon-loop 0.2.3
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/LICENSE +21 -0
- package/README.md +144 -0
- package/README.zh-CN.md +144 -0
- package/dist/cli/argv/headless-detection.js +60 -0
- package/dist/cli/argv/print-mode.js +60 -0
- package/dist/cli/authorization/allowlist.js +908 -0
- package/dist/cli/authorization/non-interactive.js +166 -0
- package/dist/cli/authorization/provider.js +416 -0
- package/dist/cli/chat-interface.js +83 -0
- package/dist/cli/chat.js +492 -0
- package/dist/cli/cli-runtime-context.js +12 -0
- package/dist/cli/commander-error-adapter.js +35 -0
- package/dist/cli/commander-error-meta.js +13 -0
- package/dist/cli/commands/allowlist.js +270 -0
- package/dist/cli/commands/chat.js +120 -0
- package/dist/cli/commands/config.js +250 -0
- package/dist/cli/commands/context.js +57 -0
- package/dist/cli/commands/dispatcher.js +53 -0
- package/dist/cli/commands/exit.js +9 -0
- package/dist/cli/commands/llm-output.js +135 -0
- package/dist/cli/commands/log-mode.js +143 -0
- package/dist/cli/commands/mode.js +136 -0
- package/dist/cli/commands/new.js +18 -0
- package/dist/cli/commands/parallel.js +256 -0
- package/dist/cli/commands/queue.js +130 -0
- package/dist/cli/commands/registry.js +85 -0
- package/dist/cli/commands/restore.js +26 -0
- package/dist/cli/commands/run/assistant-message.js +14 -0
- package/dist/cli/commands/run/config-resolution.js +37 -0
- package/dist/cli/commands/run/early-errors.js +108 -0
- package/dist/cli/commands/run/execute.js +73 -0
- package/dist/cli/commands/run/extensions-resolution.js +22 -0
- package/dist/cli/commands/run/handler.js +434 -0
- package/dist/cli/commands/run/headless-error-writer.js +182 -0
- package/dist/cli/commands/run/instruction-guard.js +24 -0
- package/dist/cli/commands/run/loop-params.js +46 -0
- package/dist/cli/commands/run/mode.js +8 -0
- package/dist/cli/commands/run/parse-options.js +67 -0
- package/dist/cli/commands/run/persist-session.js +35 -0
- package/dist/cli/commands/run/preflight.js +156 -0
- package/dist/cli/commands/run/reporter-factory.js +52 -0
- package/dist/cli/commands/run/runtime-llm.js +56 -0
- package/dist/cli/commands/run/runtime-options.js +30 -0
- package/dist/cli/commands/run/session.js +19 -0
- package/dist/cli/commands/run/structured-output.js +106 -0
- package/dist/cli/commands/run/types.js +2 -0
- package/dist/cli/commands/run/validate-options.js +28 -0
- package/dist/cli/commands/run/verbose.js +36 -0
- package/dist/cli/commands/run.js +2 -0
- package/dist/cli/commands/serve.js +323 -0
- package/dist/cli/commands/session.js +77 -0
- package/dist/cli/commands/snapshot-interactive.js +165 -0
- package/dist/cli/commands/snapshot.js +159 -0
- package/dist/cli/commands/status.js +17 -0
- package/dist/cli/commands/subagent.js +178 -0
- package/dist/cli/commands/subcommand-suggestions.js +63 -0
- package/dist/cli/commands/tool-names.js +155 -0
- package/dist/cli/commands/types.js +2 -0
- package/dist/cli/commands/utils.js +42 -0
- package/dist/cli/config.js +16 -0
- package/dist/cli/crash-reporter.js +5 -0
- package/dist/cli/headless/anthropic-stream-normalized-encoder.js +164 -0
- package/dist/cli/headless/anthropic-stream-protocol.js +62 -0
- package/dist/cli/headless/json-protocol.js +124 -0
- package/dist/cli/headless/native-stream-normalized-encoder.js +206 -0
- package/dist/cli/headless/openai-responses-canonical-applier.js +94 -0
- package/dist/cli/headless/openai-responses-state.js +294 -0
- package/dist/cli/headless/openai-stream-encoder.js +152 -0
- package/dist/cli/headless/stdout-writer.js +9 -0
- package/dist/cli/headless/stream-json-protocol.js +136 -0
- package/dist/cli/index.js +8 -0
- package/dist/cli/locales/en.js +409 -0
- package/dist/cli/locales/index.js +7 -0
- package/dist/cli/program-bootstrap.js +14 -0
- package/dist/cli/program-commands.js +106 -0
- package/dist/cli/program-options.js +15 -0
- package/dist/cli/program-output-mode.js +11 -0
- package/dist/cli/program-parse.js +24 -0
- package/dist/cli/reporters/anthropic-stream.js +77 -0
- package/dist/cli/reporters/base.js +2 -0
- package/dist/cli/reporters/json.js +69 -0
- package/dist/cli/reporters/openai-stream.js +72 -0
- package/dist/cli/reporters/standard.js +226 -0
- package/dist/cli/reporters/stderr-log-reporter.js +71 -0
- package/dist/cli/reporters/stream-json.js +111 -0
- package/dist/cli/run-cli.js +25 -0
- package/dist/cli/slash/runtime.js +240 -0
- package/dist/cli/ui/App.js +273 -0
- package/dist/cli/ui/authorization/bus.js +35 -0
- package/dist/cli/ui/components/CommandInput.js +200 -0
- package/dist/cli/ui/components/CommandSuggestionList.js +20 -0
- package/dist/cli/ui/components/Markdown.js +423 -0
- package/dist/cli/ui/components/MessageList.js +34 -0
- package/dist/cli/ui/components/StatusBannerLine.js +7 -0
- package/dist/cli/ui/components/TodoDrawer.js +60 -0
- package/dist/cli/ui/components/WelcomeMessage.js +14 -0
- package/dist/cli/ui/components/animations/StretchingThinking.js +51 -0
- package/dist/cli/ui/components/animations/ThinkingWave.js +15 -0
- package/dist/cli/ui/components/animations/TypeIndicator.js +30 -0
- package/dist/cli/ui/components/layout/SplitPane.js +11 -0
- package/dist/cli/ui/components/messageList/MessageItem.js +27 -0
- package/dist/cli/ui/components/messageList/QueuePreviewList.js +11 -0
- package/dist/cli/ui/components/messageList/items/EmphasisMessageItem.js +20 -0
- package/dist/cli/ui/components/messageList/items/InterruptMessageItem.js +10 -0
- package/dist/cli/ui/components/messageList/items/LightweightMessageItem.js +12 -0
- package/dist/cli/ui/components/messageList/items/StandardMessageItem.js +23 -0
- package/dist/cli/ui/components/messageList/items/WelcomeMessageItem.js +7 -0
- package/dist/cli/ui/components/messageList/messageListLayout.js +27 -0
- package/dist/cli/ui/components/messageList/streaming.js +51 -0
- package/dist/cli/ui/components/messageList/types.js +2 -0
- package/dist/cli/ui/components/messageList/utils.js +7 -0
- package/dist/cli/ui/components/sidebar/FileContext.js +8 -0
- package/dist/cli/ui/components/sidebar/MissionControl.js +8 -0
- package/dist/cli/ui/config.js +59 -0
- package/dist/cli/ui/hooks/useCommandLifecycle.js +110 -0
- package/dist/cli/ui/hooks/useCommandSuggestions.js +87 -0
- package/dist/cli/ui/hooks/useInputHistory.js +57 -0
- package/dist/cli/ui/hooks/useLoopEvents.js +382 -0
- package/dist/cli/ui/hooks/useLoopState.js +73 -0
- package/dist/cli/ui/hooks/useOnionExit.js +31 -0
- package/dist/cli/ui/hooks/useTerminalDimensions.js +34 -0
- package/dist/cli/ui/index.js +136 -0
- package/dist/cli/ui/selection/bus.js +35 -0
- package/dist/cli/ui/status/formatStatusBanner.js +8 -0
- package/dist/cli/ui/store/context.js +17 -0
- package/dist/cli/ui/store/reducer.js +264 -0
- package/dist/cli/ui/store/types.js +81 -0
- package/dist/cli/ui/styles/theme.js +295 -0
- package/dist/cli/ui/types.js +2 -0
- package/dist/cli/ui/utils/sanitizer.js +122 -0
- package/dist/cli/ui/utils/transcript.js +28 -0
- package/dist/cli/utils/asyncQueue.js +125 -0
- package/dist/cli/utils/audit-scope.js +10 -0
- package/dist/cli/utils/detectors/index.js +38 -0
- package/dist/cli/utils/llm-output.js +34 -0
- package/dist/cli/utils/outcome-reporter.js +17 -0
- package/dist/cli/utils/safe-fs.js +184 -0
- package/dist/cli/utils/verify-resolver.js +34 -0
- package/dist/cli/utils/worktree-prepare-resolver.js +18 -0
- package/dist/core/adapters/fs/atomic-file-writer.js +129 -0
- package/dist/core/adapters/fs/file-adapter.js +95 -0
- package/dist/core/adapters/fs/filesystem.js +31 -0
- package/dist/core/adapters/fs/index.js +5 -0
- package/dist/core/adapters/fs/node-fs.js +7 -0
- package/dist/core/adapters/fs/readonly-filesystem.js +23 -0
- package/dist/core/adapters/git/git-adapter.js +704 -0
- package/dist/core/adapters/git/git-runner.js +119 -0
- package/dist/core/adapters/git/lock-manager.js +314 -0
- package/dist/core/adapters/git/types.js +2 -0
- package/dist/core/adapters/path/index.js +2 -0
- package/dist/core/adapters/path/path-adapter.js +23 -0
- package/dist/core/ast/guard.js +116 -0
- package/dist/core/ast/index.js +4 -0
- package/dist/core/ast/parser.js +284 -0
- package/dist/core/ast/validator.js +46 -0
- package/dist/core/backends/salmon-loop/task-executor.js +68 -0
- package/dist/core/checkpoint-domain/manifest-store.js +379 -0
- package/dist/core/checkpoint-domain/service.js +84 -0
- package/dist/core/checkpoint-domain/types.js +2 -0
- package/dist/core/config/defaults.js +50 -0
- package/dist/core/config/errors.js +11 -0
- package/dist/core/config/file-format.js +108 -0
- package/dist/core/config/index.js +7 -0
- package/dist/core/config/limits.js +77 -0
- package/dist/core/config/load.js +34 -0
- package/dist/core/config/normalize.js +35 -0
- package/dist/core/config/paths.js +20 -0
- package/dist/core/config/redact.js +16 -0
- package/dist/core/config/resolve-env.js +43 -0
- package/dist/core/config/resolve-llm.js +130 -0
- package/dist/core/config/resolve.js +68 -0
- package/dist/core/config/resolvers/ast-validation.js +8 -0
- package/dist/core/config/resolvers/context.js +21 -0
- package/dist/core/config/resolvers/observability.js +45 -0
- package/dist/core/config/resolvers/output.js +8 -0
- package/dist/core/config/resolvers/permission-mode.js +6 -0
- package/dist/core/config/resolvers/security.js +14 -0
- package/dist/core/config/resolvers/server.js +36 -0
- package/dist/core/config/resolvers/tool-authorization.js +39 -0
- package/dist/core/config/resolvers/ui.js +26 -0
- package/dist/core/config/types/config-file.js +2 -0
- package/dist/core/config/types/primitives.js +9 -0
- package/dist/core/config/types/resolved.js +2 -0
- package/dist/core/config/types.js +4 -0
- package/dist/core/config/validate.js +852 -0
- package/dist/core/context/assembly/default-prompt-assembler.js +7 -0
- package/dist/core/context/assembly/prompt-assembler.js +2 -0
- package/dist/core/context/ast/import-extractor.js +28 -0
- package/dist/core/context/ast/module-resolver.js +61 -0
- package/dist/core/context/ast/source-outline.js +25 -0
- package/dist/core/context/audit-constants.js +23 -0
- package/dist/core/context/audit.js +54 -0
- package/dist/core/context/budget/dynamic-adjuster.js +149 -0
- package/dist/core/context/budget/example-integration.js +49 -0
- package/dist/core/context/budget/integration.js +93 -0
- package/dist/core/context/builder.js +289 -0
- package/dist/core/context/cache/errors.js +16 -0
- package/dist/core/context/cache/incremental-updater.js +131 -0
- package/dist/core/context/cache/index.js +25 -0
- package/dist/core/context/cache/path-resolver.js +127 -0
- package/dist/core/context/cache/prompt-caching.js +207 -0
- package/dist/core/context/cache/store-factory.js +63 -0
- package/dist/core/context/cache/store.js +193 -0
- package/dist/core/context/cache/types.js +15 -0
- package/dist/core/context/compression/js-like-comments.js +139 -0
- package/dist/core/context/compression/smart-compress.js +61 -0
- package/dist/core/context/compression/whitespace.js +26 -0
- package/dist/core/context/dependencies.js +102 -0
- package/dist/core/context/effectiveness/index.js +25 -0
- package/dist/core/context/effectiveness/tracker.js +253 -0
- package/dist/core/context/effectiveness/types.js +15 -0
- package/dist/core/context/formatters/index.js +7 -0
- package/dist/core/context/formatters/json-converter.js +662 -0
- package/dist/core/context/formatters/types.js +6 -0
- package/dist/core/context/formatters/xml-context.js +296 -0
- package/dist/core/context/gatherers/architecture-gatherer.js +75 -0
- package/dist/core/context/gatherers/artifact-gatherer.js +53 -0
- package/dist/core/context/gatherers/ast-gatherer.js +370 -0
- package/dist/core/context/gatherers/ghost-dependency-gatherer.js +46 -0
- package/dist/core/context/gatherers/git-diff-gatherer.js +91 -0
- package/dist/core/context/gatherers/git-history-gatherer.js +57 -0
- package/dist/core/context/gatherers/knowledge-gatherer.js +101 -0
- package/dist/core/context/gatherers/metadata-gatherer.js +59 -0
- package/dist/core/context/gatherers/primary-text-gatherer.js +36 -0
- package/dist/core/context/gatherers/ripgrep-gatherer.js +104 -0
- package/dist/core/context/hash.js +52 -0
- package/dist/core/context/index.js +3 -0
- package/dist/core/context/keywords.js +179 -0
- package/dist/core/context/policies/budget-policy.js +36 -0
- package/dist/core/context/policies/pack-until-full.js +419 -0
- package/dist/core/context/scoring/relevance.js +191 -0
- package/dist/core/context/service-deps.js +32 -0
- package/dist/core/context/service-helpers.js +32 -0
- package/dist/core/context/service.js +265 -0
- package/dist/core/context/steps/context-budget.js +157 -0
- package/dist/core/context/steps/context-gather.js +71 -0
- package/dist/core/context/steps/context-primary.js +19 -0
- package/dist/core/context/steps/context-promotion.js +78 -0
- package/dist/core/context/steps/context-targets.js +85 -0
- package/dist/core/context/steps/types.js +2 -0
- package/dist/core/context/summarization/index.js +27 -0
- package/dist/core/context/summarization/prompts.js +80 -0
- package/dist/core/context/summarization/summarizer.js +377 -0
- package/dist/core/context/summarization/types.js +29 -0
- package/dist/core/context/targeting/churn-policy.js +27 -0
- package/dist/core/context/targeting/target-resolver.js +491 -0
- package/dist/core/context/token/adaptive-budget.js +364 -0
- package/dist/core/context/token/cache.js +163 -0
- package/dist/core/context/token/counter.js +190 -0
- package/dist/core/context/token/encoding-registry.js +173 -0
- package/dist/core/context/token/index.js +31 -0
- package/dist/core/context/token/token-budget.js +213 -0
- package/dist/core/context/token/types.js +10 -0
- package/dist/core/context/truncation/index.js +23 -0
- package/dist/core/context/truncation/semantic-truncator.js +103 -0
- package/dist/core/context/truncation/strategies/error-stack.js +94 -0
- package/dist/core/context/truncation/strategies/generic.js +48 -0
- package/dist/core/context/truncation/strategies/git-diff.js +99 -0
- package/dist/core/context/truncation/strategies/index.js +10 -0
- package/dist/core/context/truncation/strategies/json.js +142 -0
- package/dist/core/context/truncation/strategies/log.js +131 -0
- package/dist/core/context/truncation/strategies/test-result.js +140 -0
- package/dist/core/context/truncation/type-detector.js +133 -0
- package/dist/core/context/truncation/types.js +16 -0
- package/dist/core/context/types.js +2 -0
- package/dist/core/extensions/index.js +118 -0
- package/dist/core/extensions/load.js +36 -0
- package/dist/core/extensions/merge.js +29 -0
- package/dist/core/extensions/paths.js +40 -0
- package/dist/core/extensions/redact.js +37 -0
- package/dist/core/extensions/schemas.js +70 -0
- package/dist/core/extensions/types.js +2 -0
- package/dist/core/facades/cli-authorization-allowlist.js +3 -0
- package/dist/core/facades/cli-authorization-non-interactive.js +3 -0
- package/dist/core/facades/cli-authorization-provider.js +2 -0
- package/dist/core/facades/cli-chat.js +11 -0
- package/dist/core/facades/cli-command-allowlist.js +3 -0
- package/dist/core/facades/cli-command-chat.js +8 -0
- package/dist/core/facades/cli-command-checkpoint.js +3 -0
- package/dist/core/facades/cli-command-config.js +10 -0
- package/dist/core/facades/cli-command-dispatcher.js +2 -0
- package/dist/core/facades/cli-command-parallel.js +8 -0
- package/dist/core/facades/cli-command-session.js +2 -0
- package/dist/core/facades/cli-command-tool-names.js +6 -0
- package/dist/core/facades/cli-context.js +8 -0
- package/dist/core/facades/cli-headless.js +3 -0
- package/dist/core/facades/cli-observability.js +3 -0
- package/dist/core/facades/cli-program-bootstrap.js +2 -0
- package/dist/core/facades/cli-reporters.js +5 -0
- package/dist/core/facades/cli-run-execute.js +3 -0
- package/dist/core/facades/cli-run-handler.js +7 -0
- package/dist/core/facades/cli-run-headless-error-writer.js +2 -0
- package/dist/core/facades/cli-run-loop-params.js +2 -0
- package/dist/core/facades/cli-run-persist-session.js +2 -0
- package/dist/core/facades/cli-run-runtime-llm.js +5 -0
- package/dist/core/facades/cli-serve.js +21 -0
- package/dist/core/facades/cli-slash-runtime.js +9 -0
- package/dist/core/facades/cli-subagent.js +2 -0
- package/dist/core/facades/cli-ui.js +5 -0
- package/dist/core/facades/cli-utils-llm-output.js +3 -0
- package/dist/core/facades/cli-utils-path.js +2 -0
- package/dist/core/facades/cli-utils-worktree.js +2 -0
- package/dist/core/failure/diagnostics.js +221 -0
- package/dist/core/feedback/index.js +28 -0
- package/dist/core/feedback/parsers.js +59 -0
- package/dist/core/feedback/patterns.js +26 -0
- package/dist/core/feedback/types.js +2 -0
- package/dist/core/grizzco/domain/grizzco-types.js +41 -0
- package/dist/core/grizzco/dsl/DecisionEngine.js +149 -0
- package/dist/core/grizzco/dsl/MicroTaskRunner.js +39 -0
- package/dist/core/grizzco/dsl/llm-strategy.js +80 -0
- package/dist/core/grizzco/dsl/strategies.js +69 -0
- package/dist/core/grizzco/dsl/types.js +2 -0
- package/dist/core/grizzco/engine/observability/event-adapter.js +41 -0
- package/dist/core/grizzco/engine/observability/index.js +3 -0
- package/dist/core/grizzco/engine/observability/loop-telemetry.js +51 -0
- package/dist/core/grizzco/engine/outcome/index.js +2 -0
- package/dist/core/grizzco/engine/outcome/loop-result-mapper.js +167 -0
- package/dist/core/grizzco/engine/pipeline/pipeline.js +335 -0
- package/dist/core/grizzco/engine/pipeline/types.js +2 -0
- package/dist/core/grizzco/engine/transaction/attempt-failure.js +242 -0
- package/dist/core/grizzco/engine/transaction/authorization-summary.js +44 -0
- package/dist/core/grizzco/engine/transaction/index.js +3 -0
- package/dist/core/grizzco/engine/transaction/report-mapper.js +50 -0
- package/dist/core/grizzco/engine/transaction/retry-policy.js +19 -0
- package/dist/core/grizzco/engine/transaction/runner-builder.js +45 -0
- package/dist/core/grizzco/engine/transaction/session.js +58 -0
- package/dist/core/grizzco/engine/transaction/transaction-runner.js +193 -0
- package/dist/core/grizzco/engine/transaction/types.js +2 -0
- package/dist/core/grizzco/execution/Executor.js +58 -0
- package/dist/core/grizzco/execution/RejectionManager.js +71 -0
- package/dist/core/grizzco/execution/WorkerFactory.js +31 -0
- package/dist/core/grizzco/flows/SalmonLoopFlow.js +102 -0
- package/dist/core/grizzco/runtime/apply-back-runtime.js +136 -0
- package/dist/core/grizzco/runtime/apply-back-utils.js +13 -0
- package/dist/core/grizzco/runtime/host/host-runner.js +99 -0
- package/dist/core/grizzco/runtime/host/index.js +2 -0
- package/dist/core/grizzco/runtime/host/types.js +2 -0
- package/dist/core/grizzco/services/CachedService.js +42 -0
- package/dist/core/grizzco/services/implementations/default/GitConfigService.js +38 -0
- package/dist/core/grizzco/services/implementations/mock/MockLockService.js +11 -0
- package/dist/core/grizzco/services/implementations/mock/MockUserQuotaService.js +11 -0
- package/dist/core/grizzco/services/registry.js +30 -0
- package/dist/core/grizzco/services/types.js +2 -0
- package/dist/core/grizzco/steps/answer.js +75 -0
- package/dist/core/grizzco/steps/apply-back.js +46 -0
- package/dist/core/grizzco/steps/apply.js +136 -0
- package/dist/core/grizzco/steps/ast-validate.js +37 -0
- package/dist/core/grizzco/steps/audit.js +311 -0
- package/dist/core/grizzco/steps/context.js +74 -0
- package/dist/core/grizzco/steps/display-answer.js +6 -0
- package/dist/core/grizzco/steps/display-report.js +158 -0
- package/dist/core/grizzco/steps/display-research.js +6 -0
- package/dist/core/grizzco/steps/displayReview.js +6 -0
- package/dist/core/grizzco/steps/explore.js +245 -0
- package/dist/core/grizzco/steps/extractIssues.js +27 -0
- package/dist/core/grizzco/steps/generateFixPlan.js +13 -0
- package/dist/core/grizzco/steps/generateReview.js +71 -0
- package/dist/core/grizzco/steps/patch.js +220 -0
- package/dist/core/grizzco/steps/plan.js +191 -0
- package/dist/core/grizzco/steps/preflight.js +93 -0
- package/dist/core/grizzco/steps/prepare-deps.js +49 -0
- package/dist/core/grizzco/steps/read-only-shrink.js +4 -0
- package/dist/core/grizzco/steps/research.js +188 -0
- package/dist/core/grizzco/steps/rollback.js +138 -0
- package/dist/core/grizzco/steps/shrink.js +64 -0
- package/dist/core/grizzco/steps/validate.js +40 -0
- package/dist/core/grizzco/steps/verify.js +136 -0
- package/dist/core/grizzco/validation/AstValidationService.js +133 -0
- package/dist/core/grizzco/validation/ContextValidator.js +17 -0
- package/dist/core/grizzco/validation/ast-validation-policy.js +11 -0
- package/dist/core/grizzco/workers/direct-write-worker.js +44 -0
- package/dist/core/grizzco/workers/git-apply-worker.js +75 -0
- package/dist/core/grizzco/workers/i-merge-worker.js +2 -0
- package/dist/core/grizzco/workers/mm-three-way-worker.js +117 -0
- package/dist/core/grizzco/workers/no-op-worker.js +18 -0
- package/dist/core/grizzco/workers/overwrite-binary-worker.js +29 -0
- package/dist/core/grizzco/workers/strata-sync-worker.js +69 -0
- package/dist/core/grizzco/workers/three-way-merge-worker.js +84 -0
- package/dist/core/grizzco/workers/three-way-staged-worker.js +93 -0
- package/dist/core/grizzco/workers/union-merge-worker.js +71 -0
- package/dist/core/history/input-history.js +55 -0
- package/dist/core/intent/chat-intent.js +250 -0
- package/dist/core/interaction/events/bus.js +52 -0
- package/dist/core/interaction/model/events.js +2 -0
- package/dist/core/interaction/model/index.js +3 -0
- package/dist/core/interaction/model/task-state.js +9 -0
- package/dist/core/interaction/model/transition-policy.js +50 -0
- package/dist/core/interaction/model/types.js +2 -0
- package/dist/core/interaction/orchestration/facade.js +190 -0
- package/dist/core/interaction/orchestration/index.js +2 -0
- package/dist/core/interaction/orchestration/store.js +32 -0
- package/dist/core/interaction/sync/task-sync-engine.js +57 -0
- package/dist/core/interaction/turn-stop-reason.js +27 -0
- package/dist/core/language-support/index.js +3 -0
- package/dist/core/language-support/orchestrator.js +37 -0
- package/dist/core/language-support/strategies/extension-candidate-strategy.js +27 -0
- package/dist/core/language-support/strategies/index.js +3 -0
- package/dist/core/language-support/strategies/language-query-strategy.js +26 -0
- package/dist/core/llm/ai-sdk/chat-executor.js +88 -0
- package/dist/core/llm/ai-sdk/langfuse-headers.js +28 -0
- package/dist/core/llm/ai-sdk/message-mapper.js +240 -0
- package/dist/core/llm/ai-sdk/observation-context.js +16 -0
- package/dist/core/llm/ai-sdk/provider-factory.js +29 -0
- package/dist/core/llm/ai-sdk/request-params.js +18 -0
- package/dist/core/llm/ai-sdk/request-runtime.js +168 -0
- package/dist/core/llm/ai-sdk/result-mapper.js +31 -0
- package/dist/core/llm/ai-sdk/retry-classifier.js +82 -0
- package/dist/core/llm/ai-sdk/retry-executor.js +38 -0
- package/dist/core/llm/ai-sdk.js +92 -0
- package/dist/core/llm/audit.js +2 -0
- package/dist/core/llm/base-url.js +18 -0
- package/dist/core/llm/contracts/repair.js +68 -0
- package/dist/core/llm/errors.js +172 -0
- package/dist/core/llm/factory.js +21 -0
- package/dist/core/llm/http/index.js +2 -0
- package/dist/core/llm/index.js +6 -0
- package/dist/core/llm/message-composition.js +25 -0
- package/dist/core/llm/openai.js +69 -0
- package/dist/core/llm/output-policy.js +192 -0
- package/dist/core/llm/phase-router.js +55 -0
- package/dist/core/llm/redact.js +37 -0
- package/dist/core/llm/registry.js +81 -0
- package/dist/core/llm/retry-utils.js +114 -0
- package/dist/core/llm/stream-utils.js +87 -0
- package/dist/core/llm/utils.js +82 -0
- package/dist/core/observability/audit-file.js +199 -0
- package/dist/core/observability/audit-trail.js +125 -0
- package/dist/core/observability/authorization-decisions.js +54 -0
- package/dist/core/observability/debug-artifacts.js +61 -0
- package/dist/core/observability/error-envelope.js +63 -0
- package/dist/core/observability/error-mapping.js +271 -0
- package/dist/core/observability/ignored-error.js +6 -0
- package/dist/core/observability/logger.js +457 -0
- package/dist/core/observability/loop-event-reporter.js +46 -0
- package/dist/core/observability/monitor.js +240 -0
- package/dist/core/observability/run-outcome-reporter.js +15 -0
- package/dist/core/observability/token-usage.js +36 -0
- package/dist/core/observability/ui-log-sanitize.js +35 -0
- package/dist/core/patch/aggregator.js +93 -0
- package/dist/core/patch/diff.js +298 -0
- package/dist/core/permission-gate/default-gate.js +115 -0
- package/dist/core/permission-gate/gate.js +2 -0
- package/dist/core/permission-gate/types.js +2 -0
- package/dist/core/plan/index.js +2 -0
- package/dist/core/plan/manager.js +123 -0
- package/dist/core/plan/markdown-editor.js +238 -0
- package/dist/core/plan/storage.js +75 -0
- package/dist/core/plan/types.js +2 -0
- package/dist/core/plugin/interface.js +2 -0
- package/dist/core/plugin/loader.js +130 -0
- package/dist/core/plugin/registry.js +90 -0
- package/dist/core/plugin/validator.js +98 -0
- package/dist/core/prompts/registry.js +189 -0
- package/dist/core/prompts/runtime.js +69 -0
- package/dist/core/prompts/schema.js +2 -0
- package/dist/core/prompts/templates/phases/explore_user.hbs +26 -0
- package/dist/core/prompts/templates/phases/patch_user.hbs +57 -0
- package/dist/core/prompts/templates/phases/plan_user.hbs +33 -0
- package/dist/core/prompts/templates/system/_context_json_legend.hbs +21 -0
- package/dist/core/prompts/templates/system/_tool_defs.hbs +60 -0
- package/dist/core/prompts/templates/system/explore_system.hbs +26 -0
- package/dist/core/prompts/templates/system/main_system.hbs +18 -0
- package/dist/core/prompts/templates/system/patch_system.hbs +10 -0
- package/dist/core/prompts/templates/system/plan_system.hbs +1 -0
- package/dist/core/prompts/templates/system/reflection.hbs +39 -0
- package/dist/core/protocols/a2a/agent-card.js +30 -0
- package/dist/core/protocols/a2a/mapper.js +14 -0
- package/dist/core/protocols/a2a/sdk/auth-middleware.js +31 -0
- package/dist/core/protocols/a2a/sdk/executor.js +301 -0
- package/dist/core/protocols/a2a/sdk/server.js +24 -0
- package/dist/core/protocols/a2a/task-projection.js +45 -0
- package/dist/core/protocols/acp/acp-command-runner.js +204 -0
- package/dist/core/protocols/acp/acp-filesystem.js +43 -0
- package/dist/core/protocols/acp/checkpoint-meta.js +2 -0
- package/dist/core/protocols/acp/formal-agent.js +1201 -0
- package/dist/core/protocols/acp/handlers.js +51 -0
- package/dist/core/protocols/acp/permission-provider.js +122 -0
- package/dist/core/protocols/acp/stdio-server.js +116 -0
- package/dist/core/reflection/engine.js +55 -0
- package/dist/core/reflection/types.js +2 -0
- package/dist/core/runtime/agent-server-runtime.js +88 -0
- package/dist/core/runtime/bun-runtime.js +26 -0
- package/dist/core/runtime/command-runner-context.js +16 -0
- package/dist/core/runtime/exit-codes.js +11 -0
- package/dist/core/runtime/fastify-fetch-bridge.js +51 -0
- package/dist/core/runtime/fastify-server-bundle.js +26 -0
- package/dist/core/runtime/initialize.js +132 -0
- package/dist/core/runtime/loop-finalize.js +71 -0
- package/dist/core/runtime/loop-run-lifecycle.js +73 -0
- package/dist/core/runtime/loop-run-reporter.js +19 -0
- package/dist/core/runtime/loop-runtime-config.js +26 -0
- package/dist/core/runtime/loop-session-runner.js +30 -0
- package/dist/core/runtime/loop.js +84 -0
- package/dist/core/runtime/paths.js +84 -0
- package/dist/core/runtime/process-runner.js +16 -0
- package/dist/core/runtime/process-types.js +2 -0
- package/dist/core/runtime/semaphore.js +41 -0
- package/dist/core/runtime/sidecar-fastify-plugin.js +35 -0
- package/dist/core/runtime/sidecar-paths.js +47 -0
- package/dist/core/runtime/sidecar-route-catalog.js +103 -0
- package/dist/core/runtime/spawn-command.js +392 -0
- package/dist/core/runtime/spawn-interactive.js +71 -0
- package/dist/core/security/redaction.js +160 -0
- package/dist/core/session/compression.js +323 -0
- package/dist/core/session/flow.js +85 -0
- package/dist/core/session/manager.js +313 -0
- package/dist/core/session/pruning-strategy.js +153 -0
- package/dist/core/session/session-context-builder.js +122 -0
- package/dist/core/session/summary-sync.js +82 -0
- package/dist/core/session/token-tracker.js +82 -0
- package/dist/core/session/types.js +2 -0
- package/dist/core/skills/bridge.js +33 -0
- package/dist/core/skills/index.js +8 -0
- package/dist/core/skills/loader.js +80 -0
- package/dist/core/skills/parser.js +66 -0
- package/dist/core/skills/runtime/MicroTaskRunner.js +102 -0
- package/dist/core/skills/runtime/SkillRunner.js +108 -0
- package/dist/core/skills/strategy.js +29 -0
- package/dist/core/skills/types.js +2 -0
- package/dist/core/slash/index.js +6 -0
- package/dist/core/slash/parser.js +33 -0
- package/dist/core/slash/registry.js +78 -0
- package/dist/core/slash/router.js +76 -0
- package/dist/core/slash/steps/slash-decide.js +19 -0
- package/dist/core/slash/steps/slash-execute.js +73 -0
- package/dist/core/slash/steps/types.js +2 -0
- package/dist/core/slash/strategy.js +33 -0
- package/dist/core/slash/types.js +2 -0
- package/dist/core/strata/checkpoint/manager.js +492 -0
- package/dist/core/strata/checkpoint/snapshot-audit.js +88 -0
- package/dist/core/strata/checkpoint/snapshot-create.js +79 -0
- package/dist/core/strata/checkpoint/snapshot-write-tree.js +72 -0
- package/dist/core/strata/engine/shadow-merge-engine.js +394 -0
- package/dist/core/strata/index.js +15 -0
- package/dist/core/strata/interaction/content-guardian.js +59 -0
- package/dist/core/strata/interaction/file-system-provider.js +89 -0
- package/dist/core/strata/layers/file-state-resolver.js +157 -0
- package/dist/core/strata/layers/immutable-git-layer.js +42 -0
- package/dist/core/strata/layers/shadow-driver/copy-backend.js +114 -0
- package/dist/core/strata/layers/shadow-driver/env.js +29 -0
- package/dist/core/strata/layers/shadow-driver/error-classifier.js +41 -0
- package/dist/core/strata/layers/shadow-driver/index.js +17 -0
- package/dist/core/strata/layers/shadow-driver/readonly-lock.js +221 -0
- package/dist/core/strata/layers/shadow-driver/shadow-driver.js +234 -0
- package/dist/core/strata/layers/shadow-driver/strategy.js +86 -0
- package/dist/core/strata/layers/sidecar-layer.js +96 -0
- package/dist/core/strata/layers/worktree.js +240 -0
- package/dist/core/strata/runtime/environment.js +377 -0
- package/dist/core/strata/runtime/synchronizer.js +819 -0
- package/dist/core/strata/types.js +46 -0
- package/dist/core/streaming/canonical/canonical-responses-event-emitter.js +326 -0
- package/dist/core/streaming/canonical/function-call-item-id.js +13 -0
- package/dist/core/streaming/canonical/parts-from-llm-stream-chunk.js +54 -0
- package/dist/core/streaming/canonical/responses-event-emitter.js +127 -0
- package/dist/core/streaming/canonical/responses-events.js +2 -0
- package/dist/core/streaming/normalized-events.js +9 -0
- package/dist/core/streaming/normalized-from-text.js +47 -0
- package/dist/core/streaming/stream-assembler.js +347 -0
- package/dist/core/structured-output/index.js +3 -0
- package/dist/core/structured-output/json-extract.js +70 -0
- package/dist/core/structured-output/json-schema-validator.js +90 -0
- package/dist/core/structured-output/types.js +2 -0
- package/dist/core/sub-agent/artifacts/store.js +141 -0
- package/dist/core/sub-agent/artifacts/types.js +2 -0
- package/dist/core/sub-agent/controller.js +69 -0
- package/dist/core/sub-agent/core/loop.js +79 -0
- package/dist/core/sub-agent/core/manager.js +246 -0
- package/dist/core/sub-agent/registry-defaults.js +52 -0
- package/dist/core/sub-agent/registry.js +35 -0
- package/dist/core/sub-agent/tools/task-spawn.js +29 -0
- package/dist/core/sub-agent/types.js +23 -0
- package/dist/core/target-runtime/command-resolver.js +42 -0
- package/dist/core/target-runtime/index.js +3 -0
- package/dist/core/target-runtime/profile.js +73 -0
- package/dist/core/testgen/detector.js +17 -0
- package/dist/core/testgen/index.js +38 -0
- package/dist/core/testgen/templates.js +46 -0
- package/dist/core/tools/audit.js +140 -0
- package/dist/core/tools/authorization/types.js +2 -0
- package/dist/core/tools/budget.js +118 -0
- package/dist/core/tools/builtin/artifact.js +29 -0
- package/dist/core/tools/builtin/ast-grep.js +107 -0
- package/dist/core/tools/builtin/ast.js +62 -0
- package/dist/core/tools/builtin/code-search/backends/powershell.js +84 -0
- package/dist/core/tools/builtin/code-search/backends/rg.js +85 -0
- package/dist/core/tools/builtin/code-search/executor.js +87 -0
- package/dist/core/tools/builtin/code-search/parse/plain-grep.js +59 -0
- package/dist/core/tools/builtin/code-search/parse/rg-json.js +31 -0
- package/dist/core/tools/builtin/code-search/spec.js +82 -0
- package/dist/core/tools/builtin/fs.js +243 -0
- package/dist/core/tools/builtin/git.js +118 -0
- package/dist/core/tools/builtin/index.js +80 -0
- package/dist/core/tools/builtin/interaction.js +120 -0
- package/dist/core/tools/builtin/knowledge.js +98 -0
- package/dist/core/tools/builtin/plan.js +148 -0
- package/dist/core/tools/builtin/proposal.js +207 -0
- package/dist/core/tools/builtin/shell.js +71 -0
- package/dist/core/tools/builtin/verify.js +41 -0
- package/dist/core/tools/capability/executor.js +84 -0
- package/dist/core/tools/capability/runner.js +50 -0
- package/dist/core/tools/capability/types.js +2 -0
- package/dist/core/tools/dispatcher.js +80 -0
- package/dist/core/tools/headless-payload.js +37 -0
- package/dist/core/tools/loader.js +100 -0
- package/dist/core/tools/mapper.js +142 -0
- package/dist/core/tools/mcp/client.js +308 -0
- package/dist/core/tools/mcp/loader.js +110 -0
- package/dist/core/tools/mcp/schema.js +54 -0
- package/dist/core/tools/mcp/streamable-http.js +101 -0
- package/dist/core/tools/mcp/types.js +26 -0
- package/dist/core/tools/parallel/isolation.js +25 -0
- package/dist/core/tools/parallel/lock-manager.js +124 -0
- package/dist/core/tools/parallel/persistence.js +126 -0
- package/dist/core/tools/parallel/plan-builder.js +66 -0
- package/dist/core/tools/parallel/plan.js +2 -0
- package/dist/core/tools/parallel/refs.js +7 -0
- package/dist/core/tools/parallel/resolve-args.js +50 -0
- package/dist/core/tools/parallel/resource-helpers.js +35 -0
- package/dist/core/tools/parallel/resources.js +2 -0
- package/dist/core/tools/parallel/scheduler.js +372 -0
- package/dist/core/tools/parser.js +89 -0
- package/dist/core/tools/permissions/permission-rules.js +503 -0
- package/dist/core/tools/plugins/loader.js +102 -0
- package/dist/core/tools/policy.js +87 -0
- package/dist/core/tools/registry.js +29 -0
- package/dist/core/tools/router.js +514 -0
- package/dist/core/tools/sanitize.js +78 -0
- package/dist/core/tools/schema-utils.js +71 -0
- package/dist/core/tools/session.js +1105 -0
- package/dist/core/tools/streaming/ToolCallAccumulator.js +64 -0
- package/dist/core/tools/types.js +2 -0
- package/dist/core/types/authorization.js +2 -0
- package/dist/core/types/context.js +2 -0
- package/dist/core/types/errors.js +29 -0
- package/dist/core/types/execution.js +65 -0
- package/dist/core/types/index.js +9 -0
- package/dist/core/types/llm.js +9 -0
- package/dist/core/types/loop.js +2 -0
- package/dist/core/types/planning.js +2 -0
- package/dist/core/types/runtime.js +2 -0
- package/dist/core/types/usage.js +2 -0
- package/dist/core/ui/kaomoji.js +5 -0
- package/dist/core/utils/path.js +116 -0
- package/dist/core/utils/platform-shell.js +10 -0
- package/dist/core/utils/sanitizer.js +107 -0
- package/dist/core/verification/runner.js +265 -0
- package/dist/integrations/langfuse/litellm-langfuse-outcome-reporter.js +272 -0
- package/dist/integrations/langfuse/outcome-proxy.js +68 -0
- package/dist/interfaces/cli/task-runner.js +11 -0
- package/dist/languages/typescript/index.js +178 -0
- package/dist/locales/en.js +679 -0
- package/dist/locales/index.js +11 -0
- package/dist/utils/eol.js +35 -0
- package/package.json +153 -0
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ShadowDriver - Main Implementation
|
|
3
|
+
*
|
|
4
|
+
* Core implementation of Layer 2 ShadowDriver following v2.0 specification.
|
|
5
|
+
*/
|
|
6
|
+
import { join } from 'path';
|
|
7
|
+
import { existsSync } from '../../../adapters/fs/node-fs.js';
|
|
8
|
+
import { rm, mkdir, symlink } from '../../../adapters/fs/node-fs.js';
|
|
9
|
+
import { getLogger } from '../../../observability/logger.js';
|
|
10
|
+
import { spawnCommand } from '../../../runtime/process-runner.js';
|
|
11
|
+
import { normalizePath } from '../../../utils/path.js';
|
|
12
|
+
import { getPlatformShellInvocation } from '../../../utils/platform-shell.js';
|
|
13
|
+
import { copyDir, linkDirLinux } from './copy-backend.js';
|
|
14
|
+
import { getEnvInjection } from './env.js';
|
|
15
|
+
import { isEnvironmentError } from './error-classifier.js';
|
|
16
|
+
import { enforceReadOnly, restoreWrite, acquireLock, releaseLock } from './readonly-lock.js';
|
|
17
|
+
import { determineStrategy, planDependencyPaths, detectDependencyPaths } from './strategy.js';
|
|
18
|
+
/**
|
|
19
|
+
* ShadowDriver Class
|
|
20
|
+
*/
|
|
21
|
+
export class ShadowDriver {
|
|
22
|
+
config;
|
|
23
|
+
constructor(config) {
|
|
24
|
+
this.config = config;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Hydrate a target directory with dependencies from a source repository.
|
|
28
|
+
* This projects the environment (node_modules, venv, etc.) into the target
|
|
29
|
+
* using cross-platform symlinks (junctions).
|
|
30
|
+
*
|
|
31
|
+
* Used by: Worktree Strategy (L1) to prepare the execution environment (L2).
|
|
32
|
+
*/
|
|
33
|
+
static async hydrate(repoRoot, targetRoot) {
|
|
34
|
+
const depPaths = await detectDependencyPaths(repoRoot);
|
|
35
|
+
if (depPaths.length === 0) {
|
|
36
|
+
getLogger().debug('No dependencies detected to hydrate.');
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
getLogger().debug(`Hydrating environment: ${depPaths.join(', ')} -> ${targetRoot}`);
|
|
40
|
+
for (const depPath of depPaths) {
|
|
41
|
+
const sourcePath = join(repoRoot, depPath);
|
|
42
|
+
const targetDepPath = join(targetRoot, depPath);
|
|
43
|
+
if (!existsSync(sourcePath)) {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
// Use 'junction' for Windows compatibility (no admin rights needed usually)
|
|
48
|
+
await symlink(sourcePath, targetDepPath, 'junction');
|
|
49
|
+
getLogger().debug(`Linked dependency: ${depPath}`);
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
if ((err && typeof err === 'object' && 'code' in err
|
|
53
|
+
? err.code
|
|
54
|
+
: undefined) !== 'EEXIST') {
|
|
55
|
+
getLogger().warn(`Failed to link ${depPath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
getLogger().debug(`Dependency link already exists: ${depPath}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Setup dependency environment for task execution
|
|
65
|
+
*/
|
|
66
|
+
async setup(task) {
|
|
67
|
+
// Acquire concurrency lock
|
|
68
|
+
await acquireLock(this.config.shadowRoot);
|
|
69
|
+
const strategy = determineStrategy(task, this.config.whitelist);
|
|
70
|
+
const depPaths = await planDependencyPaths(this.config);
|
|
71
|
+
getLogger().debug(`ShadowDriver setup: strategy=${strategy}, depPaths=${depPaths.join(',')}`);
|
|
72
|
+
// Prepare dependency directories
|
|
73
|
+
await this.prepareDependencyDirs(depPaths);
|
|
74
|
+
if (strategy === 'ISOLATED') {
|
|
75
|
+
if (existsSync(join(this.config.repoRoot, 'bun.lock')) ||
|
|
76
|
+
existsSync(join(this.config.repoRoot, 'bun.lockb'))) {
|
|
77
|
+
getLogger().debug('bun project detected');
|
|
78
|
+
}
|
|
79
|
+
await this.copyDependencies(depPaths);
|
|
80
|
+
}
|
|
81
|
+
else if (strategy === 'AGGRESSIVE') {
|
|
82
|
+
await this.linkDependencies(depPaths);
|
|
83
|
+
if (this.config.readonly)
|
|
84
|
+
await enforceReadOnly(this.config.shadowRoot, depPaths);
|
|
85
|
+
}
|
|
86
|
+
// OPTIMIZED strategy doesn't require copying/linking
|
|
87
|
+
return {
|
|
88
|
+
shadowPath: this.config.shadowRoot,
|
|
89
|
+
strategy,
|
|
90
|
+
fallbackApplied: false,
|
|
91
|
+
readonlyLocked: strategy === 'AGGRESSIVE' && this.config.readonly,
|
|
92
|
+
dependencyPaths: depPaths,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Run task with driver environment
|
|
97
|
+
*/
|
|
98
|
+
async run(task) {
|
|
99
|
+
return runWithDriver(task, this.config);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Cleanup shadow environment
|
|
103
|
+
*/
|
|
104
|
+
async cleanup(depPaths) {
|
|
105
|
+
await cleanup(this.config.shadowRoot, depPaths);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Prepare dependency directories in shadow root
|
|
109
|
+
*/
|
|
110
|
+
async prepareDependencyDirs(depPaths) {
|
|
111
|
+
for (const dep of depPaths) {
|
|
112
|
+
const depPath = join(this.config.shadowRoot, dep);
|
|
113
|
+
try {
|
|
114
|
+
// Create the directory itself to ensure copy contents works correctly (paired with cp src/. dest)
|
|
115
|
+
await mkdir(depPath, { recursive: true });
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
getLogger().warn(`Failed to create dependency directory ${depPath}: ${error}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Copy dependencies for ISOLATED strategy
|
|
124
|
+
*/
|
|
125
|
+
async copyDependencies(depPaths) {
|
|
126
|
+
for (const dep of depPaths) {
|
|
127
|
+
const srcPath = join(this.config.repoRoot, dep);
|
|
128
|
+
const destPath = join(this.config.shadowRoot, dep);
|
|
129
|
+
try {
|
|
130
|
+
await copyDir(srcPath, destPath, this.config.platform);
|
|
131
|
+
getLogger().debug(`Copied dependency: ${dep}`);
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
getLogger().error(`Failed to copy dependency ${dep}: ${error}`);
|
|
135
|
+
throw error;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Link dependencies for AGGRESSIVE strategy
|
|
141
|
+
*/
|
|
142
|
+
async linkDependencies(depPaths) {
|
|
143
|
+
if (this.config.platform !== 'linux') {
|
|
144
|
+
throw new Error('AGGRESSIVE strategy only supported on Linux');
|
|
145
|
+
}
|
|
146
|
+
for (const dep of depPaths) {
|
|
147
|
+
const srcPath = join(this.config.repoRoot, dep);
|
|
148
|
+
const destPath = join(this.config.shadowRoot, dep);
|
|
149
|
+
try {
|
|
150
|
+
await linkDirLinux(srcPath, destPath);
|
|
151
|
+
getLogger().debug(`Linked dependency: ${dep}`);
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
getLogger().error(`Failed to link dependency ${dep}: ${error}`);
|
|
155
|
+
throw error;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Run task with driver environment (with fallback support)
|
|
162
|
+
*/
|
|
163
|
+
async function runWithDriver(task, ctx, isFallback = false) {
|
|
164
|
+
const driver = new ShadowDriver(ctx);
|
|
165
|
+
let depPaths;
|
|
166
|
+
try {
|
|
167
|
+
const result = await driver.setup(task);
|
|
168
|
+
depPaths = result.dependencyPaths;
|
|
169
|
+
// Execute command with injected environment
|
|
170
|
+
const env = getEnvInjection(ctx.repoRoot);
|
|
171
|
+
await executeCommand(task.command, ctx.shadowRoot, env);
|
|
172
|
+
getLogger().debug(`Command executed successfully: ${task.command}`);
|
|
173
|
+
}
|
|
174
|
+
catch (error) {
|
|
175
|
+
if (isFallback)
|
|
176
|
+
throw error;
|
|
177
|
+
if (isEnvironmentError(error)) {
|
|
178
|
+
getLogger().debug(`Environment error detected, triggering fallback: ${error}`);
|
|
179
|
+
await cleanup(ctx.shadowRoot, depPaths);
|
|
180
|
+
return runWithDriver({ ...task, forceIsolation: true }, ctx, true);
|
|
181
|
+
}
|
|
182
|
+
throw error;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Execute command in shadow environment
|
|
187
|
+
*/
|
|
188
|
+
async function executeCommand(command, cwd, env) {
|
|
189
|
+
const shell = getPlatformShellInvocation(command);
|
|
190
|
+
let stderr = '';
|
|
191
|
+
const result = await spawnCommand({
|
|
192
|
+
command: shell.file,
|
|
193
|
+
args: shell.args,
|
|
194
|
+
cwd,
|
|
195
|
+
env,
|
|
196
|
+
onStderrChunk: (chunk) => {
|
|
197
|
+
stderr += Buffer.from(chunk).toString();
|
|
198
|
+
},
|
|
199
|
+
});
|
|
200
|
+
if (result.error) {
|
|
201
|
+
throw new Error(result.error.message);
|
|
202
|
+
}
|
|
203
|
+
if (!result.timedOut && result.code === 0) {
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
if (result.timedOut) {
|
|
207
|
+
throw new Error('command timed out');
|
|
208
|
+
}
|
|
209
|
+
const message = stderr.trim() || `command failed with exit code ${String(result.code)}`;
|
|
210
|
+
throw new Error(message);
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Cleanup shadow environment
|
|
214
|
+
*/
|
|
215
|
+
async function cleanup(root, depPaths) {
|
|
216
|
+
const normalizedRoot = normalizePath(root);
|
|
217
|
+
getLogger().debug(`Cleaning up shadow environment: ${normalizedRoot}`);
|
|
218
|
+
// Restore write permissions if needed
|
|
219
|
+
if (process.platform === 'linux' && depPaths?.length) {
|
|
220
|
+
await restoreWrite(root, depPaths);
|
|
221
|
+
}
|
|
222
|
+
// Release concurrency lock
|
|
223
|
+
await releaseLock(root);
|
|
224
|
+
// Remove shadow directory
|
|
225
|
+
try {
|
|
226
|
+
await rm(root, { recursive: true, force: true, maxRetries: 3, retryDelay: 200 });
|
|
227
|
+
getLogger().debug(`Successfully cleaned up shadow environment: ${normalizedRoot}`);
|
|
228
|
+
}
|
|
229
|
+
catch (error) {
|
|
230
|
+
getLogger().error(`Failed to cleanup shadow environment ${normalizedRoot}: ${error}`);
|
|
231
|
+
throw error;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
//# sourceMappingURL=shadow-driver.js.map
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strategy Selector for ShadowDriver
|
|
3
|
+
*
|
|
4
|
+
* Implements the strategy determination logic:
|
|
5
|
+
* - Default: ISOLATED (safe by default)
|
|
6
|
+
* - Whitelist: OPTIMIZED (fast if possible)
|
|
7
|
+
* - Blacklist: ISOLATED (fallback on failure)
|
|
8
|
+
*/
|
|
9
|
+
import { join } from 'path';
|
|
10
|
+
import { existsSync } from '../../../adapters/fs/node-fs.js';
|
|
11
|
+
import { WRITE_OP_BLACKLIST } from '../../types.js';
|
|
12
|
+
/**
|
|
13
|
+
* Normalize command for consistent matching
|
|
14
|
+
*/
|
|
15
|
+
function normalizeCommand(cmd) {
|
|
16
|
+
return cmd.trim().replace(/\\/g, '/').toLowerCase();
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Determine the appropriate strategy for a given task
|
|
20
|
+
*/
|
|
21
|
+
export function determineStrategy(task, whitelist) {
|
|
22
|
+
// Force isolation takes precedence
|
|
23
|
+
if (task.forceIsolation || task.requiresWrite)
|
|
24
|
+
return 'ISOLATED';
|
|
25
|
+
const normalizedCmd = normalizeCommand(task.command);
|
|
26
|
+
// Whitelist check
|
|
27
|
+
if (whitelist && whitelist.length > 0) {
|
|
28
|
+
const inWhitelist = whitelist.some((safeCmd) => normalizedCmd.startsWith(normalizeCommand(safeCmd)));
|
|
29
|
+
if (!inWhitelist)
|
|
30
|
+
return 'ISOLATED';
|
|
31
|
+
}
|
|
32
|
+
// Blacklist check
|
|
33
|
+
if (WRITE_OP_BLACKLIST.some((op) => normalizedCmd.includes(op)))
|
|
34
|
+
return 'ISOLATED';
|
|
35
|
+
// Mode-based optimization
|
|
36
|
+
if (task.mode === 'analysis' || task.mode === 'test_readonly')
|
|
37
|
+
return 'OPTIMIZED';
|
|
38
|
+
// Default to isolation
|
|
39
|
+
return 'ISOLATED';
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Plan dependency paths based on repository configuration
|
|
43
|
+
*/
|
|
44
|
+
export async function planDependencyPaths(config) {
|
|
45
|
+
if (config.dependencyPaths?.length) {
|
|
46
|
+
return config.dependencyPaths.filter((p) => validateDependencyPath(config.repoRoot, p));
|
|
47
|
+
}
|
|
48
|
+
return detectDependencyPaths(config.repoRoot);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Validate dependency path for security
|
|
52
|
+
*/
|
|
53
|
+
export function validateDependencyPath(repoRoot, depPath) {
|
|
54
|
+
if (depPath.startsWith('/') || /^[a-zA-Z]:/.test(depPath))
|
|
55
|
+
return false;
|
|
56
|
+
if (depPath.includes('..'))
|
|
57
|
+
return false;
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Detect dependency paths based on repository files
|
|
62
|
+
*/
|
|
63
|
+
export async function detectDependencyPaths(repoRoot) {
|
|
64
|
+
const paths = [];
|
|
65
|
+
// Node.js
|
|
66
|
+
if (existsSync(join(repoRoot, 'package.json'))) {
|
|
67
|
+
paths.push('node_modules');
|
|
68
|
+
}
|
|
69
|
+
// Python
|
|
70
|
+
if (existsSync(join(repoRoot, 'requirements.txt')) ||
|
|
71
|
+
existsSync(join(repoRoot, 'pyproject.toml'))) {
|
|
72
|
+
paths.push('venv');
|
|
73
|
+
paths.push('.venv');
|
|
74
|
+
paths.push('__pycache__');
|
|
75
|
+
}
|
|
76
|
+
// Rust
|
|
77
|
+
if (existsSync(join(repoRoot, 'Cargo.toml'))) {
|
|
78
|
+
paths.push('target');
|
|
79
|
+
}
|
|
80
|
+
// Go
|
|
81
|
+
if (existsSync(join(repoRoot, 'go.mod'))) {
|
|
82
|
+
paths.push('vendor');
|
|
83
|
+
}
|
|
84
|
+
return paths.filter((p) => existsSync(join(repoRoot, p)));
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=strategy.js.map
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SyntheticSidecarLayer - Layer 3 Ignored/Untracked File Handling
|
|
3
|
+
*
|
|
4
|
+
* Manages ignored and untracked files for ShadowMergeEngine
|
|
5
|
+
* Provides base content for ignored files that are modified during execution.
|
|
6
|
+
*/
|
|
7
|
+
import { dirname } from 'path';
|
|
8
|
+
import { existsSync } from '../../adapters/fs/node-fs.js';
|
|
9
|
+
import { mkdir, readFile, writeFile as writeFileToDisk } from '../../adapters/fs/node-fs.js';
|
|
10
|
+
import { getLogger } from '../../observability/logger.js';
|
|
11
|
+
import { isSafeRelativePath, normalizePath, safeJoin } from '../../utils/path.js';
|
|
12
|
+
/**
|
|
13
|
+
* SyntheticSidecarLayer Implementation
|
|
14
|
+
*/
|
|
15
|
+
export class SyntheticSidecarLayerImpl {
|
|
16
|
+
repoRoot;
|
|
17
|
+
capturedFiles = new Map();
|
|
18
|
+
constructor(repoRoot) {
|
|
19
|
+
this.repoRoot = repoRoot;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Capture ignored/untracked files
|
|
23
|
+
*/
|
|
24
|
+
async capture(paths) {
|
|
25
|
+
getLogger().debug(`Capturing ${paths.length} ignored/untracked files`);
|
|
26
|
+
for (const filePath of paths) {
|
|
27
|
+
const normalized = normalizePath(filePath);
|
|
28
|
+
if (!isSafeRelativePath(normalized)) {
|
|
29
|
+
getLogger().warn(`Skipping unsafe path capture: ${filePath}`);
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
const absolutePath = this.repoRoot ? safeJoin(this.repoRoot, normalized) : normalized;
|
|
34
|
+
if (existsSync(absolutePath)) {
|
|
35
|
+
const content = await readFile(absolutePath);
|
|
36
|
+
this.capturedFiles.set(normalized, content);
|
|
37
|
+
getLogger().debug(`Captured file: ${normalized}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
getLogger().warn(`Failed to capture file ${filePath}: ${error}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Inject captured files to shadow worktree
|
|
47
|
+
*/
|
|
48
|
+
async inject(shadowPath) {
|
|
49
|
+
getLogger().debug(`Injecting ${this.capturedFiles.size} files to shadow worktree`);
|
|
50
|
+
for (const [filePath, content] of this.capturedFiles) {
|
|
51
|
+
const shadowFilePath = safeJoin(shadowPath, filePath);
|
|
52
|
+
try {
|
|
53
|
+
await writeSidecarFile(shadowFilePath, content);
|
|
54
|
+
getLogger().debug(`Injected file: ${filePath}`);
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
getLogger().warn(`Failed to inject file ${filePath}: ${error}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Check if file is captured
|
|
63
|
+
*/
|
|
64
|
+
has(path) {
|
|
65
|
+
const normalized = normalizePath(path);
|
|
66
|
+
if (!isSafeRelativePath(normalized))
|
|
67
|
+
return false;
|
|
68
|
+
return this.capturedFiles.has(normalized);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Get captured file content
|
|
72
|
+
*/
|
|
73
|
+
async get(path) {
|
|
74
|
+
const normalized = normalizePath(path);
|
|
75
|
+
if (!isSafeRelativePath(normalized))
|
|
76
|
+
return null;
|
|
77
|
+
return this.capturedFiles.get(normalized) || null;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Clear captured files
|
|
81
|
+
*/
|
|
82
|
+
async clear() {
|
|
83
|
+
this.capturedFiles.clear();
|
|
84
|
+
getLogger().debug('Cleared all captured files');
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Write file helper
|
|
89
|
+
*/
|
|
90
|
+
async function writeSidecarFile(filePath, content) {
|
|
91
|
+
// Ensure directory exists
|
|
92
|
+
await mkdir(dirname(filePath), { recursive: true });
|
|
93
|
+
// Write file
|
|
94
|
+
await writeFileToDisk(filePath, content);
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=sidecar-layer.js.map
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import { randomBytes } from 'crypto';
|
|
2
|
+
import { tmpdir } from 'os';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { text } from '../../../locales/index.js';
|
|
5
|
+
import { access, realpath, rm } from '../../adapters/fs/node-fs.js';
|
|
6
|
+
import { GitAdapter } from '../../adapters/git/git-adapter.js';
|
|
7
|
+
import { getLogger } from '../../observability/logger.js';
|
|
8
|
+
import { isPathWithinDirectory, normalizePath } from '../../utils/path.js';
|
|
9
|
+
function resolveEnvironmentMode(options) {
|
|
10
|
+
return options.environmentMode === 'parity' ? 'parity' : 'strict';
|
|
11
|
+
}
|
|
12
|
+
function isWindowsAbsolutePath(p) {
|
|
13
|
+
return /^[a-zA-Z]:[\\/]/.test(p) || p.startsWith('\\\\');
|
|
14
|
+
}
|
|
15
|
+
function selectPathImpl(p) {
|
|
16
|
+
const normalized = normalizePath(p);
|
|
17
|
+
if (!normalized)
|
|
18
|
+
return path;
|
|
19
|
+
if (isWindowsAbsolutePath(normalized))
|
|
20
|
+
return path.win32;
|
|
21
|
+
if (normalized.startsWith('/'))
|
|
22
|
+
return path.posix;
|
|
23
|
+
return path;
|
|
24
|
+
}
|
|
25
|
+
function resolveParityWorktreeRoot(repoPath) {
|
|
26
|
+
const impl = selectPathImpl(repoPath);
|
|
27
|
+
const normalizedRepoPath = normalizePath(repoPath);
|
|
28
|
+
return normalizePath(impl.join(impl.dirname(impl.resolve(normalizedRepoPath)), '.salmonloop', 'worktrees'));
|
|
29
|
+
}
|
|
30
|
+
function isManagedWorktreePath(baseRepoPath, workPath) {
|
|
31
|
+
if (isPathWithinDirectory(tmpdir(), workPath, { allowEqual: false }))
|
|
32
|
+
return true;
|
|
33
|
+
const parityRoot = resolveParityWorktreeRoot(baseRepoPath);
|
|
34
|
+
if (isPathWithinDirectory(parityRoot, workPath, { allowEqual: false }))
|
|
35
|
+
return true;
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
function normalizePathForCompare(value) {
|
|
39
|
+
const normalized = path.normalize(value).replace(/\\/g, '/');
|
|
40
|
+
if (process.platform === 'darwin' && normalized.startsWith('/private/')) {
|
|
41
|
+
return normalized.slice('/private'.length);
|
|
42
|
+
}
|
|
43
|
+
return normalized;
|
|
44
|
+
}
|
|
45
|
+
async function tryRealpath(value) {
|
|
46
|
+
try {
|
|
47
|
+
return await realpath(value);
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
async function resolveWorktreeMatchPath(worktreePaths, targetPath) {
|
|
54
|
+
const targetNorm = normalizePathForCompare(targetPath);
|
|
55
|
+
const exactMatch = worktreePaths.find((p) => p === targetPath) ||
|
|
56
|
+
worktreePaths.find((p) => normalizePathForCompare(p) === targetNorm);
|
|
57
|
+
if (exactMatch)
|
|
58
|
+
return exactMatch;
|
|
59
|
+
const targetReal = await tryRealpath(targetPath);
|
|
60
|
+
if (!targetReal)
|
|
61
|
+
return null;
|
|
62
|
+
for (const candidate of worktreePaths) {
|
|
63
|
+
const candidateReal = await tryRealpath(candidate);
|
|
64
|
+
if (candidateReal && candidateReal === targetReal) {
|
|
65
|
+
return candidate;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* WorkspaceManager - Manages execution workspace for different checkpoint strategies
|
|
72
|
+
*
|
|
73
|
+
* Supports two strategies:
|
|
74
|
+
* - 'direct': Operates directly on the repository
|
|
75
|
+
* - 'worktree': Creates a temporary git worktree for isolated execution
|
|
76
|
+
*/
|
|
77
|
+
export class WorkspaceManager {
|
|
78
|
+
/**
|
|
79
|
+
* Setup execution workspace based on strategy
|
|
80
|
+
* @param options RunOptions with optional strategy
|
|
81
|
+
* @param initialCommit Optional commit hash to base the worktree on (defaults to HEAD)
|
|
82
|
+
* @param onEvent Optional event callback for reporting progress
|
|
83
|
+
* @returns ExecutionWorkspace configuration
|
|
84
|
+
*/
|
|
85
|
+
static async setup(options, initialCommit, onEvent) {
|
|
86
|
+
const strategy = options.strategy || 'direct';
|
|
87
|
+
const git = new GitAdapter(options.repoPath);
|
|
88
|
+
if (strategy === 'worktree') {
|
|
89
|
+
const baseRef = initialCommit || (await git.query(['rev-parse', 'HEAD']));
|
|
90
|
+
const repoPathImpl = selectPathImpl(options.repoPath);
|
|
91
|
+
const repoName = repoPathImpl.basename(normalizePath(options.repoPath));
|
|
92
|
+
const timestamp = Date.now();
|
|
93
|
+
const random = randomBytes(4).toString('hex');
|
|
94
|
+
const environmentMode = resolveEnvironmentMode(options);
|
|
95
|
+
const worktreeRootImpl = environmentMode === 'parity' ? selectPathImpl(options.repoPath) : selectPathImpl(tmpdir());
|
|
96
|
+
const rootDir = environmentMode === 'parity'
|
|
97
|
+
? worktreeRootImpl.join(resolveParityWorktreeRoot(options.repoPath), repoName)
|
|
98
|
+
: worktreeRootImpl.join(tmpdir(), `s8p-wt/${repoName}`);
|
|
99
|
+
const worktreePath = worktreeRootImpl.join(rootDir, `${timestamp}-${random}`);
|
|
100
|
+
const normalizedWorktreePath = worktreeRootImpl.normalize(worktreePath);
|
|
101
|
+
if (environmentMode === 'parity') {
|
|
102
|
+
const parityRoot = worktreeRootImpl.normalize(resolveParityWorktreeRoot(options.repoPath));
|
|
103
|
+
if (!isPathWithinDirectory(parityRoot, normalizedWorktreePath, { allowEqual: false })) {
|
|
104
|
+
throw new Error('Worktree path must be under parity worktree root');
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
const tmpDir = worktreeRootImpl.normalize(tmpdir());
|
|
109
|
+
if (!isPathWithinDirectory(tmpDir, normalizedWorktreePath, { allowEqual: false })) {
|
|
110
|
+
throw new Error('Worktree path must be in system temp directory');
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (isPathWithinDirectory(options.repoPath, worktreePath, { allowEqual: true })) {
|
|
114
|
+
throw new Error('Worktree path must not be inside repo path');
|
|
115
|
+
}
|
|
116
|
+
// Use GitAdapter for worktree creation
|
|
117
|
+
await git.query(['worktree', 'add', '--quiet', '--detach', worktreePath, baseRef.trim()]);
|
|
118
|
+
onEvent?.({
|
|
119
|
+
type: 'workspace.ready',
|
|
120
|
+
strategy: 'worktree',
|
|
121
|
+
path: worktreePath,
|
|
122
|
+
timestamp: new Date(),
|
|
123
|
+
});
|
|
124
|
+
getLogger().debug(`Created worktree at: ${worktreePath}`);
|
|
125
|
+
return {
|
|
126
|
+
baseRepoPath: options.repoPath,
|
|
127
|
+
workPath: worktreePath,
|
|
128
|
+
strategy: 'worktree',
|
|
129
|
+
environmentMode,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
// Default direct strategy
|
|
133
|
+
onEvent?.({
|
|
134
|
+
type: 'workspace.ready',
|
|
135
|
+
strategy: 'direct',
|
|
136
|
+
path: options.repoPath,
|
|
137
|
+
timestamp: new Date(),
|
|
138
|
+
});
|
|
139
|
+
return {
|
|
140
|
+
baseRepoPath: options.repoPath,
|
|
141
|
+
workPath: options.repoPath,
|
|
142
|
+
strategy: 'direct',
|
|
143
|
+
environmentMode: resolveEnvironmentMode(options),
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Teardown execution workspace and clean up resources
|
|
148
|
+
* @param workspace ExecutionWorkspace to teardown
|
|
149
|
+
* @param onEvent Optional event callback
|
|
150
|
+
*/
|
|
151
|
+
static async teardown(workspace, onEvent) {
|
|
152
|
+
if (workspace.strategy !== 'worktree') {
|
|
153
|
+
getLogger().debug(`Teardown workspace (strategy: ${workspace.strategy}) - no action needed`);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
if (workspace.workPath === workspace.baseRepoPath) {
|
|
157
|
+
onEvent?.({
|
|
158
|
+
type: 'resource.status',
|
|
159
|
+
resource: 'worktree',
|
|
160
|
+
status: 'skipped',
|
|
161
|
+
message: text.resource.worktreeSkipCleanup,
|
|
162
|
+
timestamp: new Date(),
|
|
163
|
+
});
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
const git = new GitAdapter(workspace.baseRepoPath);
|
|
167
|
+
let removed = false;
|
|
168
|
+
try {
|
|
169
|
+
const list = await git.query(['worktree', 'list', '--porcelain']);
|
|
170
|
+
const worktreePaths = list
|
|
171
|
+
.split('\n')
|
|
172
|
+
.map((line) => line.trim())
|
|
173
|
+
.filter((line) => line.startsWith('worktree '))
|
|
174
|
+
.map((line) => line.slice('worktree '.length).trim())
|
|
175
|
+
.filter(Boolean);
|
|
176
|
+
const matchPath = await resolveWorktreeMatchPath(worktreePaths, workspace.workPath);
|
|
177
|
+
if (matchPath) {
|
|
178
|
+
await git.query(['worktree', 'remove', '--force', matchPath]);
|
|
179
|
+
removed = true;
|
|
180
|
+
const directoryStillExists = await (async () => {
|
|
181
|
+
try {
|
|
182
|
+
await access(workspace.workPath);
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
if (error && typeof error === 'object' && error.code === 'ENOENT') {
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
return true;
|
|
190
|
+
}
|
|
191
|
+
})();
|
|
192
|
+
if (directoryStillExists) {
|
|
193
|
+
removed = false;
|
|
194
|
+
getLogger().debug(`git worktree remove reported success but directory still exists; falling back to fs.rm: ${workspace.workPath}`);
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
getLogger().debug(`Removed worktree: ${matchPath}`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
onEvent?.({
|
|
202
|
+
type: 'resource.status',
|
|
203
|
+
resource: 'worktree',
|
|
204
|
+
status: 'warning',
|
|
205
|
+
message: text.resource.worktreeNotFoundInList(workspace.workPath),
|
|
206
|
+
timestamp: new Date(),
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
catch (error) {
|
|
211
|
+
const msg = error instanceof Error
|
|
212
|
+
? error instanceof Error
|
|
213
|
+
? error.message
|
|
214
|
+
: String(error)
|
|
215
|
+
: String(error);
|
|
216
|
+
onEvent?.({
|
|
217
|
+
type: 'action.fallback',
|
|
218
|
+
tool: 'git',
|
|
219
|
+
method: 'worktree remove',
|
|
220
|
+
reason: msg,
|
|
221
|
+
severity: 'low',
|
|
222
|
+
timestamp: new Date(),
|
|
223
|
+
});
|
|
224
|
+
getLogger().debug(`git worktree remove failed, falling back to filesystem removal: ${msg}`);
|
|
225
|
+
}
|
|
226
|
+
if (!removed) {
|
|
227
|
+
if (!isManagedWorktreePath(workspace.baseRepoPath, workspace.workPath)) {
|
|
228
|
+
throw new Error('Worktree path not in managed roots, refusing to delete');
|
|
229
|
+
}
|
|
230
|
+
await rm(workspace.workPath, {
|
|
231
|
+
recursive: true,
|
|
232
|
+
force: true,
|
|
233
|
+
maxRetries: 3,
|
|
234
|
+
retryDelay: 100,
|
|
235
|
+
});
|
|
236
|
+
getLogger().debug(`Successfully cleaned up worktree directory via fs.rm: ${workspace.workPath}`);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
//# sourceMappingURL=worktree.js.map
|