@evalops/maestro 0.10.50 → 0.10.51
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/dist/agent/agent-outcome.d.ts +54 -0
- package/dist/agent/agent-outcome.d.ts.map +1 -0
- package/dist/agent/agent-outcome.js +142 -0
- package/dist/agent/agent-outcome.js.map +1 -0
- package/dist/agent/agent-resume.d.ts.map +1 -1
- package/dist/agent/agent-resume.js +3 -3
- package/dist/agent/agent-resume.js.map +1 -1
- package/dist/agent/agent-run-summary.d.ts +37 -0
- package/dist/agent/agent-run-summary.d.ts.map +1 -0
- package/dist/agent/agent-run-summary.js +15 -0
- package/dist/agent/agent-run-summary.js.map +1 -0
- package/dist/agent/agent-work-board.d.ts +82 -0
- package/dist/agent/agent-work-board.d.ts.map +1 -0
- package/dist/agent/agent-work-board.js +312 -0
- package/dist/agent/agent-work-board.js.map +1 -0
- package/dist/agent/auto-compaction.d.ts +7 -2
- package/dist/agent/auto-compaction.d.ts.map +1 -1
- package/dist/agent/auto-compaction.js +23 -10
- package/dist/agent/auto-compaction.js.map +1 -1
- package/dist/agent/mission-artifacts.d.ts +62 -0
- package/dist/agent/mission-artifacts.d.ts.map +1 -0
- package/dist/agent/mission-artifacts.js +438 -0
- package/dist/agent/mission-artifacts.js.map +1 -0
- package/dist/agent/mission-manifest.d.ts +139 -3
- package/dist/agent/mission-manifest.d.ts.map +1 -1
- package/dist/agent/mission-manifest.js +549 -3
- package/dist/agent/mission-manifest.js.map +1 -1
- package/dist/agent/mission-store.d.ts +80 -0
- package/dist/agent/mission-store.d.ts.map +1 -0
- package/dist/agent/mission-store.js +603 -0
- package/dist/agent/mission-store.js.map +1 -0
- package/dist/agent/modes.d.ts +2 -2
- package/dist/agent/modes.d.ts.map +1 -1
- package/dist/agent/modes.js +10 -3
- package/dist/agent/modes.js.map +1 -1
- package/dist/agent/providers/codex-app-server.d.ts.map +1 -1
- package/dist/agent/providers/codex-app-server.js +1 -3
- package/dist/agent/providers/codex-app-server.js.map +1 -1
- package/dist/agent/providers/google-gemini-cli.js +203 -107
- package/dist/agent/providers/google.js +100 -41
- package/dist/agent/providers/scripted.d.ts.map +1 -1
- package/dist/agent/providers/scripted.js +1 -3
- package/dist/agent/providers/scripted.js.map +1 -1
- package/dist/agent/providers/validation.d.ts.map +1 -1
- package/dist/agent/providers/validation.js +1 -3
- package/dist/agent/providers/validation.js.map +1 -1
- package/dist/agent/providers/vertex.js +203 -107
- package/dist/agent/snapshot-store.d.ts +32 -0
- package/dist/agent/snapshot-store.d.ts.map +1 -0
- package/dist/agent/snapshot-store.js +195 -0
- package/dist/agent/snapshot-store.js.map +1 -0
- package/dist/agent/specialist-profiles.d.ts +36 -0
- package/dist/agent/specialist-profiles.d.ts.map +1 -0
- package/dist/agent/specialist-profiles.js +159 -0
- package/dist/agent/specialist-profiles.js.map +1 -0
- package/dist/agent/subagent-specs.d.ts +4 -1
- package/dist/agent/subagent-specs.d.ts.map +1 -1
- package/dist/agent/subagent-specs.js +81 -8
- package/dist/agent/subagent-specs.js.map +1 -1
- package/dist/agent/swarm/coverage-gate.d.ts +37 -0
- package/dist/agent/swarm/coverage-gate.d.ts.map +1 -0
- package/dist/agent/swarm/coverage-gate.js +48 -0
- package/dist/agent/swarm/coverage-gate.js.map +1 -0
- package/dist/agent/swarm/executor.d.ts +1 -0
- package/dist/agent/swarm/executor.d.ts.map +1 -1
- package/dist/agent/swarm/executor.js +151 -15
- package/dist/agent/swarm/executor.js.map +1 -1
- package/dist/agent/swarm/orchestrator-prompt.d.ts +25 -0
- package/dist/agent/swarm/orchestrator-prompt.d.ts.map +1 -0
- package/dist/agent/swarm/orchestrator-prompt.js +48 -0
- package/dist/agent/swarm/orchestrator-prompt.js.map +1 -0
- package/dist/agent/swarm/plan-parser.d.ts.map +1 -1
- package/dist/agent/swarm/plan-parser.js +27 -2
- package/dist/agent/swarm/plan-parser.js.map +1 -1
- package/dist/agent/swarm/types.d.ts +17 -0
- package/dist/agent/swarm/types.d.ts.map +1 -1
- package/dist/agent/swarm/types.js.map +1 -1
- package/dist/agent/swarm/validation-directive.d.ts +21 -0
- package/dist/agent/swarm/validation-directive.d.ts.map +1 -0
- package/dist/agent/swarm/validation-directive.js +25 -0
- package/dist/agent/swarm/validation-directive.js.map +1 -0
- package/dist/agent/transport/tool-execution-bridge.d.ts.map +1 -1
- package/dist/agent/transport/tool-execution-bridge.js +4 -1
- package/dist/agent/transport/tool-execution-bridge.js.map +1 -1
- package/dist/api/enterprise-routes.d.ts.map +1 -1
- package/dist/api/enterprise-routes.js +87 -10
- package/dist/api/enterprise-routes.js.map +1 -1
- package/dist/api/org-settings-merge.d.ts +12 -0
- package/dist/api/org-settings-merge.d.ts.map +1 -0
- package/dist/api/org-settings-merge.js +38 -0
- package/dist/api/org-settings-merge.js.map +1 -0
- package/dist/api/user-settings-merge.d.ts +16 -0
- package/dist/api/user-settings-merge.d.ts.map +1 -0
- package/dist/api/user-settings-merge.js +37 -0
- package/dist/api/user-settings-merge.js.map +1 -0
- package/dist/app-server/daemon-lifecycle-api.d.ts.map +1 -1
- package/dist/app-server/daemon-lifecycle-api.js +1 -3
- package/dist/app-server/daemon-lifecycle-api.js.map +1 -1
- package/dist/app-server/external-agent-import-api.d.ts.map +1 -1
- package/dist/app-server/external-agent-import-api.js +1 -3
- package/dist/app-server/external-agent-import-api.js.map +1 -1
- package/dist/app-server/network-governance-api.d.ts.map +1 -1
- package/dist/app-server/network-governance-api.js +1 -3
- package/dist/app-server/network-governance-api.js.map +1 -1
- package/dist/app-server/plugin-bundle-api.d.ts.map +1 -1
- package/dist/app-server/plugin-bundle-api.js +1 -3
- package/dist/app-server/plugin-bundle-api.js.map +1 -1
- package/dist/app-server/policy-control-api.d.ts.map +1 -1
- package/dist/app-server/policy-control-api.js +1 -3
- package/dist/app-server/policy-control-api.js.map +1 -1
- package/dist/app-server/protocol-modes-api.d.ts.map +1 -1
- package/dist/app-server/protocol-modes-api.js +1 -3
- package/dist/app-server/protocol-modes-api.js.map +1 -1
- package/dist/cli/args.d.ts +2 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +15 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/commands/a2a.d.ts.map +1 -1
- package/dist/cli/commands/a2a.js +1 -3
- package/dist/cli/commands/a2a.js.map +1 -1
- package/dist/cli/commands/agents.d.ts +4 -0
- package/dist/cli/commands/agents.d.ts.map +1 -1
- package/dist/cli/commands/agents.js +149 -0
- package/dist/cli/commands/agents.js.map +1 -1
- package/dist/cli/commands/mission.d.ts +4 -0
- package/dist/cli/commands/mission.d.ts.map +1 -0
- package/dist/cli/commands/mission.js +196 -0
- package/dist/cli/commands/mission.js.map +1 -0
- package/dist/cli/commands/value.d.ts +10 -0
- package/dist/cli/commands/value.d.ts.map +1 -0
- package/dist/cli/commands/value.js +33 -0
- package/dist/cli/commands/value.js.map +1 -0
- package/dist/cli/headless-protocol.d.ts.map +1 -1
- package/dist/cli/headless-protocol.js +1 -3
- package/dist/cli/headless-protocol.js.map +1 -1
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +10 -0
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/system-prompt.d.ts.map +1 -1
- package/dist/cli/system-prompt.js +38 -7
- package/dist/cli/system-prompt.js.map +1 -1
- package/dist/cli-runtime.js +7756 -2800
- package/dist/cli-tui/client-tools/client-tool-controller.d.ts.map +1 -1
- package/dist/cli-tui/client-tools/client-tool-controller.js +1 -3
- package/dist/cli-tui/client-tools/client-tool-controller.js.map +1 -1
- package/dist/cli-tui/commands/undo-handlers.d.ts.map +1 -1
- package/dist/cli-tui/commands/undo-handlers.js +7 -2
- package/dist/cli-tui/commands/undo-handlers.js.map +1 -1
- package/dist/cli-tui/tui-renderer/skills-controller.d.ts +3 -0
- package/dist/cli-tui/tui-renderer/skills-controller.d.ts.map +1 -1
- package/dist/cli-tui/tui-renderer/skills-controller.js +77 -33
- package/dist/cli-tui/tui-renderer/skills-controller.js.map +1 -1
- package/dist/codex/app-server-client.d.ts.map +1 -1
- package/dist/codex/app-server-client.js +1 -3
- package/dist/codex/app-server-client.js.map +1 -1
- package/dist/codex/compatibility.d.ts.map +1 -1
- package/dist/codex/compatibility.js +1 -3
- package/dist/codex/compatibility.js.map +1 -1
- package/dist/codex/subagent-dispatch-table.d.ts +8 -0
- package/dist/codex/subagent-dispatch-table.d.ts.map +1 -1
- package/dist/codex/subagent-dispatch-table.js +23 -0
- package/dist/codex/subagent-dispatch-table.js.map +1 -1
- package/dist/context/manifest.d.ts.map +1 -1
- package/dist/context/manifest.js +1 -3
- package/dist/context/manifest.js.map +1 -1
- package/dist/conversation/render-model.d.ts +0 -36
- package/dist/conversation/render-model.d.ts.map +1 -1
- package/dist/conversation/render-model.js +1 -3
- package/dist/conversation/render-model.js.map +1 -1
- package/dist/customer-value/ambient-learning.d.ts +75 -0
- package/dist/customer-value/ambient-learning.d.ts.map +1 -0
- package/dist/customer-value/ambient-learning.js +472 -0
- package/dist/customer-value/ambient-learning.js.map +1 -0
- package/dist/customer-value/internal-helpers.d.ts +13 -0
- package/dist/customer-value/internal-helpers.d.ts.map +1 -0
- package/dist/customer-value/internal-helpers.js +70 -0
- package/dist/customer-value/internal-helpers.js.map +1 -0
- package/dist/customer-value/report.d.ts +282 -0
- package/dist/customer-value/report.d.ts.map +1 -0
- package/dist/customer-value/report.js +2085 -0
- package/dist/customer-value/report.js.map +1 -0
- package/dist/db/schema.d.ts +5 -1
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/schema.js.map +1 -1
- package/dist/evalops/agent-bootstrap.d.ts.map +1 -1
- package/dist/evalops/agent-bootstrap.js +1 -3
- package/dist/evalops/agent-bootstrap.js.map +1 -1
- package/dist/evalops/agent-mcp-metadata.d.ts.map +1 -1
- package/dist/evalops/agent-mcp-metadata.js +1 -3
- package/dist/evalops/agent-mcp-metadata.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/installers/maestro-review-workflow.d.ts +38 -0
- package/dist/installers/maestro-review-workflow.d.ts.map +1 -0
- package/dist/installers/maestro-review-workflow.js +163 -0
- package/dist/installers/maestro-review-workflow.js.map +1 -0
- package/dist/load-env.d.ts.map +1 -1
- package/dist/load-env.js +2 -1
- package/dist/load-env.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +92 -3
- package/dist/main.js.map +1 -1
- package/dist/mcp/config.d.ts.map +1 -1
- package/dist/mcp/config.js +1 -3
- package/dist/mcp/config.js.map +1 -1
- package/dist/mcp/elicitation.d.ts.map +1 -1
- package/dist/mcp/elicitation.js +1 -3
- package/dist/mcp/elicitation.js.map +1 -1
- package/dist/mcp/official-registry.d.ts.map +1 -1
- package/dist/mcp/official-registry.js +1 -3
- package/dist/mcp/official-registry.js.map +1 -1
- package/dist/mcp/workspace-trust.d.ts.map +1 -1
- package/dist/mcp/workspace-trust.js +1 -3
- package/dist/mcp/workspace-trust.js.map +1 -1
- package/dist/memory/service-client.d.ts.map +1 -1
- package/dist/memory/service-client.js +1 -3
- package/dist/memory/service-client.js.map +1 -1
- package/dist/models/config-loader.d.ts.map +1 -1
- package/dist/models/config-loader.js +1 -3
- package/dist/models/config-loader.js.map +1 -1
- package/dist/node_modules/@evalops/contracts/dist/index.d.ts +1 -0
- package/dist/node_modules/@evalops/contracts/dist/index.d.ts.map +1 -1
- package/dist/node_modules/@evalops/contracts/dist/index.js +1 -0
- package/dist/node_modules/@evalops/contracts/dist/index.js.map +1 -1
- package/dist/node_modules/@evalops/contracts/dist/maestro-settings.d.ts +61 -0
- package/dist/node_modules/@evalops/contracts/dist/maestro-settings.d.ts.map +1 -0
- package/dist/node_modules/@evalops/contracts/dist/maestro-settings.js +183 -0
- package/dist/node_modules/@evalops/contracts/dist/maestro-settings.js.map +1 -0
- package/dist/node_modules/@evalops/contracts/package.json +1 -1
- package/dist/node_modules/@evalops/tui/package.json +1 -1
- package/dist/oauth/connectors.d.ts.map +1 -1
- package/dist/oauth/connectors.js +1 -3
- package/dist/oauth/connectors.js.map +1 -1
- package/dist/oauth/evalops.d.ts.map +1 -1
- package/dist/oauth/evalops.js +1 -3
- package/dist/oauth/evalops.js.map +1 -1
- package/dist/platform/a2a-client.d.ts.map +1 -1
- package/dist/platform/a2a-client.js +1 -3
- package/dist/platform/a2a-client.js.map +1 -1
- package/dist/platform/a2a-cockpit.d.ts +1 -0
- package/dist/platform/a2a-cockpit.d.ts.map +1 -1
- package/dist/platform/a2a-cockpit.js +42 -11
- package/dist/platform/a2a-cockpit.js.map +1 -1
- package/dist/platform/a2a-completion-audit.d.ts +1 -1
- package/dist/platform/a2a-completion-audit.d.ts.map +1 -1
- package/dist/platform/a2a-completion-audit.js +7 -11
- package/dist/platform/a2a-completion-audit.js.map +1 -1
- package/dist/platform/a2a-maestro-peer.js +16 -0
- package/dist/platform/a2a-maestro-peer.js.map +1 -1
- package/dist/platform/a2a-peer-pairing.d.ts.map +1 -1
- package/dist/platform/a2a-peer-pairing.js +1 -3
- package/dist/platform/a2a-peer-pairing.js.map +1 -1
- package/dist/platform/a2a-peer-registry.d.ts.map +1 -1
- package/dist/platform/a2a-peer-registry.js +1 -3
- package/dist/platform/a2a-peer-registry.js.map +1 -1
- package/dist/platform/a2a-task-ledger.d.ts +20 -0
- package/dist/platform/a2a-task-ledger.d.ts.map +1 -1
- package/dist/platform/a2a-task-ledger.js +207 -11
- package/dist/platform/a2a-task-ledger.js.map +1 -1
- package/dist/platform/a2a-work-graph.d.ts.map +1 -1
- package/dist/platform/a2a-work-graph.js +1 -3
- package/dist/platform/a2a-work-graph.js.map +1 -1
- package/dist/platform/operating-layer.d.ts.map +1 -1
- package/dist/platform/operating-layer.js +14 -8
- package/dist/platform/operating-layer.js.map +1 -1
- package/dist/platform/tool-execution-client.d.ts.map +1 -1
- package/dist/platform/tool-execution-client.js +19 -2
- package/dist/platform/tool-execution-client.js.map +1 -1
- package/dist/providers/auth.d.ts.map +1 -1
- package/dist/providers/auth.js +1 -3
- package/dist/providers/auth.js.map +1 -1
- package/dist/runtime/env.d.ts +9 -1
- package/dist/runtime/env.d.ts.map +1 -1
- package/dist/runtime/env.js +63 -1
- package/dist/runtime/env.js.map +1 -1
- package/dist/safety/policy.d.ts.map +1 -1
- package/dist/safety/policy.js +1 -4
- package/dist/safety/policy.js.map +1 -1
- package/dist/sandbox/docker-sandbox.d.ts.map +1 -1
- package/dist/sandbox/docker-sandbox.js +6 -1
- package/dist/sandbox/docker-sandbox.js.map +1 -1
- package/dist/server/handlers/hosted-runner-drain.d.ts.map +1 -1
- package/dist/server/handlers/hosted-runner-drain.js +1 -3
- package/dist/server/handlers/hosted-runner-drain.js.map +1 -1
- package/dist/server/handlers/platform-a2a-push.d.ts.map +1 -1
- package/dist/server/handlers/platform-a2a-push.js +53 -2
- package/dist/server/handlers/platform-a2a-push.js.map +1 -1
- package/dist/server/handlers/runtime-app-server-ws.d.ts.map +1 -1
- package/dist/server/handlers/runtime-app-server-ws.js +1 -3
- package/dist/server/handlers/runtime-app-server-ws.js.map +1 -1
- package/dist/server/headless-runtime-service.d.ts +16 -0
- package/dist/server/headless-runtime-service.d.ts.map +1 -1
- package/dist/server/headless-runtime-service.js +232 -206
- package/dist/server/headless-runtime-service.js.map +1 -1
- package/dist/server/hosted-agent-runtime-progress.d.ts.map +1 -1
- package/dist/server/hosted-agent-runtime-progress.js +12 -3
- package/dist/server/hosted-agent-runtime-progress.js.map +1 -1
- package/dist/server/pending-request-payload.d.ts.map +1 -1
- package/dist/server/pending-request-payload.js +1 -3
- package/dist/server/pending-request-payload.js.map +1 -1
- package/dist/server/route-auth.d.ts.map +1 -1
- package/dist/server/route-auth.js +2 -0
- package/dist/server/route-auth.js.map +1 -1
- package/dist/server/session-serialization.d.ts.map +1 -1
- package/dist/server/session-serialization.js +1 -3
- package/dist/server/session-serialization.js.map +1 -1
- package/dist/services/compliance/normalize.d.ts.map +1 -1
- package/dist/services/compliance/normalize.js +1 -3
- package/dist/services/compliance/normalize.js.map +1 -1
- package/dist/services/intelligent-router/normalize.d.ts.map +1 -1
- package/dist/services/intelligent-router/normalize.js +1 -3
- package/dist/services/intelligent-router/normalize.js.map +1 -1
- package/dist/services/revenue-attribution/normalize.d.ts.map +1 -1
- package/dist/services/revenue-attribution/normalize.js +1 -3
- package/dist/services/revenue-attribution/normalize.js.map +1 -1
- package/dist/services/traces/normalize.d.ts.map +1 -1
- package/dist/services/traces/normalize.js +1 -3
- package/dist/services/traces/normalize.js.map +1 -1
- package/dist/services/workspace-config/normalize.d.ts.map +1 -1
- package/dist/services/workspace-config/normalize.js +1 -3
- package/dist/services/workspace-config/normalize.js.map +1 -1
- package/dist/skills/composer.d.ts.map +1 -1
- package/dist/skills/composer.js +13 -1
- package/dist/skills/composer.js.map +1 -1
- package/dist/skills/index.d.ts +1 -0
- package/dist/skills/index.d.ts.map +1 -1
- package/dist/skills/index.js +1 -0
- package/dist/skills/index.js.map +1 -1
- package/dist/skills/learned-guidelines.d.ts +33 -0
- package/dist/skills/learned-guidelines.d.ts.map +1 -0
- package/dist/skills/learned-guidelines.js +291 -0
- package/dist/skills/learned-guidelines.js.map +1 -0
- package/dist/skills/linter.d.ts.map +1 -1
- package/dist/skills/linter.js +1 -3
- package/dist/skills/linter.js.map +1 -1
- package/dist/skills/runtime-activation.d.ts +1 -0
- package/dist/skills/runtime-activation.d.ts.map +1 -1
- package/dist/skills/runtime-activation.js +2 -3
- package/dist/skills/runtime-activation.js.map +1 -1
- package/dist/skills/tool.d.ts.map +1 -1
- package/dist/skills/tool.js +26 -21
- package/dist/skills/tool.js.map +1 -1
- package/dist/skills/trust-cache.d.ts +7 -0
- package/dist/skills/trust-cache.d.ts.map +1 -1
- package/dist/skills/trust-cache.js +16 -0
- package/dist/skills/trust-cache.js.map +1 -1
- package/dist/telemetry/agent-workforce-native-event.d.ts.map +1 -1
- package/dist/telemetry/agent-workforce-native-event.js +1 -3
- package/dist/telemetry/agent-workforce-native-event.js.map +1 -1
- package/dist/telemetry/maestro-event-bus.d.ts.map +1 -1
- package/dist/telemetry/maestro-event-bus.js +42 -81
- package/dist/telemetry/maestro-event-bus.js.map +1 -1
- package/dist/telemetry/maestro-platform-replay-fixture.d.ts.map +1 -1
- package/dist/telemetry/maestro-platform-replay-fixture.js +1 -3
- package/dist/telemetry/maestro-platform-replay-fixture.js.map +1 -1
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/telemetry.js +54 -43
- package/dist/telemetry.js.map +1 -1
- package/dist/theme/theme-loader.d.ts.map +1 -1
- package/dist/theme/theme-loader.js +1 -3
- package/dist/theme/theme-loader.js.map +1 -1
- package/dist/tools/apply-patch.d.ts.map +1 -1
- package/dist/tools/apply-patch.js +76 -8
- package/dist/tools/apply-patch.js.map +1 -1
- package/dist/tools/diff-preview.d.ts.map +1 -1
- package/dist/tools/diff-preview.js +10 -1
- package/dist/tools/diff-preview.js.map +1 -1
- package/dist/tools/edit.d.ts.map +1 -1
- package/dist/tools/edit.js +17 -0
- package/dist/tools/edit.js.map +1 -1
- package/dist/tools/write.d.ts.map +1 -1
- package/dist/tools/write.js +9 -0
- package/dist/tools/write.js.map +1 -1
- package/dist/undo/tracker.d.ts +5 -0
- package/dist/undo/tracker.d.ts.map +1 -1
- package/dist/undo/tracker.js +13 -0
- package/dist/undo/tracker.js.map +1 -1
- package/dist/utils/fs.d.ts +1 -1
- package/dist/utils/fs.d.ts.map +1 -1
- package/dist/utils/fs.js +29 -2
- package/dist/utils/fs.js.map +1 -1
- package/dist/utils/git-stash.d.ts.map +1 -1
- package/dist/utils/git-stash.js +15 -8
- package/dist/utils/git-stash.js.map +1 -1
- package/dist/utils/json.d.ts +11 -0
- package/dist/utils/json.d.ts.map +1 -1
- package/dist/utils/json.js +9 -0
- package/dist/utils/json.js.map +1 -1
- package/dist/utils/shell-env.d.ts.map +1 -1
- package/dist/utils/shell-env.js +2 -0
- package/dist/utils/shell-env.js.map +1 -1
- package/dist/utils/url-extractor-git.d.ts +26 -0
- package/dist/utils/url-extractor-git.d.ts.map +1 -0
- package/dist/utils/url-extractor-git.js +259 -0
- package/dist/utils/url-extractor-git.js.map +1 -0
- package/dist/utils/url-extractor.d.ts.map +1 -1
- package/dist/utils/url-extractor.js +23 -251
- package/dist/utils/url-extractor.js.map +1 -1
- package/dist/version.json +2 -2
- package/package.json +310 -306
- package/skills/incident-triage/SKILL.md +19 -1
- package/skills/install-code-review/SKILL.md +69 -0
- package/skills/security-review/SKILL.md +68 -0
- package/skills/security-review/reference/rubric.md +85 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diff-preview.js","sourceRoot":"","sources":["../../src/tools/diff-preview.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Diff Preview\n *\n * Shows a preview of changes before applying them, similar to Cursor's\n * diff view. Enables users to review and approve changes before they're\n * written to disk.\n *\n * ## Features\n *\n * - Generate unified diffs from edits\n * - Side-by-side comparison view\n * - Hunk-level approval/rejection\n * - Syntax highlighting support\n * - Integration with undo system\n *\n * ## Usage\n *\n * ```typescript\n * import { diffPreview } from \"./diff-preview.js\";\n *\n * // Create preview for an edit\n * const preview = await diffPreview.createPreview({\n * filePath: \"src/main.ts\",\n * originalContent: \"...\",\n * newContent: \"...\",\n * });\n *\n * // Format for display\n * const formatted = diffPreview.formatUnified(preview);\n * ```\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { basename } from \"node:path\";\nimport { createLogger } from \"../utils/logger.js\";\n\nconst logger = createLogger(\"tools:diff-preview\");\n\n/**\n * A single line in a diff\n */\nexport interface DiffLine {\n\ttype: \"context\" | \"add\" | \"remove\" | \"header\";\n\tcontent: string;\n\toldLineNum?: number;\n\tnewLineNum?: number;\n}\n\n/**\n * A hunk in a diff\n */\nexport interface DiffHunk {\n\toldStart: number;\n\toldCount: number;\n\tnewStart: number;\n\tnewCount: number;\n\tlines: DiffLine[];\n\theader: string;\n}\n\n/**\n * Complete diff preview\n */\nexport interface DiffPreviewResult {\n\tfilePath: string;\n\tfileName: string;\n\thunks: DiffHunk[];\n\tadditions: number;\n\tdeletions: number;\n\tisNewFile: boolean;\n\tisDeleted: boolean;\n\toriginalContent: string;\n\tnewContent: string;\n}\n\n/**\n * Preview configuration\n */\nexport interface PreviewConfig {\n\tfilePath: string;\n\toriginalContent?: string;\n\tnewContent: string;\n\tcontextLines?: number;\n}\n\n/**\n * Apply mode for changes\n */\nexport type ApplyMode = \"all\" | \"hunks\" | \"lines\";\n\n/**\n * Compute longest common subsequence for diff algorithm\n */\nfunction computeLCS(a: string[], b: string[]): number[][] {\n\tconst m = a.length;\n\tconst n = b.length;\n\tconst dp: number[][] = Array(m + 1)\n\t\t.fill(null)\n\t\t.map(() => Array(n + 1).fill(0));\n\n\tfor (let i = 1; i <= m; i++) {\n\t\tfor (let j = 1; j <= n; j++) {\n\t\t\tif (a[i - 1] === b[j - 1]) {\n\t\t\t\tdp[i]![j] = (dp[i - 1]?.[j - 1] || 0) + 1;\n\t\t\t} else {\n\t\t\t\tdp[i]![j] = Math.max(dp[i - 1]?.[j] || 0, dp[i]?.[j - 1] || 0);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn dp;\n}\n\n/**\n * Generate diff between two arrays of lines\n */\nfunction generateDiff(\n\toldLines: string[],\n\tnewLines: string[],\n\tcontextLines = 3,\n): DiffHunk[] {\n\tconst dp = computeLCS(oldLines, newLines);\n\tconst operations: Array<{\n\t\ttype: \"keep\" | \"add\" | \"remove\";\n\t\tline: string;\n\t\toldIdx?: number;\n\t\tnewIdx?: number;\n\t}> = [];\n\n\t// Backtrack to find the diff\n\tlet i = oldLines.length;\n\tlet j = newLines.length;\n\n\twhile (i > 0 || j > 0) {\n\t\tif (i > 0 && j > 0 && oldLines[i - 1] === newLines[j - 1]) {\n\t\t\toperations.unshift({\n\t\t\t\ttype: \"keep\",\n\t\t\t\tline: oldLines[i - 1]!,\n\t\t\t\toldIdx: i - 1,\n\t\t\t\tnewIdx: j - 1,\n\t\t\t});\n\t\t\ti--;\n\t\t\tj--;\n\t\t} else if (\n\t\t\tj > 0 &&\n\t\t\t(i === 0 || (dp[i]?.[j - 1] || 0) >= (dp[i - 1]?.[j] || 0))\n\t\t) {\n\t\t\toperations.unshift({\n\t\t\t\ttype: \"add\",\n\t\t\t\tline: newLines[j - 1]!,\n\t\t\t\tnewIdx: j - 1,\n\t\t\t});\n\t\t\tj--;\n\t\t} else {\n\t\t\toperations.unshift({\n\t\t\t\ttype: \"remove\",\n\t\t\t\tline: oldLines[i - 1]!,\n\t\t\t\toldIdx: i - 1,\n\t\t\t});\n\t\t\ti--;\n\t\t}\n\t}\n\n\t// Convert operations to hunks\n\tconst hunks: DiffHunk[] = [];\n\tlet currentHunk: DiffHunk | null = null;\n\tlet lastChangeIdx = Number.NEGATIVE_INFINITY;\n\n\tfor (let opIdx = 0; opIdx < operations.length; opIdx++) {\n\t\tconst op = operations[opIdx]!;\n\t\tconst isChange = op.type !== \"keep\";\n\n\t\tif (isChange) {\n\t\t\t// Start a new hunk or extend the current one\n\t\t\tif (!currentHunk || opIdx - lastChangeIdx > contextLines * 2) {\n\t\t\t\t// Start new hunk\n\t\t\t\tif (currentHunk) {\n\t\t\t\t\thunks.push(currentHunk);\n\t\t\t\t}\n\n\t\t\t\tconst startIdx = Math.max(0, opIdx - contextLines);\n\t\t\t\tcurrentHunk = {\n\t\t\t\t\toldStart: (operations[startIdx]?.oldIdx ?? 0) + 1,\n\t\t\t\t\toldCount: 0,\n\t\t\t\t\tnewStart: (operations[startIdx]?.newIdx ?? 0) + 1,\n\t\t\t\t\tnewCount: 0,\n\t\t\t\t\tlines: [],\n\t\t\t\t\theader: \"\",\n\t\t\t\t};\n\n\t\t\t\t// Add leading context\n\t\t\t\tfor (let ctx = startIdx; ctx < opIdx; ctx++) {\n\t\t\t\t\tconst ctxOp = operations[ctx];\n\t\t\t\t\tif (ctxOp && ctxOp.type === \"keep\") {\n\t\t\t\t\t\tcurrentHunk.lines.push({\n\t\t\t\t\t\t\ttype: \"context\",\n\t\t\t\t\t\t\tcontent: ctxOp.line,\n\t\t\t\t\t\t\toldLineNum: (ctxOp.oldIdx ?? 0) + 1,\n\t\t\t\t\t\t\tnewLineNum: (ctxOp.newIdx ?? 0) + 1,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tcurrentHunk.oldCount++;\n\t\t\t\t\t\tcurrentHunk.newCount++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlastChangeIdx = opIdx;\n\t\t}\n\n\t\tif (currentHunk) {\n\t\t\tif (op.type === \"keep\") {\n\t\t\t\t// Check if we should add trailing context\n\t\t\t\tif (opIdx - lastChangeIdx <= contextLines) {\n\t\t\t\t\tcurrentHunk.lines.push({\n\t\t\t\t\t\ttype: \"context\",\n\t\t\t\t\t\tcontent: op.line,\n\t\t\t\t\t\toldLineNum: (op.oldIdx ?? 0) + 1,\n\t\t\t\t\t\tnewLineNum: (op.newIdx ?? 0) + 1,\n\t\t\t\t\t});\n\t\t\t\t\tcurrentHunk.oldCount++;\n\t\t\t\t\tcurrentHunk.newCount++;\n\t\t\t\t}\n\t\t\t} else if (op.type === \"add\") {\n\t\t\t\tcurrentHunk.lines.push({\n\t\t\t\t\ttype: \"add\",\n\t\t\t\t\tcontent: op.line,\n\t\t\t\t\tnewLineNum: (op.newIdx ?? 0) + 1,\n\t\t\t\t});\n\t\t\t\tcurrentHunk.newCount++;\n\t\t\t} else if (op.type === \"remove\") {\n\t\t\t\tcurrentHunk.lines.push({\n\t\t\t\t\ttype: \"remove\",\n\t\t\t\t\tcontent: op.line,\n\t\t\t\t\toldLineNum: (op.oldIdx ?? 0) + 1,\n\t\t\t\t});\n\t\t\t\tcurrentHunk.oldCount++;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (currentHunk) {\n\t\thunks.push(currentHunk);\n\t}\n\n\t// Generate headers for hunks\n\tfor (const hunk of hunks) {\n\t\thunk.header = `@@ -${hunk.oldStart},${hunk.oldCount} +${hunk.newStart},${hunk.newCount} @@`;\n\t}\n\n\treturn hunks;\n}\n\n/**\n * Diff preview manager\n */\nclass DiffPreviewManager {\n\tprivate pendingPreviews = new Map<string, DiffPreviewResult>();\n\n\t/**\n\t * Create a diff preview for an edit\n\t */\n\tasync createPreview(config: PreviewConfig): Promise<DiffPreviewResult> {\n\t\tconst { filePath, newContent, contextLines = 3 } = config;\n\t\tlet originalContent = config.originalContent;\n\n\t\t// Read original content if not provided\n\t\tif (originalContent === undefined) {\n\t\t\tif (existsSync(filePath)) {\n\t\t\t\toriginalContent = readFileSync(filePath, \"utf-8\");\n\t\t\t} else {\n\t\t\t\toriginalContent = \"\";\n\t\t\t}\n\t\t}\n\n\t\tconst isNewFile = originalContent === \"\";\n\t\tconst isDeleted = newContent === \"\";\n\n\t\tconst oldLines = originalContent.split(\"\\n\");\n\t\tconst newLines = newContent.split(\"\\n\");\n\n\t\tconst hunks = generateDiff(oldLines, newLines, contextLines);\n\n\t\t// Count additions and deletions\n\t\tlet additions = 0;\n\t\tlet deletions = 0;\n\t\tfor (const hunk of hunks) {\n\t\t\tfor (const line of hunk.lines) {\n\t\t\t\tif (line.type === \"add\") additions++;\n\t\t\t\tif (line.type === \"remove\") deletions++;\n\t\t\t}\n\t\t}\n\n\t\tconst preview: DiffPreviewResult = {\n\t\t\tfilePath,\n\t\t\tfileName: basename(filePath),\n\t\t\thunks,\n\t\t\tadditions,\n\t\t\tdeletions,\n\t\t\tisNewFile,\n\t\t\tisDeleted,\n\t\t\toriginalContent,\n\t\t\tnewContent,\n\t\t};\n\n\t\t// Store for later application\n\t\tthis.pendingPreviews.set(filePath, preview);\n\n\t\tlogger.debug(\"Diff preview created\", {\n\t\t\tfilePath,\n\t\t\thunks: hunks.length,\n\t\t\tadditions,\n\t\t\tdeletions,\n\t\t});\n\n\t\treturn preview;\n\t}\n\n\t/**\n\t * Format diff as unified diff string\n\t */\n\tformatUnified(preview: DiffPreviewResult): string {\n\t\tconst lines: string[] = [\n\t\t\t`--- a/${preview.fileName}`,\n\t\t\t`+++ b/${preview.fileName}`,\n\t\t];\n\n\t\tfor (const hunk of preview.hunks) {\n\t\t\tlines.push(hunk.header);\n\t\t\tfor (const line of hunk.lines) {\n\t\t\t\tswitch (line.type) {\n\t\t\t\t\tcase \"context\":\n\t\t\t\t\t\tlines.push(` ${line.content}`);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"add\":\n\t\t\t\t\t\tlines.push(`+${line.content}`);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"remove\":\n\t\t\t\t\t\tlines.push(`-${line.content}`);\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn lines.join(\"\\n\");\n\t}\n\n\t/**\n\t * Format diff with color codes for terminal\n\t */\n\tformatColored(preview: DiffPreviewResult): string {\n\t\tconst RED = \"\\x1b[31m\";\n\t\tconst GREEN = \"\\x1b[32m\";\n\t\tconst CYAN = \"\\x1b[36m\";\n\t\tconst RESET = \"\\x1b[0m\";\n\t\tconst DIM = \"\\x1b[2m\";\n\n\t\tconst lines: string[] = [\n\t\t\t`${DIM}--- a/${preview.fileName}${RESET}`,\n\t\t\t`${DIM}+++ b/${preview.fileName}${RESET}`,\n\t\t];\n\n\t\tfor (const hunk of preview.hunks) {\n\t\t\tlines.push(`${CYAN}${hunk.header}${RESET}`);\n\t\t\tfor (const line of hunk.lines) {\n\t\t\t\tswitch (line.type) {\n\t\t\t\t\tcase \"context\":\n\t\t\t\t\t\tlines.push(`${DIM} ${line.content}${RESET}`);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"add\":\n\t\t\t\t\t\tlines.push(`${GREEN}+${line.content}${RESET}`);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"remove\":\n\t\t\t\t\t\tlines.push(`${RED}-${line.content}${RESET}`);\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn lines.join(\"\\n\");\n\t}\n\n\t/**\n\t * Format diff as side-by-side comparison\n\t */\n\tformatSideBySide(preview: DiffPreviewResult, width = 80): string {\n\t\tconst halfWidth = Math.floor(width / 2) - 3;\n\t\tconst lines: string[] = [];\n\n\t\t// Header\n\t\tconst leftHeader = `Old (${preview.deletions} deletions)`.padEnd(halfWidth);\n\t\tconst rightHeader = `New (${preview.additions} additions)`.padEnd(\n\t\t\thalfWidth,\n\t\t);\n\t\tlines.push(`${leftHeader} │ ${rightHeader}`);\n\t\tlines.push(`${\"─\".repeat(halfWidth)}─┼─${\"─\".repeat(halfWidth)}`);\n\n\t\tfor (const hunk of preview.hunks) {\n\t\t\tconst oldLines: Array<{ num: number; content: string }> = [];\n\t\t\tconst newLines: Array<{ num: number; content: string }> = [];\n\n\t\t\tfor (const line of hunk.lines) {\n\t\t\t\tif (line.type === \"context\") {\n\t\t\t\t\toldLines.push({ num: line.oldLineNum!, content: line.content });\n\t\t\t\t\tnewLines.push({ num: line.newLineNum!, content: line.content });\n\t\t\t\t} else if (line.type === \"remove\") {\n\t\t\t\t\toldLines.push({ num: line.oldLineNum!, content: line.content });\n\t\t\t\t} else if (line.type === \"add\") {\n\t\t\t\t\tnewLines.push({ num: line.newLineNum!, content: line.content });\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Pad to same length\n\t\t\tconst maxLen = Math.max(oldLines.length, newLines.length);\n\t\t\twhile (oldLines.length < maxLen) oldLines.push({ num: 0, content: \"\" });\n\t\t\twhile (newLines.length < maxLen) newLines.push({ num: 0, content: \"\" });\n\n\t\t\tfor (let i = 0; i < maxLen; i++) {\n\t\t\t\tconst oldLine = oldLines[i]!;\n\t\t\t\tconst newLine = newLines[i]!;\n\n\t\t\t\tconst leftNum = oldLine.num ? String(oldLine.num).padStart(4) : \" \";\n\t\t\t\tconst rightNum = newLine.num ? String(newLine.num).padStart(4) : \" \";\n\n\t\t\t\tconst leftContent = oldLine.content\n\t\t\t\t\t.slice(0, halfWidth - 6)\n\t\t\t\t\t.padEnd(halfWidth - 5);\n\t\t\t\tconst rightContent = newLine.content\n\t\t\t\t\t.slice(0, halfWidth - 6)\n\t\t\t\t\t.padEnd(halfWidth - 5);\n\n\t\t\t\tlines.push(`${leftNum} ${leftContent} │ ${rightNum} ${rightContent}`);\n\t\t\t}\n\n\t\t\tlines.push(`${\"─\".repeat(halfWidth)}─┼─${\"─\".repeat(halfWidth)}`);\n\t\t}\n\n\t\treturn lines.join(\"\\n\");\n\t}\n\n\t/**\n\t * Get pending preview for a file\n\t */\n\tgetPendingPreview(filePath: string): DiffPreviewResult | undefined {\n\t\treturn this.pendingPreviews.get(filePath);\n\t}\n\n\t/**\n\t * Clear pending preview for a file\n\t */\n\tclearPreview(filePath: string): void {\n\t\tthis.pendingPreviews.delete(filePath);\n\t}\n\n\t/**\n\t * Clear all pending previews\n\t */\n\tclearAllPreviews(): void {\n\t\tthis.pendingPreviews.clear();\n\t}\n\n\t/**\n\t * Get summary of all pending previews\n\t */\n\tgetSummary(): {\n\t\ttotalFiles: number;\n\t\ttotalAdditions: number;\n\t\ttotalDeletions: number;\n\t\tfiles: Array<{ path: string; additions: number; deletions: number }>;\n\t} {\n\t\tlet totalAdditions = 0;\n\t\tlet totalDeletions = 0;\n\t\tconst files: Array<{ path: string; additions: number; deletions: number }> =\n\t\t\t[];\n\n\t\tfor (const [path, preview] of Array.from(this.pendingPreviews)) {\n\t\t\ttotalAdditions += preview.additions;\n\t\t\ttotalDeletions += preview.deletions;\n\t\t\tfiles.push({\n\t\t\t\tpath,\n\t\t\t\tadditions: preview.additions,\n\t\t\t\tdeletions: preview.deletions,\n\t\t\t});\n\t\t}\n\n\t\treturn {\n\t\t\ttotalFiles: this.pendingPreviews.size,\n\t\t\ttotalAdditions,\n\t\t\ttotalDeletions,\n\t\t\tfiles,\n\t\t};\n\t}\n\n\t/**\n\t * Apply specific hunks from a preview\n\t */\n\tapplyHunks(preview: DiffPreviewResult, hunkIndices: number[]): string {\n\t\tconst oldLines = preview.originalContent.split(\"\\n\");\n\t\tconst result = [...oldLines];\n\t\tlet offset = 0;\n\n\t\t// Sort hunks by start position\n\t\tconst sortedIndices = [...hunkIndices].sort((a, b) => {\n\t\t\tconst hunkA = preview.hunks[a];\n\t\t\tconst hunkB = preview.hunks[b];\n\t\t\treturn (hunkA?.oldStart || 0) - (hunkB?.oldStart || 0);\n\t\t});\n\n\t\tfor (const hunkIdx of sortedIndices) {\n\t\t\tconst hunk = preview.hunks[hunkIdx];\n\t\t\tif (!hunk) continue;\n\n\t\t\tconst startIdx = hunk.oldStart - 1 + offset;\n\t\t\tlet removeCount = 0;\n\t\t\tconst addLines: string[] = [];\n\n\t\t\tfor (const line of hunk.lines) {\n\t\t\t\tif (line.type === \"remove\") {\n\t\t\t\t\tremoveCount++;\n\t\t\t\t} else if (line.type === \"add\") {\n\t\t\t\t\taddLines.push(line.content);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tresult.splice(startIdx, removeCount, ...addLines);\n\t\t\toffset += addLines.length - removeCount;\n\t\t}\n\n\t\treturn result.join(\"\\n\");\n\t}\n}\n\n/**\n * Global diff preview manager instance\n */\nexport const diffPreview = new DiffPreviewManager();\n\n/**\n * Quick function to preview an edit\n */\nexport async function previewEdit(\n\tfilePath: string,\n\tnewContent: string,\n): Promise<string> {\n\tconst preview = await diffPreview.createPreview({ filePath, newContent });\n\treturn diffPreview.formatColored(preview);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"diff-preview.js","sourceRoot":"","sources":["../../src/tools/diff-preview.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Diff Preview\n *\n * Shows a preview of changes before applying them, similar to Cursor's\n * diff view. Enables users to review and approve changes before they're\n * written to disk.\n *\n * ## Features\n *\n * - Generate unified diffs from edits\n * - Side-by-side comparison view\n * - Hunk-level approval/rejection\n * - Syntax highlighting support\n * - Integration with undo system\n *\n * ## Usage\n *\n * ```typescript\n * import { diffPreview } from \"./diff-preview.js\";\n *\n * // Create preview for an edit\n * const preview = await diffPreview.createPreview({\n * filePath: \"src/main.ts\",\n * originalContent: \"...\",\n * newContent: \"...\",\n * });\n *\n * // Format for display\n * const formatted = diffPreview.formatUnified(preview);\n * ```\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { basename } from \"node:path\";\nimport { createLogger } from \"../utils/logger.js\";\n\nconst logger = createLogger(\"tools:diff-preview\");\n\n/**\n * A single line in a diff\n */\nexport interface DiffLine {\n\ttype: \"context\" | \"add\" | \"remove\" | \"header\";\n\tcontent: string;\n\toldLineNum?: number;\n\tnewLineNum?: number;\n}\n\n/**\n * A hunk in a diff\n */\nexport interface DiffHunk {\n\toldStart: number;\n\toldCount: number;\n\tnewStart: number;\n\tnewCount: number;\n\tlines: DiffLine[];\n\theader: string;\n}\n\n/**\n * Complete diff preview\n */\nexport interface DiffPreviewResult {\n\tfilePath: string;\n\tfileName: string;\n\thunks: DiffHunk[];\n\tadditions: number;\n\tdeletions: number;\n\tisNewFile: boolean;\n\tisDeleted: boolean;\n\toriginalContent: string;\n\tnewContent: string;\n}\n\n/**\n * Preview configuration\n */\nexport interface PreviewConfig {\n\tfilePath: string;\n\toriginalContent?: string;\n\tnewContent: string;\n\tcontextLines?: number;\n}\n\n/**\n * Apply mode for changes\n */\nexport type ApplyMode = \"all\" | \"hunks\" | \"lines\";\n\n/**\n * Compute longest common subsequence for diff algorithm\n */\nfunction computeLCS(a: string[], b: string[]): number[][] {\n\tconst m = a.length;\n\tconst n = b.length;\n\tconst dp: number[][] = Array(m + 1)\n\t\t.fill(null)\n\t\t.map(() => Array(n + 1).fill(0));\n\n\tfor (let i = 1; i <= m; i++) {\n\t\tfor (let j = 1; j <= n; j++) {\n\t\t\tif (a[i - 1] === b[j - 1]) {\n\t\t\t\tdp[i]![j] = (dp[i - 1]?.[j - 1] || 0) + 1;\n\t\t\t} else {\n\t\t\t\tdp[i]![j] = Math.max(dp[i - 1]?.[j] || 0, dp[i]?.[j - 1] || 0);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn dp;\n}\n\n/**\n * Generate diff between two arrays of lines\n */\nfunction generateDiff(\n\toldLines: string[],\n\tnewLines: string[],\n\tcontextLines = 3,\n): DiffHunk[] {\n\tconst dp = computeLCS(oldLines, newLines);\n\tconst operations: Array<{\n\t\ttype: \"keep\" | \"add\" | \"remove\";\n\t\tline: string;\n\t\toldIdx?: number;\n\t\tnewIdx?: number;\n\t}> = [];\n\n\t// Backtrack to find the diff\n\tlet i = oldLines.length;\n\tlet j = newLines.length;\n\n\twhile (i > 0 || j > 0) {\n\t\tif (i > 0 && j > 0 && oldLines[i - 1] === newLines[j - 1]) {\n\t\t\toperations.unshift({\n\t\t\t\ttype: \"keep\",\n\t\t\t\tline: oldLines[i - 1]!,\n\t\t\t\toldIdx: i - 1,\n\t\t\t\tnewIdx: j - 1,\n\t\t\t});\n\t\t\ti--;\n\t\t\tj--;\n\t\t} else if (\n\t\t\tj > 0 &&\n\t\t\t(i === 0 || (dp[i]?.[j - 1] || 0) >= (dp[i - 1]?.[j] || 0))\n\t\t) {\n\t\t\toperations.unshift({\n\t\t\t\ttype: \"add\",\n\t\t\t\tline: newLines[j - 1]!,\n\t\t\t\tnewIdx: j - 1,\n\t\t\t});\n\t\t\tj--;\n\t\t} else {\n\t\t\toperations.unshift({\n\t\t\t\ttype: \"remove\",\n\t\t\t\tline: oldLines[i - 1]!,\n\t\t\t\toldIdx: i - 1,\n\t\t\t});\n\t\t\ti--;\n\t\t}\n\t}\n\n\t// Convert operations to hunks\n\tconst hunks: DiffHunk[] = [];\n\tlet currentHunk: DiffHunk | null = null;\n\tlet lastChangeIdx = Number.NEGATIVE_INFINITY;\n\n\tfor (let opIdx = 0; opIdx < operations.length; opIdx++) {\n\t\tconst op = operations[opIdx]!;\n\t\tconst isChange = op.type !== \"keep\";\n\n\t\tif (isChange) {\n\t\t\t// Start a new hunk or extend the current one\n\t\t\tif (!currentHunk || opIdx - lastChangeIdx > contextLines * 2) {\n\t\t\t\t// Start new hunk\n\t\t\t\tif (currentHunk) {\n\t\t\t\t\thunks.push(currentHunk);\n\t\t\t\t}\n\n\t\t\t\tconst startIdx = Math.max(0, opIdx - contextLines);\n\t\t\t\tcurrentHunk = {\n\t\t\t\t\toldStart: (operations[startIdx]?.oldIdx ?? 0) + 1,\n\t\t\t\t\toldCount: 0,\n\t\t\t\t\tnewStart: (operations[startIdx]?.newIdx ?? 0) + 1,\n\t\t\t\t\tnewCount: 0,\n\t\t\t\t\tlines: [],\n\t\t\t\t\theader: \"\",\n\t\t\t\t};\n\n\t\t\t\t// Add leading context\n\t\t\t\tfor (let ctx = startIdx; ctx < opIdx; ctx++) {\n\t\t\t\t\tconst ctxOp = operations[ctx];\n\t\t\t\t\tif (ctxOp && ctxOp.type === \"keep\") {\n\t\t\t\t\t\tcurrentHunk.lines.push({\n\t\t\t\t\t\t\ttype: \"context\",\n\t\t\t\t\t\t\tcontent: ctxOp.line,\n\t\t\t\t\t\t\toldLineNum: (ctxOp.oldIdx ?? 0) + 1,\n\t\t\t\t\t\t\tnewLineNum: (ctxOp.newIdx ?? 0) + 1,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tcurrentHunk.oldCount++;\n\t\t\t\t\t\tcurrentHunk.newCount++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlastChangeIdx = opIdx;\n\t\t}\n\n\t\tif (currentHunk) {\n\t\t\tif (op.type === \"keep\") {\n\t\t\t\t// Check if we should add trailing context\n\t\t\t\tif (opIdx - lastChangeIdx <= contextLines) {\n\t\t\t\t\tcurrentHunk.lines.push({\n\t\t\t\t\t\ttype: \"context\",\n\t\t\t\t\t\tcontent: op.line,\n\t\t\t\t\t\toldLineNum: (op.oldIdx ?? 0) + 1,\n\t\t\t\t\t\tnewLineNum: (op.newIdx ?? 0) + 1,\n\t\t\t\t\t});\n\t\t\t\t\tcurrentHunk.oldCount++;\n\t\t\t\t\tcurrentHunk.newCount++;\n\t\t\t\t}\n\t\t\t} else if (op.type === \"add\") {\n\t\t\t\tcurrentHunk.lines.push({\n\t\t\t\t\ttype: \"add\",\n\t\t\t\t\tcontent: op.line,\n\t\t\t\t\tnewLineNum: (op.newIdx ?? 0) + 1,\n\t\t\t\t});\n\t\t\t\tcurrentHunk.newCount++;\n\t\t\t} else if (op.type === \"remove\") {\n\t\t\t\tcurrentHunk.lines.push({\n\t\t\t\t\ttype: \"remove\",\n\t\t\t\t\tcontent: op.line,\n\t\t\t\t\toldLineNum: (op.oldIdx ?? 0) + 1,\n\t\t\t\t});\n\t\t\t\tcurrentHunk.oldCount++;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (currentHunk) {\n\t\thunks.push(currentHunk);\n\t}\n\n\t// Generate headers for hunks\n\tfor (const hunk of hunks) {\n\t\thunk.header = `@@ -${hunk.oldStart},${hunk.oldCount} +${hunk.newStart},${hunk.newCount} @@`;\n\t}\n\n\treturn hunks;\n}\n\n/**\n * Diff preview manager\n */\nclass DiffPreviewManager {\n\tprivate pendingPreviews = new Map<string, DiffPreviewResult>();\n\n\t/**\n\t * Create a diff preview for an edit\n\t */\n\tasync createPreview(config: PreviewConfig): Promise<DiffPreviewResult> {\n\t\tconst { filePath, newContent, contextLines = 3 } = config;\n\t\tlet originalContent = config.originalContent;\n\n\t\t// Read original content if not provided\n\t\tif (originalContent === undefined) {\n\t\t\tif (existsSync(filePath)) {\n\t\t\t\toriginalContent = readFileSync(filePath, \"utf-8\");\n\t\t\t} else {\n\t\t\t\toriginalContent = \"\";\n\t\t\t}\n\t\t}\n\n\t\tconst isNewFile = originalContent === \"\";\n\t\tconst isDeleted = newContent === \"\";\n\n\t\tconst oldLines = originalContent.split(\"\\n\");\n\t\tconst newLines = newContent.split(\"\\n\");\n\n\t\tconst hunks = generateDiff(oldLines, newLines, contextLines);\n\n\t\t// Count additions and deletions\n\t\tlet additions = 0;\n\t\tlet deletions = 0;\n\t\tfor (const hunk of hunks) {\n\t\t\tfor (const line of hunk.lines) {\n\t\t\t\tif (line.type === \"add\") additions++;\n\t\t\t\tif (line.type === \"remove\") deletions++;\n\t\t\t}\n\t\t}\n\n\t\tconst preview: DiffPreviewResult = {\n\t\t\tfilePath,\n\t\t\tfileName: basename(filePath),\n\t\t\thunks,\n\t\t\tadditions,\n\t\t\tdeletions,\n\t\t\tisNewFile,\n\t\t\tisDeleted,\n\t\t\toriginalContent,\n\t\t\tnewContent,\n\t\t};\n\n\t\t// Store for later application\n\t\tthis.pendingPreviews.set(filePath, preview);\n\n\t\tlogger.debug(\"Diff preview created\", {\n\t\t\tfilePath,\n\t\t\thunks: hunks.length,\n\t\t\tadditions,\n\t\t\tdeletions,\n\t\t});\n\n\t\treturn preview;\n\t}\n\n\t/**\n\t * Format diff as unified diff string\n\t */\n\tformatUnified(preview: DiffPreviewResult): string {\n\t\tconst lines: string[] = [\n\t\t\t`--- a/${preview.fileName}`,\n\t\t\t`+++ b/${preview.fileName}`,\n\t\t];\n\n\t\tfor (const hunk of preview.hunks) {\n\t\t\tlines.push(hunk.header);\n\t\t\tfor (const line of hunk.lines) {\n\t\t\t\tswitch (line.type) {\n\t\t\t\t\tcase \"context\":\n\t\t\t\t\t\tlines.push(` ${line.content}`);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"add\":\n\t\t\t\t\t\tlines.push(`+${line.content}`);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"remove\":\n\t\t\t\t\t\tlines.push(`-${line.content}`);\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn lines.join(\"\\n\");\n\t}\n\n\t/**\n\t * Format diff with color codes for terminal\n\t */\n\tformatColored(preview: DiffPreviewResult): string {\n\t\tconst RED = \"\\x1b[31m\";\n\t\tconst GREEN = \"\\x1b[32m\";\n\t\tconst CYAN = \"\\x1b[36m\";\n\t\tconst RESET = \"\\x1b[0m\";\n\t\tconst DIM = \"\\x1b[2m\";\n\n\t\tconst lines: string[] = [\n\t\t\t`${DIM}--- a/${preview.fileName}${RESET}`,\n\t\t\t`${DIM}+++ b/${preview.fileName}${RESET}`,\n\t\t];\n\n\t\tfor (const hunk of preview.hunks) {\n\t\t\tlines.push(`${CYAN}${hunk.header}${RESET}`);\n\t\t\tfor (const line of hunk.lines) {\n\t\t\t\tswitch (line.type) {\n\t\t\t\t\tcase \"context\":\n\t\t\t\t\t\tlines.push(`${DIM} ${line.content}${RESET}`);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"add\":\n\t\t\t\t\t\tlines.push(`${GREEN}+${line.content}${RESET}`);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"remove\":\n\t\t\t\t\t\tlines.push(`${RED}-${line.content}${RESET}`);\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn lines.join(\"\\n\");\n\t}\n\n\t/**\n\t * Format diff as side-by-side comparison\n\t */\n\tformatSideBySide(preview: DiffPreviewResult, width = 80): string {\n\t\tconst halfWidth = Math.floor(width / 2) - 3;\n\t\tconst lines: string[] = [];\n\n\t\t// Header\n\t\tconst leftHeader = `Old (${preview.deletions} deletions)`.padEnd(halfWidth);\n\t\tconst rightHeader = `New (${preview.additions} additions)`.padEnd(\n\t\t\thalfWidth,\n\t\t);\n\t\tlines.push(`${leftHeader} │ ${rightHeader}`);\n\t\tlines.push(`${\"─\".repeat(halfWidth)}─┼─${\"─\".repeat(halfWidth)}`);\n\n\t\tfor (const hunk of preview.hunks) {\n\t\t\tconst oldLines: Array<{ num: number; content: string }> = [];\n\t\t\tconst newLines: Array<{ num: number; content: string }> = [];\n\n\t\t\tfor (const line of hunk.lines) {\n\t\t\t\tif (line.type === \"context\") {\n\t\t\t\t\toldLines.push({ num: line.oldLineNum!, content: line.content });\n\t\t\t\t\tnewLines.push({ num: line.newLineNum!, content: line.content });\n\t\t\t\t} else if (line.type === \"remove\") {\n\t\t\t\t\toldLines.push({ num: line.oldLineNum!, content: line.content });\n\t\t\t\t} else if (line.type === \"add\") {\n\t\t\t\t\tnewLines.push({ num: line.newLineNum!, content: line.content });\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Pad to same length\n\t\t\tconst maxLen = Math.max(oldLines.length, newLines.length);\n\t\t\twhile (oldLines.length < maxLen) oldLines.push({ num: 0, content: \"\" });\n\t\t\twhile (newLines.length < maxLen) newLines.push({ num: 0, content: \"\" });\n\n\t\t\tfor (let i = 0; i < maxLen; i++) {\n\t\t\t\tconst oldLine = oldLines[i]!;\n\t\t\t\tconst newLine = newLines[i]!;\n\n\t\t\t\tconst leftNum = oldLine.num ? String(oldLine.num).padStart(4) : \" \";\n\t\t\t\tconst rightNum = newLine.num ? String(newLine.num).padStart(4) : \" \";\n\n\t\t\t\tconst leftContent = oldLine.content\n\t\t\t\t\t.slice(0, halfWidth - 6)\n\t\t\t\t\t.padEnd(halfWidth - 5);\n\t\t\t\tconst rightContent = newLine.content\n\t\t\t\t\t.slice(0, halfWidth - 6)\n\t\t\t\t\t.padEnd(halfWidth - 5);\n\n\t\t\t\tlines.push(`${leftNum} ${leftContent} │ ${rightNum} ${rightContent}`);\n\t\t\t}\n\n\t\t\tlines.push(`${\"─\".repeat(halfWidth)}─┼─${\"─\".repeat(halfWidth)}`);\n\t\t}\n\n\t\treturn lines.join(\"\\n\");\n\t}\n\n\t/**\n\t * Get pending preview for a file\n\t */\n\tgetPendingPreview(filePath: string): DiffPreviewResult | undefined {\n\t\treturn this.pendingPreviews.get(filePath);\n\t}\n\n\t/**\n\t * Clear pending preview for a file\n\t */\n\tclearPreview(filePath: string): void {\n\t\tthis.pendingPreviews.delete(filePath);\n\t}\n\n\t/**\n\t * Clear all pending previews\n\t */\n\tclearAllPreviews(): void {\n\t\tthis.pendingPreviews.clear();\n\t}\n\n\t/**\n\t * Get summary of all pending previews\n\t */\n\tgetSummary(): {\n\t\ttotalFiles: number;\n\t\ttotalAdditions: number;\n\t\ttotalDeletions: number;\n\t\tfiles: Array<{ path: string; additions: number; deletions: number }>;\n\t} {\n\t\tlet totalAdditions = 0;\n\t\tlet totalDeletions = 0;\n\t\tconst files: Array<{ path: string; additions: number; deletions: number }> =\n\t\t\t[];\n\n\t\tfor (const [path, preview] of Array.from(this.pendingPreviews)) {\n\t\t\ttotalAdditions += preview.additions;\n\t\t\ttotalDeletions += preview.deletions;\n\t\t\tfiles.push({\n\t\t\t\tpath,\n\t\t\t\tadditions: preview.additions,\n\t\t\t\tdeletions: preview.deletions,\n\t\t\t});\n\t\t}\n\n\t\treturn {\n\t\t\ttotalFiles: this.pendingPreviews.size,\n\t\t\ttotalAdditions,\n\t\t\ttotalDeletions,\n\t\t\tfiles,\n\t\t};\n\t}\n\n\t/**\n\t * Apply specific hunks from a preview\n\t */\n\tapplyHunks(preview: DiffPreviewResult, hunkIndices: number[]): string {\n\t\tconst oldLines = preview.originalContent.split(\"\\n\");\n\t\tconst result = [...oldLines];\n\t\tlet offset = 0;\n\n\t\t// Sort hunks by start position\n\t\tconst sortedIndices = [...hunkIndices].sort((a, b) => {\n\t\t\tconst hunkA = preview.hunks[a];\n\t\t\tconst hunkB = preview.hunks[b];\n\t\t\treturn (hunkA?.oldStart || 0) - (hunkB?.oldStart || 0);\n\t\t});\n\n\t\tfor (const hunkIdx of sortedIndices) {\n\t\t\tconst hunk = preview.hunks[hunkIdx];\n\t\t\tif (!hunk) continue;\n\n\t\t\tlet removeCount = 0;\n\t\t\tlet leadingContext = 0;\n\t\t\tlet seenRemove = false;\n\t\t\tconst addLines: string[] = [];\n\n\t\t\tfor (const line of hunk.lines) {\n\t\t\t\tif (line.type === \"remove\") {\n\t\t\t\t\tremoveCount++;\n\t\t\t\t\tseenRemove = true;\n\t\t\t\t} else if (line.type === \"add\") {\n\t\t\t\t\taddLines.push(line.content);\n\t\t\t\t\tseenRemove = true;\n\t\t\t\t} else if (line.type === \"context\" && !seenRemove) {\n\t\t\t\t\t// oldStart points at the hunk's first line, which may be leading\n\t\t\t\t\t// context — skip past it so the splice lands on the first removal.\n\t\t\t\t\tleadingContext++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst startIdx = hunk.oldStart - 1 + leadingContext + offset;\n\t\t\tresult.splice(startIdx, removeCount, ...addLines);\n\t\t\toffset += addLines.length - removeCount;\n\t\t}\n\n\t\treturn result.join(\"\\n\");\n\t}\n}\n\n/**\n * Global diff preview manager instance\n */\nexport const diffPreview = new DiffPreviewManager();\n\n/**\n * Quick function to preview an edit\n */\nexport async function previewEdit(\n\tfilePath: string,\n\tnewContent: string,\n): Promise<string> {\n\tconst preview = await diffPreview.createPreview({ filePath, newContent });\n\treturn diffPreview.formatColored(preview);\n}\n"]}
|
package/dist/tools/edit.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"edit.d.ts","sourceRoot":"","sources":["../../src/tools/edit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;
|
|
1
|
+
{"version":3,"file":"edit.d.ts","sourceRoot":"","sources":["../../src/tools/edit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAeH,OAAO,EACN,KAAK,0BAA0B,EAG/B,MAAM,6BAA6B,CAAC;AAMrC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAwHjE,KAAK,eAAe,GAAG;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAClC,eAAe,CAAC,EAAE,0BAA0B,CAAC;IAC7C,IAAI,CAAC,EAAE,SAAS,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgTnB,CAAC"}
|
package/dist/tools/edit.js
CHANGED
|
@@ -40,6 +40,7 @@ import { constants } from "node:fs";
|
|
|
40
40
|
import { access, readFile, rename, unlink, writeFile } from "node:fs/promises";
|
|
41
41
|
import { resolve as resolvePath } from "node:path";
|
|
42
42
|
import { Type } from "@sinclair/typebox";
|
|
43
|
+
import { detectMissionSessionRole, validateMissionArtifactWrite, } from "../agent/mission-artifacts.js";
|
|
43
44
|
import { captureDiagnosticBaseline, collectDiagnosticDelta, } from "../lsp/diagnostic-deltas.js";
|
|
44
45
|
import { buildDiagnosticDeltaToolSummary, formatDiagnosticDeltaForToolOutput, } from "../lsp/diagnostic-repair.js";
|
|
45
46
|
import { assertTeamMemoryContentSafe } from "../memory/team-memory.js";
|
|
@@ -252,6 +253,14 @@ If "not found", read file to check actual content.`,
|
|
|
252
253
|
const { newContent: normalizedNewContent, replacementCount } = applyEdits(document.normalized);
|
|
253
254
|
const newContent = restoreDocumentContent(normalizedNewContent, document);
|
|
254
255
|
assertTeamMemoryContentSafe(absolutePath, newContent);
|
|
256
|
+
const missionArtifactWrite = validateMissionArtifactWrite({
|
|
257
|
+
filePath: absolutePath,
|
|
258
|
+
content: newContent,
|
|
259
|
+
role: detectMissionSessionRole(),
|
|
260
|
+
});
|
|
261
|
+
if (!missionArtifactWrite.ok) {
|
|
262
|
+
return respond.error(missionArtifactWrite.message);
|
|
263
|
+
}
|
|
255
264
|
const diff = generateDiffString(originalContent, newContent);
|
|
256
265
|
if (!dryRun) {
|
|
257
266
|
await sandbox.writeFile(path, newContent);
|
|
@@ -286,6 +295,14 @@ If "not found", read file to check actual content.`,
|
|
|
286
295
|
const { newContent: normalizedNewContent, replacementCount } = applyEdits(document.normalized);
|
|
287
296
|
const newContent = restoreDocumentContent(normalizedNewContent, document);
|
|
288
297
|
assertTeamMemoryContentSafe(absolutePath, newContent);
|
|
298
|
+
const missionArtifactWrite = validateMissionArtifactWrite({
|
|
299
|
+
filePath: absolutePath,
|
|
300
|
+
content: newContent,
|
|
301
|
+
role: detectMissionSessionRole(),
|
|
302
|
+
});
|
|
303
|
+
if (!missionArtifactWrite.ok) {
|
|
304
|
+
return respond.error(missionArtifactWrite.message);
|
|
305
|
+
}
|
|
289
306
|
const diff = generateDiffString(originalContent, newContent);
|
|
290
307
|
if (dryRun) {
|
|
291
308
|
const modeDesc = hasMultiEdit
|
package/dist/tools/edit.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"edit.js","sourceRoot":"","sources":["../../src/tools/edit.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Edit Tool - Find-and-replace text editing with fuzzy matching fallback\n *\n * This module implements a robust text editing tool that performs exact string\n * replacement with intelligent fallback to approximate matching when exact matches\n * fail. The core design philosophy is \"fail helpfully\" - when the user's search\n * text doesn't match exactly (due to whitespace differences, typos, or outdated\n * content), we provide actionable suggestions pointing to the closest matches.\n *\n * ## Architecture Overview\n *\n * 1. **Exact Matching (Primary Path)**\n * - Simple string indexOf search for O(n) performance\n * - Handles single edit, multi-edit (sequential), and replace-all modes\n * - Reports all match locations with line numbers for disambiguation\n *\n * 2. **Approximate Matching (Fallback Path)**\n * - Triggered only when exact match fails\n * - Uses two complementary strategies:\n * a) Regex-based relaxed matching (whitespace normalization)\n * b) Line-by-line Levenshtein similarity scoring\n * - Results sorted by similarity score, filtered by threshold\n *\n * 3. **Similarity Scoring**\n * - Levenshtein distance normalized to 0-1 similarity ratio\n * - Dual thresholds: 50% for single candidates, 60% for multiple\n * - Prevents noise while surfacing genuinely close matches\n *\n * ## Key Design Decisions\n *\n * - **Atomic writes**: Uses temp file + rename for crash safety\n * - **Multi-edit mode**: Applies edits sequentially for deterministic results\n * - **LSP integration**: Collects diagnostics after edits for immediate feedback\n * - **Sandbox support**: Operates through sandbox abstraction when available\n *\n * @module tools/edit\n */\n\nimport crypto from \"node:crypto\";\nimport { constants } from \"node:fs\";\nimport { access, readFile, rename, unlink, writeFile } from \"node:fs/promises\";\nimport { resolve as resolvePath } from \"node:path\";\nimport { Type } from \"@sinclair/typebox\";\nimport {\n\tcaptureDiagnosticBaseline,\n\tcollectDiagnosticDelta,\n} from \"../lsp/diagnostic-deltas.js\";\nimport {\n\ttype DiagnosticDeltaToolSummary,\n\tbuildDiagnosticDeltaToolSummary,\n\tformatDiagnosticDeltaForToolOutput,\n} from \"../lsp/diagnostic-repair.js\";\nimport { assertTeamMemoryContentSafe } from \"../memory/team-memory.js\";\nimport {\n\trequirePlanCheck,\n\trunValidatorsOnSuccess,\n} from \"../safety/safe-mode.js\";\nimport type { ValidatorRunResult } from \"../safety/safe-mode.js\";\nimport { formatLspDiagnostics, generateDiffString } from \"./diff-utils.js\";\nimport { createTool, expandUserPath } from \"./tool-dsl.js\";\n\nasync function writeFileAtomically(\n\tfilePath: string,\n\tcontents: string,\n): Promise<void> {\n\tconst tempPath = `${filePath}.${crypto.randomUUID()}.tmp`;\n\tawait writeFile(tempPath, contents, \"utf-8\");\n\ttry {\n\t\tawait rename(tempPath, filePath);\n\t} catch (error) {\n\t\tawait unlink(tempPath).catch(() => {});\n\t\tthrow error;\n\t}\n}\n\n/** Diff support lives in diff-utils for reuse */\n\ntype LineEnding = \"\\n\" | \"\\r\\n\" | \"\\r\";\n\ntype NormalizedDocument = {\n\toriginal: string;\n\tnormalized: string;\n\tbom: string;\n\tlineEnding: LineEnding;\n};\n\nfunction detectLineEnding(text: string): LineEnding {\n\tif (text.includes(\"\\r\\n\")) return \"\\r\\n\";\n\tif (text.includes(\"\\r\")) return \"\\r\";\n\treturn \"\\n\";\n}\n\nfunction normalizeDocument(content: string): NormalizedDocument {\n\tconst bom = content.startsWith(\"\\uFEFF\") ? \"\\uFEFF\" : \"\";\n\tconst withoutBom = bom ? content.slice(1) : content;\n\tconst lineEnding = detectLineEnding(withoutBom);\n\tconst normalized = withoutBom.replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\");\n\treturn { original: content, normalized, bom, lineEnding };\n}\n\nfunction normalizeEditText(text: string | undefined): string | undefined {\n\tif (text === undefined) return undefined;\n\treturn text.replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\");\n}\n\nfunction restoreDocumentContent(\n\tnormalized: string,\n\tdocument: NormalizedDocument,\n): string {\n\tconst restored =\n\t\tdocument.lineEnding === \"\\n\"\n\t\t\t? normalized\n\t\t\t: normalized.replace(/\\n/g, document.lineEnding);\n\treturn `${document.bom}${restored}`;\n}\n\nconst editOperationSchema = Type.Object({\n\toldText: Type.String({\n\t\tdescription: \"Exact text to find and replace\",\n\t\tminLength: 1,\n\t}),\n\tnewText: Type.Optional(\n\t\tType.String({\n\t\t\tdescription: \"Replacement text (omit or empty string to delete)\",\n\t\t\tdefault: \"\",\n\t\t}),\n\t),\n});\n\nconst editSchema = Type.Object({\n\tpath: Type.String({\n\t\tdescription: \"Path to the file to edit (relative or absolute)\",\n\t\tminLength: 1,\n\t}),\n\toldText: Type.Optional(\n\t\tType.String({\n\t\t\tdescription: \"Exact text to find and replace (must match exactly)\",\n\t\t\tminLength: 1,\n\t\t}),\n\t),\n\tnewText: Type.Optional(\n\t\tType.String({\n\t\t\tdescription: \"New text to replace the old text with\",\n\t\t\tdefault: \"\",\n\t\t}),\n\t),\n\tedits: Type.Optional(\n\t\tType.Array(editOperationSchema, {\n\t\t\tdescription:\n\t\t\t\t\"Multiple edits to apply sequentially (alternative to oldText/newText)\",\n\t\t\tminItems: 1,\n\t\t\tmaxItems: 50,\n\t\t}),\n\t),\n\treplaceAll: Type.Optional(\n\t\tType.Boolean({\n\t\t\tdescription:\n\t\t\t\t\"Replace all occurrences (useful for variable renaming). Cannot be used with occurrence or edits.\",\n\t\t\tdefault: false,\n\t\t}),\n\t),\n\toccurrence: Type.Optional(\n\t\tType.Integer({\n\t\t\tdescription:\n\t\t\t\t\"Which occurrence of the text to replace (1-based). Cannot be used with replaceAll or edits.\",\n\t\t\tminimum: 1,\n\t\t\tdefault: 1,\n\t\t}),\n\t),\n\tdryRun: Type.Optional(\n\t\tType.Boolean({\n\t\t\tdescription: \"Preview the diff without writing changes\",\n\t\t\tdefault: false,\n\t\t}),\n\t),\n});\n\ntype EditToolDetails = {\n\tdiff: string;\n\teditsApplied?: number;\n\tvalidators?: ValidatorRunResult[];\n\tdiagnosticDelta?: DiagnosticDeltaToolSummary;\n\tmode?: \"sandbox\";\n};\n\nexport const editTool = createTool<typeof editSchema, EditToolDetails>({\n\tname: \"edit\",\n\tlabel: \"edit\",\n\tdescription: `Edit files with find-and-replace. oldText must match exactly (whitespace, indentation, newlines).\n\nParameters:\n- path: File path\n- oldText/newText: Single edit (text to find and replacement)\n- edits: Array of {oldText, newText} for multiple sequential edits (1-50)\n- replaceAll: Replace all occurrences (default: false). For single edit only.\n- occurrence: Which match (default: 1). For single edit only.\n- dryRun: Preview only (default: false)\n\nUse either oldText/newText OR edits array, not both.\n\nBest practices:\n- Read file first to verify exact formatting\n- Include context (5-10 lines) for uniqueness\n- Match indentation style (tabs vs spaces)\n- Use dryRun for complex edits\n- Use edits array for multiple related changes (atomic)\n\nIf \"not found\", read file to check actual content.`,\n\tschema: editSchema,\n\tasync run(\n\t\t{\n\t\t\tpath,\n\t\t\toldText,\n\t\t\tnewText,\n\t\t\tedits,\n\t\t\treplaceAll = false,\n\t\t\toccurrence = 1,\n\t\t\tdryRun = false,\n\t\t},\n\t\t{ signal, respond, sandbox },\n\t) {\n\t\trequirePlanCheck(\"edit\");\n\n\t\tconst absolutePath = resolvePath(expandUserPath(path));\n\t\tconst throwIfAborted = () => {\n\t\t\tif (signal?.aborted) {\n\t\t\t\tthrow new Error(\"Operation aborted\");\n\t\t\t}\n\t\t};\n\n\t\t// Validate mutually exclusive parameters\n\t\tconst hasSingleEdit = oldText !== undefined;\n\t\t// newText with non-empty value alongside edits array is an error\n\t\t// (empty string is allowed as it's the default and harmless)\n\t\tconst hasExplicitNewText = newText !== undefined && newText !== \"\";\n\t\tconst hasMultiEdit = edits !== undefined && edits.length > 0;\n\n\t\tif ((hasSingleEdit || hasExplicitNewText) && hasMultiEdit) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Cannot use both oldText/newText and edits array. Use one or the other.\",\n\t\t\t);\n\t\t}\n\n\t\tif (!hasSingleEdit && !hasMultiEdit) {\n\t\t\tthrow new Error(\"Must provide either oldText/newText or edits array.\");\n\t\t}\n\n\t\tif (hasMultiEdit && (replaceAll || occurrence !== 1)) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Cannot use replaceAll or occurrence with edits array. These options only apply to single edits.\",\n\t\t\t);\n\t\t}\n\n\t\tif (replaceAll && occurrence !== 1) {\n\t\t\tthrow new Error(\"Cannot use both replaceAll and occurrence.\");\n\t\t}\n\n\t\tconst normalizedOldText = normalizeEditText(oldText);\n\t\tconst normalizedNewText = normalizeEditText(newText);\n\t\tconst normalizedEdits = edits?.map((edit) => ({\n\t\t\t...edit,\n\t\t\toldText: normalizeEditText(edit.oldText) ?? \"\",\n\t\t\tnewText: normalizeEditText(edit.newText),\n\t\t}));\n\n\t\t// Helper to apply edits to content (shared between sandbox and normal mode)\n\t\tconst applyEdits = (\n\t\t\toriginalContent: string,\n\t\t): { newContent: string; replacementCount: number } => {\n\t\t\tif (hasMultiEdit && normalizedEdits) {\n\t\t\t\tlet content = originalContent;\n\t\t\t\tlet editsApplied = 0;\n\t\t\t\tfor (const [index, edit] of normalizedEdits.entries()) {\n\t\t\t\t\tconst matches = findExactMatches(content, edit.oldText);\n\t\t\t\t\tif (matches.length === 0) {\n\t\t\t\t\t\tconst approx = findApproximateMatches(content, edit.oldText);\n\t\t\t\t\t\tconst suggestion = approx.length\n\t\t\t\t\t\t\t? `\\n\\nPossible matches:\\n${approx.slice(0, 3).map(formatMatchPreview).join(\"\\n\")}`\n\t\t\t\t\t\t\t: \"\";\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t`Edit #${index + 1}: Could not find text after ${editsApplied} prior edit(s).${suggestion}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (matches.length > 1) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t`Edit #${index + 1}: Found ${matches.length} matches for oldText. Provide more context. Matches at lines: ${matches.map((m) => m.line).join(\", \")}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tconst matchIndex = matches[0]?.index ?? 0;\n\t\t\t\t\tcontent =\n\t\t\t\t\t\tcontent.slice(0, matchIndex) +\n\t\t\t\t\t\t(edit.newText ?? \"\") +\n\t\t\t\t\t\tcontent.slice(matchIndex + edit.oldText.length);\n\t\t\t\t\teditsApplied++;\n\t\t\t\t}\n\t\t\t\treturn { newContent: content, replacementCount: editsApplied };\n\t\t\t}\n\t\t\t// Single edit mode\n\t\t\tif (!normalizedOldText || normalizedOldText.length === 0) {\n\t\t\t\tthrow new Error(\"oldText cannot be empty\");\n\t\t\t}\n\t\t\tconst exactMatches = findExactMatches(originalContent, normalizedOldText);\n\t\t\tif (exactMatches.length === 0) {\n\t\t\t\tconst approx = findApproximateMatches(\n\t\t\t\t\toriginalContent,\n\t\t\t\t\tnormalizedOldText,\n\t\t\t\t);\n\t\t\t\tconst suggestion = approx.length\n\t\t\t\t\t? `\\n\\nPossible matches:\\n${approx.slice(0, 3).map(formatMatchPreview).join(\"\\n\")}`\n\t\t\t\t\t: `\\n\\nTip: double-check whitespace/newlines via /diff ${path}`;\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Could not find the exact text in ${path}.${suggestion}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (replaceAll) {\n\t\t\t\tif (exactMatches.length > 10000) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Too many replacements: ${exactMatches.length} (max 10000).`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tnewContent: originalContent.replaceAll(\n\t\t\t\t\t\tnormalizedOldText,\n\t\t\t\t\t\tnormalizedNewText ?? \"\",\n\t\t\t\t\t),\n\t\t\t\t\treplacementCount: exactMatches.length,\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (occurrence > exactMatches.length) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Only ${exactMatches.length} occurrence(s) found, but #${occurrence} requested.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst targetMatch = exactMatches[occurrence - 1]!;\n\t\t\tconst matchIndex = targetMatch.index ?? 0;\n\t\t\treturn {\n\t\t\t\tnewContent:\n\t\t\t\t\toriginalContent.slice(0, matchIndex) +\n\t\t\t\t\t(normalizedNewText ?? \"\") +\n\t\t\t\t\toriginalContent.slice(matchIndex + normalizedOldText.length),\n\t\t\t\treplacementCount: 1,\n\t\t\t};\n\t\t};\n\n\t\t// Use sandbox if available\n\t\tif (sandbox) {\n\t\t\ttry {\n\t\t\t\tconst exists = await sandbox.exists(path);\n\t\t\t\tif (!exists) {\n\t\t\t\t\tthrow new Error(`File not found in sandbox: ${path}`);\n\t\t\t\t}\n\t\t\t\tconst originalContent = await sandbox.readFile(path);\n\t\t\t\tconst document = normalizeDocument(originalContent);\n\t\t\t\tconst { newContent: normalizedNewContent, replacementCount } =\n\t\t\t\t\tapplyEdits(document.normalized);\n\t\t\t\tconst newContent = restoreDocumentContent(\n\t\t\t\t\tnormalizedNewContent,\n\t\t\t\t\tdocument,\n\t\t\t\t);\n\t\t\t\tassertTeamMemoryContentSafe(absolutePath, newContent);\n\t\t\t\tconst diff = generateDiffString(originalContent, newContent);\n\n\t\t\t\tif (!dryRun) {\n\t\t\t\t\tawait sandbox.writeFile(path, newContent);\n\t\t\t\t}\n\n\t\t\t\treturn respond\n\t\t\t\t\t.text(\n\t\t\t\t\t\tdryRun\n\t\t\t\t\t\t\t? `[DRY RUN] Would apply ${replacementCount} edit(s) to ${path} in sandbox`\n\t\t\t\t\t\t\t: `Applied ${replacementCount} edit(s) to ${path} in sandbox`,\n\t\t\t\t\t)\n\t\t\t\t\t.detail({ diff, editsApplied: replacementCount, mode: \"sandbox\" });\n\t\t\t} catch (err) {\n\t\t\t\tif (err instanceof Error) throw err;\n\t\t\t\tthrow new Error(String(err));\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\tawait access(absolutePath, constants.R_OK | constants.W_OK);\n\t\t} catch {\n\t\t\t// Provide helpful hint\n\t\t\tlet hint = \"\";\n\t\t\tif (path.includes(\"//\")) {\n\t\t\t\thint = \" Hint: path contains double slashes.\";\n\t\t\t}\n\t\t\tthrow new Error(\n\t\t\t\t`File not found: ${path}.${hint} Use 'read' to verify the path exists.`,\n\t\t\t);\n\t\t}\n\n\t\tthrowIfAborted();\n\t\tconst originalContent = await readFile(absolutePath, \"utf-8\");\n\t\tthrowIfAborted();\n\t\tconst document = normalizeDocument(originalContent);\n\t\tconst { newContent: normalizedNewContent, replacementCount } = applyEdits(\n\t\t\tdocument.normalized,\n\t\t);\n\t\tconst newContent = restoreDocumentContent(normalizedNewContent, document);\n\t\tassertTeamMemoryContentSafe(absolutePath, newContent);\n\t\tconst diff = generateDiffString(originalContent, newContent);\n\n\t\tif (dryRun) {\n\t\t\tconst modeDesc = hasMultiEdit\n\t\t\t\t? `${replacementCount} edit(s)`\n\t\t\t\t: replaceAll\n\t\t\t\t\t? \"all occurrences\"\n\t\t\t\t\t: `occurrence #${occurrence}`;\n\t\t\treturn respond\n\t\t\t\t.text(`Dry run: preview for ${path} (${modeDesc}). No changes written.`)\n\t\t\t\t.detail({\n\t\t\t\t\tdiff,\n\t\t\t\t\teditsApplied: hasMultiEdit ? replacementCount : undefined,\n\t\t\t\t});\n\t\t}\n\n\t\tconst diagnosticBaseline = await captureDiagnosticBaseline(absolutePath);\n\t\tthrowIfAborted();\n\n\t\tawait writeFileAtomically(absolutePath, newContent);\n\t\tlet validatorSummaries: ValidatorRunResult[] | undefined;\n\t\tlet linterOutput = \"\";\n\t\tlet diagnosticDeltaSummary: DiagnosticDeltaToolSummary | undefined;\n\t\ttry {\n\t\t\tconst diagnosticDelta = await collectDiagnosticDelta(diagnosticBaseline);\n\t\t\tdiagnosticDeltaSummary = buildDiagnosticDeltaToolSummary({\n\t\t\t\tfile: absolutePath,\n\t\t\t\tdisplayPath: path,\n\t\t\t\tresult: diagnosticDelta,\n\t\t\t});\n\t\t\tconst visibleDiagnostics = diagnosticDelta.usedDelta\n\t\t\t\t? diagnosticDelta.newDiagnostics\n\t\t\t\t: diagnosticDelta.fileDiagnostics;\n\t\t\tif (visibleDiagnostics.length > 0) {\n\t\t\t\tlinterOutput = formatLspDiagnostics(path, visibleDiagnostics);\n\t\t\t}\n\t\t\tvalidatorSummaries = await runValidatorsOnSuccess(\n\t\t\t\t[absolutePath],\n\t\t\t\tdiagnosticDelta.validatorDiagnostics,\n\t\t\t);\n\t\t} catch (validatorError) {\n\t\t\tawait writeFileAtomically(absolutePath, originalContent);\n\t\t\tthrow validatorError;\n\t\t}\n\n\t\tthrowIfAborted();\n\n\t\tconst resultMessage = hasMultiEdit\n\t\t\t? `Successfully applied ${replacementCount} edit(s) to ${path}.`\n\t\t\t: replaceAll\n\t\t\t\t? `Successfully replaced all ${replacementCount} occurrence(s) in ${path}.`\n\t\t\t\t: `Successfully edited ${path}.`;\n\n\t\treturn respond\n\t\t\t.text(\n\t\t\t\t[\n\t\t\t\t\tresultMessage,\n\t\t\t\t\tlinterOutput,\n\t\t\t\t\tdiagnosticDeltaSummary\n\t\t\t\t\t\t? formatDiagnosticDeltaForToolOutput(diagnosticDeltaSummary)\n\t\t\t\t\t\t: \"\",\n\t\t\t\t]\n\t\t\t\t\t.filter(Boolean)\n\t\t\t\t\t.join(\"\\n\"),\n\t\t\t)\n\t\t\t.detail({\n\t\t\t\tdiff,\n\t\t\t\teditsApplied: hasMultiEdit ? replacementCount : undefined,\n\t\t\t\tvalidators: validatorSummaries,\n\t\t\t\tdiagnosticDelta: diagnosticDeltaSummary,\n\t\t\t});\n\t},\n});\n\ntype MatchPreview = {\n\tline: number;\n\tsnippet: string;\n\tindex?: number;\n\tsimilarity?: number;\n};\n\nfunction findExactMatches(content: string, snippet: string): MatchPreview[] {\n\tconst matches: MatchPreview[] = [];\n\tlet index = content.indexOf(snippet);\n\twhile (index !== -1) {\n\t\tmatches.push({\n\t\t\tline: getLineNumber(content, index),\n\t\t\tsnippet: getSnippet(content, index, snippet.length),\n\t\t\tindex,\n\t\t});\n\t\tindex = content.indexOf(snippet, index + snippet.length);\n\t}\n\treturn matches;\n}\n\n/**\n * Levenshtein Distance Algorithm - Measures string similarity via edit operations\n *\n * Computes the minimum number of single-character edits (insertions, deletions,\n * or substitutions) required to transform string `a` into string `b`. This is\n * the classic dynamic programming solution, optimized for space efficiency.\n *\n * ## Algorithm Explanation\n *\n * The standard DP approach uses a 2D matrix where cell [i,j] represents the\n * edit distance between a[0..i-1] and b[0..j-1]. The recurrence relation:\n *\n * dist[i][j] = min(\n * dist[i-1][j] + 1, // deletion: remove char from a\n * dist[i][j-1] + 1, // insertion: add char to a\n * dist[i-1][j-1] + cost // substitution: cost=0 if chars match, else 1\n * )\n *\n * ## Space Optimization\n *\n * Since each row only depends on the previous row, we use two 1D arrays instead\n * of a full matrix. This reduces space complexity from O(m*n) to O(min(m,n)).\n *\n * - `prev`: the previous row of the DP matrix\n * - `curr`: the current row being computed\n * - After each outer loop iteration, we swap the arrays\n *\n * ## Complexity\n *\n * - Time: O(m * n) where m = len(a), n = len(b)\n * - Space: O(n) - only two arrays of length n+1\n *\n * ## Usage in Edit Tool\n *\n * This function powers the fuzzy matching fallback. When an exact match fails,\n * we compute Levenshtein distance between the search text and candidate regions\n * in the file, then convert to a similarity ratio (see `similarity()` below).\n *\n * @param a - First string to compare\n * @param b - Second string to compare\n * @returns The edit distance (0 = identical, higher = more different)\n */\nfunction levenshtein(a: string, b: string): number {\n\t// Base cases: if either string is empty, distance is the length of the other\n\tif (a.length === 0) return b.length;\n\tif (b.length === 0) return a.length;\n\n\t// Space-optimized DP: maintain only two rows instead of full matrix.\n\t// `prev` holds the distances computed for the previous character of `a`.\n\t// Initialize with distances from empty string: 0, 1, 2, ..., b.length\n\tlet prev = Array.from({ length: b.length + 1 }, (_, i) => i);\n\tlet curr = new Array<number>(b.length + 1);\n\n\t// Iterate through each character of string `a`\n\tfor (let i = 1; i <= a.length; i++) {\n\t\t// Distance from a[0..i-1] to empty string is i (delete all chars)\n\t\tcurr[0] = i;\n\n\t\t// Iterate through each character of string `b`\n\t\tfor (let j = 1; j <= b.length; j++) {\n\t\t\t// Cost is 0 if characters match, 1 if they need substitution\n\t\t\tconst cost = a[i - 1] === b[j - 1] ? 0 : 1;\n\n\t\t\t// Take minimum of three possible operations:\n\t\t\tcurr[j] = Math.min(\n\t\t\t\tprev[j]! + 1, // deletion: remove a[i-1], use distance for a[0..i-2] to b[0..j-1]\n\t\t\t\tcurr[j - 1]! + 1, // insertion: insert b[j-1], use distance for a[0..i-1] to b[0..j-2]\n\t\t\t\tprev[j - 1]! + cost, // substitution: use distance for a[0..i-2] to b[0..j-2] + substitution cost\n\t\t\t);\n\t\t}\n\t\t// Swap rows: current row becomes previous for next iteration\n\t\t[prev, curr] = [curr, prev];\n\t}\n\t// After all iterations, `prev` contains the final row (due to swap)\n\treturn prev[b.length]!;\n}\n\n/**\n * Similarity Ratio - Normalizes Levenshtein distance to a 0-1 scale\n *\n * Converts the raw edit distance into an intuitive percentage where:\n * - 1.0 = identical strings (0 edits needed)\n * - 0.0 = completely different (edit distance equals max string length)\n *\n * Formula: similarity = 1 - (edit_distance / max_length)\n *\n * This normalization is crucial because raw edit distance doesn't account\n * for string length. For example, an edit distance of 5 between two 100-char\n * strings (95% similar) is very different from distance 5 between two 6-char\n * strings (17% similar).\n *\n * @param a - First string to compare\n * @param b - Second string to compare\n * @returns Similarity ratio from 0 (completely different) to 1 (identical)\n */\nfunction similarity(a: string, b: string): number {\n\tconst maxLen = Math.max(a.length, b.length);\n\t// Two empty strings are identical\n\tif (maxLen === 0) return 1;\n\t// Normalize: 0 edits = 1.0 similarity, maxLen edits = 0.0 similarity\n\treturn 1 - levenshtein(a, b) / maxLen;\n}\n\n/**\n * Similarity Thresholds for Approximate Matching\n *\n * These thresholds control which fuzzy matches are shown to the user. They're\n * intentionally different based on context to balance helpfulness vs noise.\n *\n * ## Threshold Strategy\n *\n * **Single Candidate (50%)**: When only one potential match is found, we're\n * lenient because showing something is better than nothing. Even a 50% match\n * might be the reformatted/moved code the user is looking for.\n *\n * **Multiple Candidates (60%)**: When several matches exist, we're stricter\n * to avoid overwhelming the user with noise. A higher threshold ensures only\n * genuinely relevant suggestions surface.\n *\n * ## Why These Values?\n *\n * - 50% catches significant changes (indentation, variable renames, added lines)\n * while filtering out completely unrelated code\n * - 60% for multiple matches prevents showing 3+ mediocre suggestions that\n * confuse more than they help\n * - Values chosen empirically from real-world edit failure scenarios\n */\nconst SINGLE_CANDIDATE_THRESHOLD = 0.5; // Accept single match if 50%+ similar\nconst MULTI_CANDIDATE_THRESHOLD = 0.6; // Need 60%+ to show when multiple matches\n\n/**\n * Approximate Match Finder - Multi-strategy fuzzy search for similar text\n *\n * When exact matching fails, this function attempts to find regions in the file\n * that closely resemble the search snippet. It employs two complementary strategies\n * to maximize the chances of finding the right location even when the content\n * has changed.\n *\n * ## Strategy 1: Relaxed Regex Matching\n *\n * Creates a regex that normalizes whitespace (see `buildRelaxedRegex`), then\n * finds all matches in the content. This catches cases where:\n * - Indentation changed (tabs vs spaces, different indent levels)\n * - Extra blank lines were added/removed\n * - Line wrapping changed\n *\n * ## Strategy 2: Sliding Window Line Comparison\n *\n * For multi-line snippets, slides a window of the same size through the content\n * and computes Levenshtein similarity at each position. This catches cases where:\n * - Variables were renamed\n * - Minor code changes occurred (added parameters, changed values)\n * - Content was moved but not significantly altered\n *\n * ## Deduplication\n *\n * Both strategies may find the same region; we deduplicate by line number to\n * avoid showing duplicate suggestions.\n *\n * ## Result Limits\n *\n * - Maximum 10 candidates collected (performance guard)\n * - Maximum 5 shown to user (UI clarity)\n * - Dynamic threshold based on candidate count (see threshold constants above)\n *\n * @param content - The full file content to search in\n * @param snippet - The text the user is looking for\n * @returns Array of match previews sorted by similarity, filtered by threshold\n */\nfunction findApproximateMatches(\n\tcontent: string,\n\tsnippet: string,\n): MatchPreview[] {\n\t// Strategy 1: Regex-based matching with whitespace normalization\n\tconst relaxed = buildRelaxedRegex(snippet);\n\tconst regexMatches: Array<MatchPreview & { similarity: number }> = [];\n\n\tif (relaxed) {\n\t\tlet result: RegExpExecArray | null;\n\t\t// Limit to 10 matches to prevent performance issues in large files\n\t\twhile (regexMatches.length < 10) {\n\t\t\tresult = relaxed.exec(content);\n\t\t\tif (!result) break;\n\t\t\tconst matchIndex = result.index;\n\t\t\tconst matchText = result[0];\n\t\t\t// Score each regex match by actual similarity (regex may be too permissive)\n\t\t\tconst sim = similarity(snippet.trim(), matchText.trim());\n\t\t\tregexMatches.push({\n\t\t\t\tline: getLineNumber(content, matchIndex),\n\t\t\t\tsnippet: getSnippet(content, matchIndex, matchText.length),\n\t\t\t\tsimilarity: sim,\n\t\t\t});\n\t\t}\n\t}\n\n\t// Strategy 2: Sliding window comparison for multi-line snippets\n\t// This catches renamed variables and minor changes that regex misses\n\tconst snippetLines = snippet.trim().split(\"\\n\");\n\tif (snippetLines.length > 1) {\n\t\tconst contentLines = content.split(\"\\n\");\n\t\t// Slide a window of size |snippetLines| through the content\n\t\tfor (let i = 0; i <= contentLines.length - snippetLines.length; i++) {\n\t\t\tconst candidateLines = contentLines.slice(i, i + snippetLines.length);\n\t\t\tconst candidate = candidateLines.join(\"\\n\");\n\t\t\tconst sim = similarity(snippet.trim(), candidate.trim());\n\t\t\t// Only consider if above the minimum threshold\n\t\t\tif (sim >= SINGLE_CANDIDATE_THRESHOLD) {\n\t\t\t\t// Deduplicate: don't add if we already found this line via regex\n\t\t\t\tconst lineNum = i + 1;\n\t\t\t\tif (!regexMatches.some((m) => m.line === lineNum)) {\n\t\t\t\t\tregexMatches.push({\n\t\t\t\t\t\tline: lineNum,\n\t\t\t\t\t\t// Show first 3 lines as preview to avoid overwhelming output\n\t\t\t\t\t\tsnippet: candidateLines.slice(0, 3).join(\"\\n\").trim(),\n\t\t\t\t\t\tsimilarity: sim,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Performance guard: stop after collecting 10 candidates\n\t\t\tif (regexMatches.length >= 10) break;\n\t\t}\n\t}\n\n\t// Sort all candidates by similarity (best matches first)\n\tregexMatches.sort((a, b) => b.similarity - a.similarity);\n\n\t// Apply dynamic threshold: stricter when many candidates exist\n\t// This prevents showing 5 mediocre matches when there's one good one\n\tconst threshold =\n\t\tregexMatches.length === 1\n\t\t\t? SINGLE_CANDIDATE_THRESHOLD\n\t\t\t: MULTI_CANDIDATE_THRESHOLD;\n\n\t// Return top 5 matches above threshold, stripping internal similarity score\n\treturn regexMatches\n\t\t.filter((m) => m.similarity >= threshold)\n\t\t.slice(0, 5)\n\t\t.map(({ line, snippet, similarity }) => ({ line, snippet, similarity }));\n}\n\n/**\n * Relaxed Regex Builder - Creates whitespace-normalized pattern for fuzzy matching\n *\n * Transforms a literal search string into a regex that matches the same content\n * with flexible whitespace. This is the first strategy in approximate matching.\n *\n * ## Transformation Steps\n *\n * 1. **Trim**: Remove leading/trailing whitespace (user likely copied extra)\n * 2. **Escape metacharacters**: Treat all regex special chars as literals\n * - Characters escaped: . * + ? ^ $ { } ( ) | [ ] \\\n * 3. **Normalize whitespace**: Replace all whitespace runs with `\\s+`\n * - Matches any combination of spaces, tabs, newlines\n * - Makes indentation changes transparent\n *\n * ## Example Transformation\n *\n * Input: \"function foo( a, b ) {\"\n * Regex: \"function\\s+foo\\(\\s+a,\\s+b\\s+\\)\\s+\\{\"\n * Matches: \"function foo(a, b) {\" or \"function foo( a, b ) {\"\n *\n * ## Safety Guards\n *\n * - Empty input → null (avoid matching everything)\n * - Pattern > 500 chars → null (prevent ReDoS on very long snippets)\n * - Invalid regex → null (graceful fallback to line-by-line comparison)\n *\n * @param snippet - The text to convert into a relaxed regex\n * @returns Compiled regex with 'gi' flags, or null if construction fails\n */\nfunction buildRelaxedRegex(snippet: string): RegExp | null {\n\tconst trimmed = snippet.trim();\n\t// Empty pattern would match everything - not useful\n\tif (!trimmed) return null;\n\n\t// Step 1: Escape all regex metacharacters so they match literally\n\t// This prevents \"user.name\" from being interpreted as \"user<any-char>name\"\n\tconst escaped = trimmed\n\t\t.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")\n\t\t// Step 2: Replace whitespace runs with flexible matcher\n\t\t// This makes the pattern match regardless of indentation style\n\t\t.replace(/\\s+/g, \"\\\\s+\");\n\n\t// Guard against ReDoS: very long patterns can cause exponential backtracking\n\tif (escaped.length > 500) return null;\n\n\ttry {\n\t\t// nosemgrep: javascript.lang.security.audit.detect-non-literal-regexp.detect-non-literal-regexp\n\t\t// Flags: g = global (find all), i = case-insensitive (catches renamed vars)\n\t\treturn new RegExp(escaped, \"gi\");\n\t} catch {\n\t\t// Invalid regex (shouldn't happen after escaping, but be safe)\n\t\treturn null;\n\t}\n}\n\nfunction getLineNumber(content: string, index: number): number {\n\treturn content.slice(0, index).split(\"\\n\").length;\n}\n\nfunction getSnippet(content: string, start: number, _length: number): string {\n\tconst lines = content.split(\"\\n\");\n\tconst lineNum = getLineNumber(content, start);\n\tconst startLine = Math.max(0, lineNum - 2);\n\tconst endLine = Math.min(lines.length, lineNum + 1);\n\treturn lines.slice(startLine, endLine).join(\"\\n\").trim();\n}\n\nfunction formatMatchPreview(match: MatchPreview): string {\n\tconst simPct = match.similarity\n\t\t? ` (${Math.round(match.similarity * 100)}% similar)`\n\t\t: \"\";\n\treturn `• Line ${match.line}${simPct}: ${match.snippet}`;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"edit.js","sourceRoot":"","sources":["../../src/tools/edit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC/E,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,EACN,wBAAwB,EACxB,4BAA4B,GAC5B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACN,yBAAyB,EACzB,sBAAsB,GACtB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAEN,+BAA+B,EAC/B,kCAAkC,GAClC,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;AACvE,OAAO,EACN,gBAAgB,EAChB,sBAAsB,GACtB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC3E,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE3D,KAAK,UAAU,mBAAmB,CACjC,QAAgB,EAChB,QAAgB;IAEhB,MAAM,QAAQ,GAAG,GAAG,QAAQ,IAAI,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC;IAC1D,MAAM,SAAS,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC7C,IAAI,CAAC;QACJ,MAAM,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACvC,MAAM,KAAK,CAAC;IACb,CAAC;AACF,CAAC;AAaD,SAAS,gBAAgB,CAAC,IAAY;IACrC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,MAAM,CAAC;IACzC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACrC,OAAO,IAAI,CAAC;AACb,CAAC;AAED,SAAS,iBAAiB,CAAC,OAAe;IACzC,MAAM,GAAG,GAAG,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;IACzD,MAAM,UAAU,GAAG,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IACpD,MAAM,UAAU,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAChD,MAAM,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC1E,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC;AAC3D,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAwB;IAClD,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACzC,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AACzD,CAAC;AAED,SAAS,sBAAsB,CAC9B,UAAkB,EAClB,QAA4B;IAE5B,MAAM,QAAQ,GACb,QAAQ,CAAC,UAAU,KAAK,IAAI;QAC3B,CAAC,CAAC,UAAU;QACZ,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC;IACnD,OAAO,GAAG,QAAQ,CAAC,GAAG,GAAG,QAAQ,EAAE,CAAC;AACrC,CAAC;AAED,MAAM,mBAAmB,GAAG,IAAI,CAAC,MAAM,CAAC;IACvC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC;QACpB,WAAW,EAAE,gCAAgC;QAC7C,SAAS,EAAE,CAAC;KACZ,CAAC;IACF,OAAO,EAAE,IAAI,CAAC,QAAQ,CACrB,IAAI,CAAC,MAAM,CAAC;QACX,WAAW,EAAE,mDAAmD;QAChE,OAAO,EAAE,EAAE;KACX,CAAC,CACF;CACD,CAAC,CAAC;AAEH,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC;IAC9B,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC;QACjB,WAAW,EAAE,iDAAiD;QAC9D,SAAS,EAAE,CAAC;KACZ,CAAC;IACF,OAAO,EAAE,IAAI,CAAC,QAAQ,CACrB,IAAI,CAAC,MAAM,CAAC;QACX,WAAW,EAAE,qDAAqD;QAClE,SAAS,EAAE,CAAC;KACZ,CAAC,CACF;IACD,OAAO,EAAE,IAAI,CAAC,QAAQ,CACrB,IAAI,CAAC,MAAM,CAAC;QACX,WAAW,EAAE,uCAAuC;QACpD,OAAO,EAAE,EAAE;KACX,CAAC,CACF;IACD,KAAK,EAAE,IAAI,CAAC,QAAQ,CACnB,IAAI,CAAC,KAAK,CAAC,mBAAmB,EAAE;QAC/B,WAAW,EACV,uEAAuE;QACxE,QAAQ,EAAE,CAAC;QACX,QAAQ,EAAE,EAAE;KACZ,CAAC,CACF;IACD,UAAU,EAAE,IAAI,CAAC,QAAQ,CACxB,IAAI,CAAC,OAAO,CAAC;QACZ,WAAW,EACV,kGAAkG;QACnG,OAAO,EAAE,KAAK;KACd,CAAC,CACF;IACD,UAAU,EAAE,IAAI,CAAC,QAAQ,CACxB,IAAI,CAAC,OAAO,CAAC;QACZ,WAAW,EACV,6FAA6F;QAC9F,OAAO,EAAE,CAAC;QACV,OAAO,EAAE,CAAC;KACV,CAAC,CACF;IACD,MAAM,EAAE,IAAI,CAAC,QAAQ,CACpB,IAAI,CAAC,OAAO,CAAC;QACZ,WAAW,EAAE,0CAA0C;QACvD,OAAO,EAAE,KAAK;KACd,CAAC,CACF;CACD,CAAC,CAAC;AAUH,MAAM,CAAC,MAAM,QAAQ,GAAG,UAAU,CAAqC;IACtE,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,MAAM;IACb,WAAW,EAAE;;;;;;;;;;;;;;;;;;;mDAmBqC;IAClD,MAAM,EAAE,UAAU;IAClB,KAAK,CAAC,GAAG,CACR,EACC,IAAI,EACJ,OAAO,EACP,OAAO,EACP,KAAK,EACL,UAAU,GAAG,KAAK,EAClB,UAAU,GAAG,CAAC,EACd,MAAM,GAAG,KAAK,GACd,EACD,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE;QAE5B,gBAAgB,CAAC,MAAM,CAAC,CAAC;QAEzB,MAAM,YAAY,GAAG,WAAW,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC;QACvD,MAAM,cAAc,GAAG,GAAG,EAAE;YAC3B,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;gBACrB,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;YACtC,CAAC;QACF,CAAC,CAAC;QAEF,yCAAyC;QACzC,MAAM,aAAa,GAAG,OAAO,KAAK,SAAS,CAAC;QAC5C,iEAAiE;QACjE,6DAA6D;QAC7D,MAAM,kBAAkB,GAAG,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,EAAE,CAAC;QACnE,MAAM,YAAY,GAAG,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;QAE7D,IAAI,CAAC,aAAa,IAAI,kBAAkB,CAAC,IAAI,YAAY,EAAE,CAAC;YAC3D,MAAM,IAAI,KAAK,CACd,wEAAwE,CACxE,CAAC;QACH,CAAC;QAED,IAAI,CAAC,aAAa,IAAI,CAAC,YAAY,EAAE,CAAC;YACrC,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;QACxE,CAAC;QAED,IAAI,YAAY,IAAI,CAAC,UAAU,IAAI,UAAU,KAAK,CAAC,CAAC,EAAE,CAAC;YACtD,MAAM,IAAI,KAAK,CACd,iGAAiG,CACjG,CAAC;QACH,CAAC;QAED,IAAI,UAAU,IAAI,UAAU,KAAK,CAAC,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAC/D,CAAC;QAED,MAAM,iBAAiB,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;QACrD,MAAM,iBAAiB,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;QACrD,MAAM,eAAe,GAAG,KAAK,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC7C,GAAG,IAAI;YACP,OAAO,EAAE,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE;YAC9C,OAAO,EAAE,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC;SACxC,CAAC,CAAC,CAAC;QAEJ,4EAA4E;QAC5E,MAAM,UAAU,GAAG,CAClB,eAAuB,EAC4B,EAAE;YACrD,IAAI,YAAY,IAAI,eAAe,EAAE,CAAC;gBACrC,IAAI,OAAO,GAAG,eAAe,CAAC;gBAC9B,IAAI,YAAY,GAAG,CAAC,CAAC;gBACrB,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,eAAe,CAAC,OAAO,EAAE,EAAE,CAAC;oBACvD,MAAM,OAAO,GAAG,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;oBACxD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;wBAC1B,MAAM,MAAM,GAAG,sBAAsB,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;wBAC7D,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM;4BAC/B,CAAC,CAAC,0BAA0B,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;4BACnF,CAAC,CAAC,EAAE,CAAC;wBACN,MAAM,IAAI,KAAK,CACd,SAAS,KAAK,GAAG,CAAC,+BAA+B,YAAY,kBAAkB,UAAU,EAAE,CAC3F,CAAC;oBACH,CAAC;oBACD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBACxB,MAAM,IAAI,KAAK,CACd,SAAS,KAAK,GAAG,CAAC,WAAW,OAAO,CAAC,MAAM,iEAAiE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACnJ,CAAC;oBACH,CAAC;oBACD,MAAM,UAAU,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,CAAC;oBAC1C,OAAO;wBACN,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC;4BAC5B,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;4BACpB,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;oBACjD,YAAY,EAAE,CAAC;gBAChB,CAAC;gBACD,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,CAAC;YAChE,CAAC;YACD,mBAAmB;YACnB,IAAI,CAAC,iBAAiB,IAAI,iBAAiB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC1D,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;YAC5C,CAAC;YACD,MAAM,YAAY,GAAG,gBAAgB,CAAC,eAAe,EAAE,iBAAiB,CAAC,CAAC;YAC1E,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC/B,MAAM,MAAM,GAAG,sBAAsB,CACpC,eAAe,EACf,iBAAiB,CACjB,CAAC;gBACF,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM;oBAC/B,CAAC,CAAC,0BAA0B,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;oBACnF,CAAC,CAAC,uDAAuD,IAAI,EAAE,CAAC;gBACjE,MAAM,IAAI,KAAK,CACd,oCAAoC,IAAI,IAAI,UAAU,EAAE,CACxD,CAAC;YACH,CAAC;YACD,IAAI,UAAU,EAAE,CAAC;gBAChB,IAAI,YAAY,CAAC,MAAM,GAAG,KAAK,EAAE,CAAC;oBACjC,MAAM,IAAI,KAAK,CACd,0BAA0B,YAAY,CAAC,MAAM,eAAe,CAC5D,CAAC;gBACH,CAAC;gBACD,OAAO;oBACN,UAAU,EAAE,eAAe,CAAC,UAAU,CACrC,iBAAiB,EACjB,iBAAiB,IAAI,EAAE,CACvB;oBACD,gBAAgB,EAAE,YAAY,CAAC,MAAM;iBACrC,CAAC;YACH,CAAC;YACD,IAAI,UAAU,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC;gBACtC,MAAM,IAAI,KAAK,CACd,QAAQ,YAAY,CAAC,MAAM,8BAA8B,UAAU,aAAa,CAChF,CAAC;YACH,CAAC;YACD,MAAM,WAAW,GAAG,YAAY,CAAC,UAAU,GAAG,CAAC,CAAE,CAAC;YAClD,MAAM,UAAU,GAAG,WAAW,CAAC,KAAK,IAAI,CAAC,CAAC;YAC1C,OAAO;gBACN,UAAU,EACT,eAAe,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC;oBACpC,CAAC,iBAAiB,IAAI,EAAE,CAAC;oBACzB,eAAe,CAAC,KAAK,CAAC,UAAU,GAAG,iBAAiB,CAAC,MAAM,CAAC;gBAC7D,gBAAgB,EAAE,CAAC;aACnB,CAAC;QACH,CAAC,CAAC;QAEF,2BAA2B;QAC3B,IAAI,OAAO,EAAE,CAAC;YACb,IAAI,CAAC;gBACJ,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBAC1C,IAAI,CAAC,MAAM,EAAE,CAAC;oBACb,MAAM,IAAI,KAAK,CAAC,8BAA8B,IAAI,EAAE,CAAC,CAAC;gBACvD,CAAC;gBACD,MAAM,eAAe,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;gBACrD,MAAM,QAAQ,GAAG,iBAAiB,CAAC,eAAe,CAAC,CAAC;gBACpD,MAAM,EAAE,UAAU,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,GAC3D,UAAU,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;gBACjC,MAAM,UAAU,GAAG,sBAAsB,CACxC,oBAAoB,EACpB,QAAQ,CACR,CAAC;gBACF,2BAA2B,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;gBACtD,MAAM,oBAAoB,GAAG,4BAA4B,CAAC;oBACzD,QAAQ,EAAE,YAAY;oBACtB,OAAO,EAAE,UAAU;oBACnB,IAAI,EAAE,wBAAwB,EAAE;iBAChC,CAAC,CAAC;gBACH,IAAI,CAAC,oBAAoB,CAAC,EAAE,EAAE,CAAC;oBAC9B,OAAO,OAAO,CAAC,KAAK,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC;gBACpD,CAAC;gBACD,MAAM,IAAI,GAAG,kBAAkB,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;gBAE7D,IAAI,CAAC,MAAM,EAAE,CAAC;oBACb,MAAM,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;gBAC3C,CAAC;gBAED,OAAO,OAAO;qBACZ,IAAI,CACJ,MAAM;oBACL,CAAC,CAAC,yBAAyB,gBAAgB,eAAe,IAAI,aAAa;oBAC3E,CAAC,CAAC,WAAW,gBAAgB,eAAe,IAAI,aAAa,CAC9D;qBACA,MAAM,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,gBAAgB,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;YACrE,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACd,IAAI,GAAG,YAAY,KAAK;oBAAE,MAAM,GAAG,CAAC;gBACpC,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YAC9B,CAAC;QACF,CAAC;QAED,IAAI,CAAC;YACJ,MAAM,MAAM,CAAC,YAAY,EAAE,SAAS,CAAC,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAC7D,CAAC;QAAC,MAAM,CAAC;YACR,uBAAuB;YACvB,IAAI,IAAI,GAAG,EAAE,CAAC;YACd,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBACzB,IAAI,GAAG,sCAAsC,CAAC;YAC/C,CAAC;YACD,MAAM,IAAI,KAAK,CACd,mBAAmB,IAAI,IAAI,IAAI,wCAAwC,CACvE,CAAC;QACH,CAAC;QAED,cAAc,EAAE,CAAC;QACjB,MAAM,eAAe,GAAG,MAAM,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QAC9D,cAAc,EAAE,CAAC;QACjB,MAAM,QAAQ,GAAG,iBAAiB,CAAC,eAAe,CAAC,CAAC;QACpD,MAAM,EAAE,UAAU,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,GAAG,UAAU,CACxE,QAAQ,CAAC,UAAU,CACnB,CAAC;QACF,MAAM,UAAU,GAAG,sBAAsB,CAAC,oBAAoB,EAAE,QAAQ,CAAC,CAAC;QAC1E,2BAA2B,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;QACtD,MAAM,oBAAoB,GAAG,4BAA4B,CAAC;YACzD,QAAQ,EAAE,YAAY;YACtB,OAAO,EAAE,UAAU;YACnB,IAAI,EAAE,wBAAwB,EAAE;SAChC,CAAC,CAAC;QACH,IAAI,CAAC,oBAAoB,CAAC,EAAE,EAAE,CAAC;YAC9B,OAAO,OAAO,CAAC,KAAK,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC;QACpD,CAAC;QACD,MAAM,IAAI,GAAG,kBAAkB,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;QAE7D,IAAI,MAAM,EAAE,CAAC;YACZ,MAAM,QAAQ,GAAG,YAAY;gBAC5B,CAAC,CAAC,GAAG,gBAAgB,UAAU;gBAC/B,CAAC,CAAC,UAAU;oBACX,CAAC,CAAC,iBAAiB;oBACnB,CAAC,CAAC,eAAe,UAAU,EAAE,CAAC;YAChC,OAAO,OAAO;iBACZ,IAAI,CAAC,wBAAwB,IAAI,KAAK,QAAQ,wBAAwB,CAAC;iBACvE,MAAM,CAAC;gBACP,IAAI;gBACJ,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS;aACzD,CAAC,CAAC;QACL,CAAC;QAED,MAAM,kBAAkB,GAAG,MAAM,yBAAyB,CAAC,YAAY,CAAC,CAAC;QACzE,cAAc,EAAE,CAAC;QAEjB,MAAM,mBAAmB,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;QACpD,IAAI,kBAAoD,CAAC;QACzD,IAAI,YAAY,GAAG,EAAE,CAAC;QACtB,IAAI,sBAA8D,CAAC;QACnE,IAAI,CAAC;YACJ,MAAM,eAAe,GAAG,MAAM,sBAAsB,CAAC,kBAAkB,CAAC,CAAC;YACzE,sBAAsB,GAAG,+BAA+B,CAAC;gBACxD,IAAI,EAAE,YAAY;gBAClB,WAAW,EAAE,IAAI;gBACjB,MAAM,EAAE,eAAe;aACvB,CAAC,CAAC;YACH,MAAM,kBAAkB,GAAG,eAAe,CAAC,SAAS;gBACnD,CAAC,CAAC,eAAe,CAAC,cAAc;gBAChC,CAAC,CAAC,eAAe,CAAC,eAAe,CAAC;YACnC,IAAI,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACnC,YAAY,GAAG,oBAAoB,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAC;YAC/D,CAAC;YACD,kBAAkB,GAAG,MAAM,sBAAsB,CAChD,CAAC,YAAY,CAAC,EACd,eAAe,CAAC,oBAAoB,CACpC,CAAC;QACH,CAAC;QAAC,OAAO,cAAc,EAAE,CAAC;YACzB,MAAM,mBAAmB,CAAC,YAAY,EAAE,eAAe,CAAC,CAAC;YACzD,MAAM,cAAc,CAAC;QACtB,CAAC;QAED,cAAc,EAAE,CAAC;QAEjB,MAAM,aAAa,GAAG,YAAY;YACjC,CAAC,CAAC,wBAAwB,gBAAgB,eAAe,IAAI,GAAG;YAChE,CAAC,CAAC,UAAU;gBACX,CAAC,CAAC,6BAA6B,gBAAgB,qBAAqB,IAAI,GAAG;gBAC3E,CAAC,CAAC,uBAAuB,IAAI,GAAG,CAAC;QAEnC,OAAO,OAAO;aACZ,IAAI,CACJ;YACC,aAAa;YACb,YAAY;YACZ,sBAAsB;gBACrB,CAAC,CAAC,kCAAkC,CAAC,sBAAsB,CAAC;gBAC5D,CAAC,CAAC,EAAE;SACL;aACC,MAAM,CAAC,OAAO,CAAC;aACf,IAAI,CAAC,IAAI,CAAC,CACZ;aACA,MAAM,CAAC;YACP,IAAI;YACJ,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS;YACzD,UAAU,EAAE,kBAAkB;YAC9B,eAAe,EAAE,sBAAsB;SACvC,CAAC,CAAC;IACL,CAAC;CACD,CAAC,CAAC;AASH,SAAS,gBAAgB,CAAC,OAAe,EAAE,OAAe;IACzD,MAAM,OAAO,GAAmB,EAAE,CAAC;IACnC,IAAI,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACrC,OAAO,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;QACrB,OAAO,CAAC,IAAI,CAAC;YACZ,IAAI,EAAE,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC;YACnC,OAAO,EAAE,UAAU,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC;YACnD,KAAK;SACL,CAAC,CAAC;QACH,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,OAAO,CAAC;AAChB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,SAAS,WAAW,CAAC,CAAS,EAAE,CAAS;IACxC,6EAA6E;IAC7E,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC,MAAM,CAAC;IACpC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC,MAAM,CAAC;IAEpC,qEAAqE;IACrE,yEAAyE;IACzE,sEAAsE;IACtE,IAAI,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7D,IAAI,IAAI,GAAG,IAAI,KAAK,CAAS,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAE3C,+CAA+C;IAC/C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACpC,kEAAkE;QAClE,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAEZ,+CAA+C;QAC/C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACpC,6DAA6D;YAC7D,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAE3C,6CAA6C;YAC7C,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CACjB,IAAI,CAAC,CAAC,CAAE,GAAG,CAAC,EAAE,mEAAmE;YACjF,IAAI,CAAC,CAAC,GAAG,CAAC,CAAE,GAAG,CAAC,EAAE,oEAAoE;YACtF,IAAI,CAAC,CAAC,GAAG,CAAC,CAAE,GAAG,IAAI,CACnB,CAAC;QACH,CAAC;QACD,6DAA6D;QAC7D,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC7B,CAAC;IACD,oEAAoE;IACpE,OAAO,IAAI,CAAC,CAAC,CAAC,MAAM,CAAE,CAAC;AACxB,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,SAAS,UAAU,CAAC,CAAS,EAAE,CAAS;IACvC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IAC5C,kCAAkC;IAClC,IAAI,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAC3B,qEAAqE;IACrE,OAAO,CAAC,GAAG,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC;AACvC,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,0BAA0B,GAAG,GAAG,CAAC,CAAC,sCAAsC;AAC9E,MAAM,yBAAyB,GAAG,GAAG,CAAC,CAAC,0CAA0C;AAEjF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,SAAS,sBAAsB,CAC9B,OAAe,EACf,OAAe;IAEf,iEAAiE;IACjE,MAAM,OAAO,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAC3C,MAAM,YAAY,GAAiD,EAAE,CAAC;IAEtE,IAAI,OAAO,EAAE,CAAC;QACb,IAAI,MAA8B,CAAC;QACnC,mEAAmE;QACnE,OAAO,YAAY,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;YACjC,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC/B,IAAI,CAAC,MAAM;gBAAE,MAAM;YACnB,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC;YAChC,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;YAC5B,4EAA4E;YAC5E,MAAM,GAAG,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC;YACzD,YAAY,CAAC,IAAI,CAAC;gBACjB,IAAI,EAAE,aAAa,CAAC,OAAO,EAAE,UAAU,CAAC;gBACxC,OAAO,EAAE,UAAU,CAAC,OAAO,EAAE,UAAU,EAAE,SAAS,CAAC,MAAM,CAAC;gBAC1D,UAAU,EAAE,GAAG;aACf,CAAC,CAAC;QACJ,CAAC;IACF,CAAC;IAED,gEAAgE;IAChE,qEAAqE;IACrE,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAChD,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACzC,4DAA4D;QAC5D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,YAAY,CAAC,MAAM,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACrE,MAAM,cAAc,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;YACtE,MAAM,SAAS,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC5C,MAAM,GAAG,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC;YACzD,+CAA+C;YAC/C,IAAI,GAAG,IAAI,0BAA0B,EAAE,CAAC;gBACvC,iEAAiE;gBACjE,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC;gBACtB,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,EAAE,CAAC;oBACnD,YAAY,CAAC,IAAI,CAAC;wBACjB,IAAI,EAAE,OAAO;wBACb,6DAA6D;wBAC7D,OAAO,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE;wBACrD,UAAU,EAAE,GAAG;qBACf,CAAC,CAAC;gBACJ,CAAC;YACF,CAAC;YACD,yDAAyD;YACzD,IAAI,YAAY,CAAC,MAAM,IAAI,EAAE;gBAAE,MAAM;QACtC,CAAC;IACF,CAAC;IAED,yDAAyD;IACzD,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC;IAEzD,+DAA+D;IAC/D,qEAAqE;IACrE,MAAM,SAAS,GACd,YAAY,CAAC,MAAM,KAAK,CAAC;QACxB,CAAC,CAAC,0BAA0B;QAC5B,CAAC,CAAC,yBAAyB,CAAC;IAE9B,4EAA4E;IAC5E,OAAO,YAAY;SACjB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,IAAI,SAAS,CAAC;SACxC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;SACX,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC;AAC3E,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,SAAS,iBAAiB,CAAC,OAAe;IACzC,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAC/B,oDAAoD;IACpD,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAE1B,kEAAkE;IAClE,2EAA2E;IAC3E,MAAM,OAAO,GAAG,OAAO;SACrB,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC;QACvC,wDAAwD;QACxD,+DAA+D;SAC9D,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE1B,6EAA6E;IAC7E,IAAI,OAAO,CAAC,MAAM,GAAG,GAAG;QAAE,OAAO,IAAI,CAAC;IAEtC,IAAI,CAAC;QACJ,gGAAgG;QAChG,4EAA4E;QAC5E,OAAO,IAAI,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACR,+DAA+D;QAC/D,OAAO,IAAI,CAAC;IACb,CAAC;AACF,CAAC;AAED,SAAS,aAAa,CAAC,OAAe,EAAE,KAAa;IACpD,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;AACnD,CAAC;AAED,SAAS,UAAU,CAAC,OAAe,EAAE,KAAa,EAAE,OAAe;IAClE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC9C,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC;IAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC;IACpD,OAAO,KAAK,CAAC,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;AAC1D,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAmB;IAC9C,MAAM,MAAM,GAAG,KAAK,CAAC,UAAU;QAC9B,CAAC,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,GAAG,GAAG,CAAC,YAAY;QACrD,CAAC,CAAC,EAAE,CAAC;IACN,OAAO,UAAU,KAAK,CAAC,IAAI,GAAG,MAAM,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC;AAC1D,CAAC","sourcesContent":["/**\n * Edit Tool - Find-and-replace text editing with fuzzy matching fallback\n *\n * This module implements a robust text editing tool that performs exact string\n * replacement with intelligent fallback to approximate matching when exact matches\n * fail. The core design philosophy is \"fail helpfully\" - when the user's search\n * text doesn't match exactly (due to whitespace differences, typos, or outdated\n * content), we provide actionable suggestions pointing to the closest matches.\n *\n * ## Architecture Overview\n *\n * 1. **Exact Matching (Primary Path)**\n * - Simple string indexOf search for O(n) performance\n * - Handles single edit, multi-edit (sequential), and replace-all modes\n * - Reports all match locations with line numbers for disambiguation\n *\n * 2. **Approximate Matching (Fallback Path)**\n * - Triggered only when exact match fails\n * - Uses two complementary strategies:\n * a) Regex-based relaxed matching (whitespace normalization)\n * b) Line-by-line Levenshtein similarity scoring\n * - Results sorted by similarity score, filtered by threshold\n *\n * 3. **Similarity Scoring**\n * - Levenshtein distance normalized to 0-1 similarity ratio\n * - Dual thresholds: 50% for single candidates, 60% for multiple\n * - Prevents noise while surfacing genuinely close matches\n *\n * ## Key Design Decisions\n *\n * - **Atomic writes**: Uses temp file + rename for crash safety\n * - **Multi-edit mode**: Applies edits sequentially for deterministic results\n * - **LSP integration**: Collects diagnostics after edits for immediate feedback\n * - **Sandbox support**: Operates through sandbox abstraction when available\n *\n * @module tools/edit\n */\n\nimport crypto from \"node:crypto\";\nimport { constants } from \"node:fs\";\nimport { access, readFile, rename, unlink, writeFile } from \"node:fs/promises\";\nimport { resolve as resolvePath } from \"node:path\";\nimport { Type } from \"@sinclair/typebox\";\nimport {\n\tdetectMissionSessionRole,\n\tvalidateMissionArtifactWrite,\n} from \"../agent/mission-artifacts.js\";\nimport {\n\tcaptureDiagnosticBaseline,\n\tcollectDiagnosticDelta,\n} from \"../lsp/diagnostic-deltas.js\";\nimport {\n\ttype DiagnosticDeltaToolSummary,\n\tbuildDiagnosticDeltaToolSummary,\n\tformatDiagnosticDeltaForToolOutput,\n} from \"../lsp/diagnostic-repair.js\";\nimport { assertTeamMemoryContentSafe } from \"../memory/team-memory.js\";\nimport {\n\trequirePlanCheck,\n\trunValidatorsOnSuccess,\n} from \"../safety/safe-mode.js\";\nimport type { ValidatorRunResult } from \"../safety/safe-mode.js\";\nimport { formatLspDiagnostics, generateDiffString } from \"./diff-utils.js\";\nimport { createTool, expandUserPath } from \"./tool-dsl.js\";\n\nasync function writeFileAtomically(\n\tfilePath: string,\n\tcontents: string,\n): Promise<void> {\n\tconst tempPath = `${filePath}.${crypto.randomUUID()}.tmp`;\n\tawait writeFile(tempPath, contents, \"utf-8\");\n\ttry {\n\t\tawait rename(tempPath, filePath);\n\t} catch (error) {\n\t\tawait unlink(tempPath).catch(() => {});\n\t\tthrow error;\n\t}\n}\n\n/** Diff support lives in diff-utils for reuse */\n\ntype LineEnding = \"\\n\" | \"\\r\\n\" | \"\\r\";\n\ntype NormalizedDocument = {\n\toriginal: string;\n\tnormalized: string;\n\tbom: string;\n\tlineEnding: LineEnding;\n};\n\nfunction detectLineEnding(text: string): LineEnding {\n\tif (text.includes(\"\\r\\n\")) return \"\\r\\n\";\n\tif (text.includes(\"\\r\")) return \"\\r\";\n\treturn \"\\n\";\n}\n\nfunction normalizeDocument(content: string): NormalizedDocument {\n\tconst bom = content.startsWith(\"\\uFEFF\") ? \"\\uFEFF\" : \"\";\n\tconst withoutBom = bom ? content.slice(1) : content;\n\tconst lineEnding = detectLineEnding(withoutBom);\n\tconst normalized = withoutBom.replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\");\n\treturn { original: content, normalized, bom, lineEnding };\n}\n\nfunction normalizeEditText(text: string | undefined): string | undefined {\n\tif (text === undefined) return undefined;\n\treturn text.replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\");\n}\n\nfunction restoreDocumentContent(\n\tnormalized: string,\n\tdocument: NormalizedDocument,\n): string {\n\tconst restored =\n\t\tdocument.lineEnding === \"\\n\"\n\t\t\t? normalized\n\t\t\t: normalized.replace(/\\n/g, document.lineEnding);\n\treturn `${document.bom}${restored}`;\n}\n\nconst editOperationSchema = Type.Object({\n\toldText: Type.String({\n\t\tdescription: \"Exact text to find and replace\",\n\t\tminLength: 1,\n\t}),\n\tnewText: Type.Optional(\n\t\tType.String({\n\t\t\tdescription: \"Replacement text (omit or empty string to delete)\",\n\t\t\tdefault: \"\",\n\t\t}),\n\t),\n});\n\nconst editSchema = Type.Object({\n\tpath: Type.String({\n\t\tdescription: \"Path to the file to edit (relative or absolute)\",\n\t\tminLength: 1,\n\t}),\n\toldText: Type.Optional(\n\t\tType.String({\n\t\t\tdescription: \"Exact text to find and replace (must match exactly)\",\n\t\t\tminLength: 1,\n\t\t}),\n\t),\n\tnewText: Type.Optional(\n\t\tType.String({\n\t\t\tdescription: \"New text to replace the old text with\",\n\t\t\tdefault: \"\",\n\t\t}),\n\t),\n\tedits: Type.Optional(\n\t\tType.Array(editOperationSchema, {\n\t\t\tdescription:\n\t\t\t\t\"Multiple edits to apply sequentially (alternative to oldText/newText)\",\n\t\t\tminItems: 1,\n\t\t\tmaxItems: 50,\n\t\t}),\n\t),\n\treplaceAll: Type.Optional(\n\t\tType.Boolean({\n\t\t\tdescription:\n\t\t\t\t\"Replace all occurrences (useful for variable renaming). Cannot be used with occurrence or edits.\",\n\t\t\tdefault: false,\n\t\t}),\n\t),\n\toccurrence: Type.Optional(\n\t\tType.Integer({\n\t\t\tdescription:\n\t\t\t\t\"Which occurrence of the text to replace (1-based). Cannot be used with replaceAll or edits.\",\n\t\t\tminimum: 1,\n\t\t\tdefault: 1,\n\t\t}),\n\t),\n\tdryRun: Type.Optional(\n\t\tType.Boolean({\n\t\t\tdescription: \"Preview the diff without writing changes\",\n\t\t\tdefault: false,\n\t\t}),\n\t),\n});\n\ntype EditToolDetails = {\n\tdiff: string;\n\teditsApplied?: number;\n\tvalidators?: ValidatorRunResult[];\n\tdiagnosticDelta?: DiagnosticDeltaToolSummary;\n\tmode?: \"sandbox\";\n};\n\nexport const editTool = createTool<typeof editSchema, EditToolDetails>({\n\tname: \"edit\",\n\tlabel: \"edit\",\n\tdescription: `Edit files with find-and-replace. oldText must match exactly (whitespace, indentation, newlines).\n\nParameters:\n- path: File path\n- oldText/newText: Single edit (text to find and replacement)\n- edits: Array of {oldText, newText} for multiple sequential edits (1-50)\n- replaceAll: Replace all occurrences (default: false). For single edit only.\n- occurrence: Which match (default: 1). For single edit only.\n- dryRun: Preview only (default: false)\n\nUse either oldText/newText OR edits array, not both.\n\nBest practices:\n- Read file first to verify exact formatting\n- Include context (5-10 lines) for uniqueness\n- Match indentation style (tabs vs spaces)\n- Use dryRun for complex edits\n- Use edits array for multiple related changes (atomic)\n\nIf \"not found\", read file to check actual content.`,\n\tschema: editSchema,\n\tasync run(\n\t\t{\n\t\t\tpath,\n\t\t\toldText,\n\t\t\tnewText,\n\t\t\tedits,\n\t\t\treplaceAll = false,\n\t\t\toccurrence = 1,\n\t\t\tdryRun = false,\n\t\t},\n\t\t{ signal, respond, sandbox },\n\t) {\n\t\trequirePlanCheck(\"edit\");\n\n\t\tconst absolutePath = resolvePath(expandUserPath(path));\n\t\tconst throwIfAborted = () => {\n\t\t\tif (signal?.aborted) {\n\t\t\t\tthrow new Error(\"Operation aborted\");\n\t\t\t}\n\t\t};\n\n\t\t// Validate mutually exclusive parameters\n\t\tconst hasSingleEdit = oldText !== undefined;\n\t\t// newText with non-empty value alongside edits array is an error\n\t\t// (empty string is allowed as it's the default and harmless)\n\t\tconst hasExplicitNewText = newText !== undefined && newText !== \"\";\n\t\tconst hasMultiEdit = edits !== undefined && edits.length > 0;\n\n\t\tif ((hasSingleEdit || hasExplicitNewText) && hasMultiEdit) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Cannot use both oldText/newText and edits array. Use one or the other.\",\n\t\t\t);\n\t\t}\n\n\t\tif (!hasSingleEdit && !hasMultiEdit) {\n\t\t\tthrow new Error(\"Must provide either oldText/newText or edits array.\");\n\t\t}\n\n\t\tif (hasMultiEdit && (replaceAll || occurrence !== 1)) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Cannot use replaceAll or occurrence with edits array. These options only apply to single edits.\",\n\t\t\t);\n\t\t}\n\n\t\tif (replaceAll && occurrence !== 1) {\n\t\t\tthrow new Error(\"Cannot use both replaceAll and occurrence.\");\n\t\t}\n\n\t\tconst normalizedOldText = normalizeEditText(oldText);\n\t\tconst normalizedNewText = normalizeEditText(newText);\n\t\tconst normalizedEdits = edits?.map((edit) => ({\n\t\t\t...edit,\n\t\t\toldText: normalizeEditText(edit.oldText) ?? \"\",\n\t\t\tnewText: normalizeEditText(edit.newText),\n\t\t}));\n\n\t\t// Helper to apply edits to content (shared between sandbox and normal mode)\n\t\tconst applyEdits = (\n\t\t\toriginalContent: string,\n\t\t): { newContent: string; replacementCount: number } => {\n\t\t\tif (hasMultiEdit && normalizedEdits) {\n\t\t\t\tlet content = originalContent;\n\t\t\t\tlet editsApplied = 0;\n\t\t\t\tfor (const [index, edit] of normalizedEdits.entries()) {\n\t\t\t\t\tconst matches = findExactMatches(content, edit.oldText);\n\t\t\t\t\tif (matches.length === 0) {\n\t\t\t\t\t\tconst approx = findApproximateMatches(content, edit.oldText);\n\t\t\t\t\t\tconst suggestion = approx.length\n\t\t\t\t\t\t\t? `\\n\\nPossible matches:\\n${approx.slice(0, 3).map(formatMatchPreview).join(\"\\n\")}`\n\t\t\t\t\t\t\t: \"\";\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t`Edit #${index + 1}: Could not find text after ${editsApplied} prior edit(s).${suggestion}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (matches.length > 1) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t`Edit #${index + 1}: Found ${matches.length} matches for oldText. Provide more context. Matches at lines: ${matches.map((m) => m.line).join(\", \")}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tconst matchIndex = matches[0]?.index ?? 0;\n\t\t\t\t\tcontent =\n\t\t\t\t\t\tcontent.slice(0, matchIndex) +\n\t\t\t\t\t\t(edit.newText ?? \"\") +\n\t\t\t\t\t\tcontent.slice(matchIndex + edit.oldText.length);\n\t\t\t\t\teditsApplied++;\n\t\t\t\t}\n\t\t\t\treturn { newContent: content, replacementCount: editsApplied };\n\t\t\t}\n\t\t\t// Single edit mode\n\t\t\tif (!normalizedOldText || normalizedOldText.length === 0) {\n\t\t\t\tthrow new Error(\"oldText cannot be empty\");\n\t\t\t}\n\t\t\tconst exactMatches = findExactMatches(originalContent, normalizedOldText);\n\t\t\tif (exactMatches.length === 0) {\n\t\t\t\tconst approx = findApproximateMatches(\n\t\t\t\t\toriginalContent,\n\t\t\t\t\tnormalizedOldText,\n\t\t\t\t);\n\t\t\t\tconst suggestion = approx.length\n\t\t\t\t\t? `\\n\\nPossible matches:\\n${approx.slice(0, 3).map(formatMatchPreview).join(\"\\n\")}`\n\t\t\t\t\t: `\\n\\nTip: double-check whitespace/newlines via /diff ${path}`;\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Could not find the exact text in ${path}.${suggestion}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (replaceAll) {\n\t\t\t\tif (exactMatches.length > 10000) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Too many replacements: ${exactMatches.length} (max 10000).`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tnewContent: originalContent.replaceAll(\n\t\t\t\t\t\tnormalizedOldText,\n\t\t\t\t\t\tnormalizedNewText ?? \"\",\n\t\t\t\t\t),\n\t\t\t\t\treplacementCount: exactMatches.length,\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (occurrence > exactMatches.length) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Only ${exactMatches.length} occurrence(s) found, but #${occurrence} requested.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst targetMatch = exactMatches[occurrence - 1]!;\n\t\t\tconst matchIndex = targetMatch.index ?? 0;\n\t\t\treturn {\n\t\t\t\tnewContent:\n\t\t\t\t\toriginalContent.slice(0, matchIndex) +\n\t\t\t\t\t(normalizedNewText ?? \"\") +\n\t\t\t\t\toriginalContent.slice(matchIndex + normalizedOldText.length),\n\t\t\t\treplacementCount: 1,\n\t\t\t};\n\t\t};\n\n\t\t// Use sandbox if available\n\t\tif (sandbox) {\n\t\t\ttry {\n\t\t\t\tconst exists = await sandbox.exists(path);\n\t\t\t\tif (!exists) {\n\t\t\t\t\tthrow new Error(`File not found in sandbox: ${path}`);\n\t\t\t\t}\n\t\t\t\tconst originalContent = await sandbox.readFile(path);\n\t\t\t\tconst document = normalizeDocument(originalContent);\n\t\t\t\tconst { newContent: normalizedNewContent, replacementCount } =\n\t\t\t\t\tapplyEdits(document.normalized);\n\t\t\t\tconst newContent = restoreDocumentContent(\n\t\t\t\t\tnormalizedNewContent,\n\t\t\t\t\tdocument,\n\t\t\t\t);\n\t\t\t\tassertTeamMemoryContentSafe(absolutePath, newContent);\n\t\t\t\tconst missionArtifactWrite = validateMissionArtifactWrite({\n\t\t\t\t\tfilePath: absolutePath,\n\t\t\t\t\tcontent: newContent,\n\t\t\t\t\trole: detectMissionSessionRole(),\n\t\t\t\t});\n\t\t\t\tif (!missionArtifactWrite.ok) {\n\t\t\t\t\treturn respond.error(missionArtifactWrite.message);\n\t\t\t\t}\n\t\t\t\tconst diff = generateDiffString(originalContent, newContent);\n\n\t\t\t\tif (!dryRun) {\n\t\t\t\t\tawait sandbox.writeFile(path, newContent);\n\t\t\t\t}\n\n\t\t\t\treturn respond\n\t\t\t\t\t.text(\n\t\t\t\t\t\tdryRun\n\t\t\t\t\t\t\t? `[DRY RUN] Would apply ${replacementCount} edit(s) to ${path} in sandbox`\n\t\t\t\t\t\t\t: `Applied ${replacementCount} edit(s) to ${path} in sandbox`,\n\t\t\t\t\t)\n\t\t\t\t\t.detail({ diff, editsApplied: replacementCount, mode: \"sandbox\" });\n\t\t\t} catch (err) {\n\t\t\t\tif (err instanceof Error) throw err;\n\t\t\t\tthrow new Error(String(err));\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\tawait access(absolutePath, constants.R_OK | constants.W_OK);\n\t\t} catch {\n\t\t\t// Provide helpful hint\n\t\t\tlet hint = \"\";\n\t\t\tif (path.includes(\"//\")) {\n\t\t\t\thint = \" Hint: path contains double slashes.\";\n\t\t\t}\n\t\t\tthrow new Error(\n\t\t\t\t`File not found: ${path}.${hint} Use 'read' to verify the path exists.`,\n\t\t\t);\n\t\t}\n\n\t\tthrowIfAborted();\n\t\tconst originalContent = await readFile(absolutePath, \"utf-8\");\n\t\tthrowIfAborted();\n\t\tconst document = normalizeDocument(originalContent);\n\t\tconst { newContent: normalizedNewContent, replacementCount } = applyEdits(\n\t\t\tdocument.normalized,\n\t\t);\n\t\tconst newContent = restoreDocumentContent(normalizedNewContent, document);\n\t\tassertTeamMemoryContentSafe(absolutePath, newContent);\n\t\tconst missionArtifactWrite = validateMissionArtifactWrite({\n\t\t\tfilePath: absolutePath,\n\t\t\tcontent: newContent,\n\t\t\trole: detectMissionSessionRole(),\n\t\t});\n\t\tif (!missionArtifactWrite.ok) {\n\t\t\treturn respond.error(missionArtifactWrite.message);\n\t\t}\n\t\tconst diff = generateDiffString(originalContent, newContent);\n\n\t\tif (dryRun) {\n\t\t\tconst modeDesc = hasMultiEdit\n\t\t\t\t? `${replacementCount} edit(s)`\n\t\t\t\t: replaceAll\n\t\t\t\t\t? \"all occurrences\"\n\t\t\t\t\t: `occurrence #${occurrence}`;\n\t\t\treturn respond\n\t\t\t\t.text(`Dry run: preview for ${path} (${modeDesc}). No changes written.`)\n\t\t\t\t.detail({\n\t\t\t\t\tdiff,\n\t\t\t\t\teditsApplied: hasMultiEdit ? replacementCount : undefined,\n\t\t\t\t});\n\t\t}\n\n\t\tconst diagnosticBaseline = await captureDiagnosticBaseline(absolutePath);\n\t\tthrowIfAborted();\n\n\t\tawait writeFileAtomically(absolutePath, newContent);\n\t\tlet validatorSummaries: ValidatorRunResult[] | undefined;\n\t\tlet linterOutput = \"\";\n\t\tlet diagnosticDeltaSummary: DiagnosticDeltaToolSummary | undefined;\n\t\ttry {\n\t\t\tconst diagnosticDelta = await collectDiagnosticDelta(diagnosticBaseline);\n\t\t\tdiagnosticDeltaSummary = buildDiagnosticDeltaToolSummary({\n\t\t\t\tfile: absolutePath,\n\t\t\t\tdisplayPath: path,\n\t\t\t\tresult: diagnosticDelta,\n\t\t\t});\n\t\t\tconst visibleDiagnostics = diagnosticDelta.usedDelta\n\t\t\t\t? diagnosticDelta.newDiagnostics\n\t\t\t\t: diagnosticDelta.fileDiagnostics;\n\t\t\tif (visibleDiagnostics.length > 0) {\n\t\t\t\tlinterOutput = formatLspDiagnostics(path, visibleDiagnostics);\n\t\t\t}\n\t\t\tvalidatorSummaries = await runValidatorsOnSuccess(\n\t\t\t\t[absolutePath],\n\t\t\t\tdiagnosticDelta.validatorDiagnostics,\n\t\t\t);\n\t\t} catch (validatorError) {\n\t\t\tawait writeFileAtomically(absolutePath, originalContent);\n\t\t\tthrow validatorError;\n\t\t}\n\n\t\tthrowIfAborted();\n\n\t\tconst resultMessage = hasMultiEdit\n\t\t\t? `Successfully applied ${replacementCount} edit(s) to ${path}.`\n\t\t\t: replaceAll\n\t\t\t\t? `Successfully replaced all ${replacementCount} occurrence(s) in ${path}.`\n\t\t\t\t: `Successfully edited ${path}.`;\n\n\t\treturn respond\n\t\t\t.text(\n\t\t\t\t[\n\t\t\t\t\tresultMessage,\n\t\t\t\t\tlinterOutput,\n\t\t\t\t\tdiagnosticDeltaSummary\n\t\t\t\t\t\t? formatDiagnosticDeltaForToolOutput(diagnosticDeltaSummary)\n\t\t\t\t\t\t: \"\",\n\t\t\t\t]\n\t\t\t\t\t.filter(Boolean)\n\t\t\t\t\t.join(\"\\n\"),\n\t\t\t)\n\t\t\t.detail({\n\t\t\t\tdiff,\n\t\t\t\teditsApplied: hasMultiEdit ? replacementCount : undefined,\n\t\t\t\tvalidators: validatorSummaries,\n\t\t\t\tdiagnosticDelta: diagnosticDeltaSummary,\n\t\t\t});\n\t},\n});\n\ntype MatchPreview = {\n\tline: number;\n\tsnippet: string;\n\tindex?: number;\n\tsimilarity?: number;\n};\n\nfunction findExactMatches(content: string, snippet: string): MatchPreview[] {\n\tconst matches: MatchPreview[] = [];\n\tlet index = content.indexOf(snippet);\n\twhile (index !== -1) {\n\t\tmatches.push({\n\t\t\tline: getLineNumber(content, index),\n\t\t\tsnippet: getSnippet(content, index, snippet.length),\n\t\t\tindex,\n\t\t});\n\t\tindex = content.indexOf(snippet, index + snippet.length);\n\t}\n\treturn matches;\n}\n\n/**\n * Levenshtein Distance Algorithm - Measures string similarity via edit operations\n *\n * Computes the minimum number of single-character edits (insertions, deletions,\n * or substitutions) required to transform string `a` into string `b`. This is\n * the classic dynamic programming solution, optimized for space efficiency.\n *\n * ## Algorithm Explanation\n *\n * The standard DP approach uses a 2D matrix where cell [i,j] represents the\n * edit distance between a[0..i-1] and b[0..j-1]. The recurrence relation:\n *\n * dist[i][j] = min(\n * dist[i-1][j] + 1, // deletion: remove char from a\n * dist[i][j-1] + 1, // insertion: add char to a\n * dist[i-1][j-1] + cost // substitution: cost=0 if chars match, else 1\n * )\n *\n * ## Space Optimization\n *\n * Since each row only depends on the previous row, we use two 1D arrays instead\n * of a full matrix. This reduces space complexity from O(m*n) to O(min(m,n)).\n *\n * - `prev`: the previous row of the DP matrix\n * - `curr`: the current row being computed\n * - After each outer loop iteration, we swap the arrays\n *\n * ## Complexity\n *\n * - Time: O(m * n) where m = len(a), n = len(b)\n * - Space: O(n) - only two arrays of length n+1\n *\n * ## Usage in Edit Tool\n *\n * This function powers the fuzzy matching fallback. When an exact match fails,\n * we compute Levenshtein distance between the search text and candidate regions\n * in the file, then convert to a similarity ratio (see `similarity()` below).\n *\n * @param a - First string to compare\n * @param b - Second string to compare\n * @returns The edit distance (0 = identical, higher = more different)\n */\nfunction levenshtein(a: string, b: string): number {\n\t// Base cases: if either string is empty, distance is the length of the other\n\tif (a.length === 0) return b.length;\n\tif (b.length === 0) return a.length;\n\n\t// Space-optimized DP: maintain only two rows instead of full matrix.\n\t// `prev` holds the distances computed for the previous character of `a`.\n\t// Initialize with distances from empty string: 0, 1, 2, ..., b.length\n\tlet prev = Array.from({ length: b.length + 1 }, (_, i) => i);\n\tlet curr = new Array<number>(b.length + 1);\n\n\t// Iterate through each character of string `a`\n\tfor (let i = 1; i <= a.length; i++) {\n\t\t// Distance from a[0..i-1] to empty string is i (delete all chars)\n\t\tcurr[0] = i;\n\n\t\t// Iterate through each character of string `b`\n\t\tfor (let j = 1; j <= b.length; j++) {\n\t\t\t// Cost is 0 if characters match, 1 if they need substitution\n\t\t\tconst cost = a[i - 1] === b[j - 1] ? 0 : 1;\n\n\t\t\t// Take minimum of three possible operations:\n\t\t\tcurr[j] = Math.min(\n\t\t\t\tprev[j]! + 1, // deletion: remove a[i-1], use distance for a[0..i-2] to b[0..j-1]\n\t\t\t\tcurr[j - 1]! + 1, // insertion: insert b[j-1], use distance for a[0..i-1] to b[0..j-2]\n\t\t\t\tprev[j - 1]! + cost, // substitution: use distance for a[0..i-2] to b[0..j-2] + substitution cost\n\t\t\t);\n\t\t}\n\t\t// Swap rows: current row becomes previous for next iteration\n\t\t[prev, curr] = [curr, prev];\n\t}\n\t// After all iterations, `prev` contains the final row (due to swap)\n\treturn prev[b.length]!;\n}\n\n/**\n * Similarity Ratio - Normalizes Levenshtein distance to a 0-1 scale\n *\n * Converts the raw edit distance into an intuitive percentage where:\n * - 1.0 = identical strings (0 edits needed)\n * - 0.0 = completely different (edit distance equals max string length)\n *\n * Formula: similarity = 1 - (edit_distance / max_length)\n *\n * This normalization is crucial because raw edit distance doesn't account\n * for string length. For example, an edit distance of 5 between two 100-char\n * strings (95% similar) is very different from distance 5 between two 6-char\n * strings (17% similar).\n *\n * @param a - First string to compare\n * @param b - Second string to compare\n * @returns Similarity ratio from 0 (completely different) to 1 (identical)\n */\nfunction similarity(a: string, b: string): number {\n\tconst maxLen = Math.max(a.length, b.length);\n\t// Two empty strings are identical\n\tif (maxLen === 0) return 1;\n\t// Normalize: 0 edits = 1.0 similarity, maxLen edits = 0.0 similarity\n\treturn 1 - levenshtein(a, b) / maxLen;\n}\n\n/**\n * Similarity Thresholds for Approximate Matching\n *\n * These thresholds control which fuzzy matches are shown to the user. They're\n * intentionally different based on context to balance helpfulness vs noise.\n *\n * ## Threshold Strategy\n *\n * **Single Candidate (50%)**: When only one potential match is found, we're\n * lenient because showing something is better than nothing. Even a 50% match\n * might be the reformatted/moved code the user is looking for.\n *\n * **Multiple Candidates (60%)**: When several matches exist, we're stricter\n * to avoid overwhelming the user with noise. A higher threshold ensures only\n * genuinely relevant suggestions surface.\n *\n * ## Why These Values?\n *\n * - 50% catches significant changes (indentation, variable renames, added lines)\n * while filtering out completely unrelated code\n * - 60% for multiple matches prevents showing 3+ mediocre suggestions that\n * confuse more than they help\n * - Values chosen empirically from real-world edit failure scenarios\n */\nconst SINGLE_CANDIDATE_THRESHOLD = 0.5; // Accept single match if 50%+ similar\nconst MULTI_CANDIDATE_THRESHOLD = 0.6; // Need 60%+ to show when multiple matches\n\n/**\n * Approximate Match Finder - Multi-strategy fuzzy search for similar text\n *\n * When exact matching fails, this function attempts to find regions in the file\n * that closely resemble the search snippet. It employs two complementary strategies\n * to maximize the chances of finding the right location even when the content\n * has changed.\n *\n * ## Strategy 1: Relaxed Regex Matching\n *\n * Creates a regex that normalizes whitespace (see `buildRelaxedRegex`), then\n * finds all matches in the content. This catches cases where:\n * - Indentation changed (tabs vs spaces, different indent levels)\n * - Extra blank lines were added/removed\n * - Line wrapping changed\n *\n * ## Strategy 2: Sliding Window Line Comparison\n *\n * For multi-line snippets, slides a window of the same size through the content\n * and computes Levenshtein similarity at each position. This catches cases where:\n * - Variables were renamed\n * - Minor code changes occurred (added parameters, changed values)\n * - Content was moved but not significantly altered\n *\n * ## Deduplication\n *\n * Both strategies may find the same region; we deduplicate by line number to\n * avoid showing duplicate suggestions.\n *\n * ## Result Limits\n *\n * - Maximum 10 candidates collected (performance guard)\n * - Maximum 5 shown to user (UI clarity)\n * - Dynamic threshold based on candidate count (see threshold constants above)\n *\n * @param content - The full file content to search in\n * @param snippet - The text the user is looking for\n * @returns Array of match previews sorted by similarity, filtered by threshold\n */\nfunction findApproximateMatches(\n\tcontent: string,\n\tsnippet: string,\n): MatchPreview[] {\n\t// Strategy 1: Regex-based matching with whitespace normalization\n\tconst relaxed = buildRelaxedRegex(snippet);\n\tconst regexMatches: Array<MatchPreview & { similarity: number }> = [];\n\n\tif (relaxed) {\n\t\tlet result: RegExpExecArray | null;\n\t\t// Limit to 10 matches to prevent performance issues in large files\n\t\twhile (regexMatches.length < 10) {\n\t\t\tresult = relaxed.exec(content);\n\t\t\tif (!result) break;\n\t\t\tconst matchIndex = result.index;\n\t\t\tconst matchText = result[0];\n\t\t\t// Score each regex match by actual similarity (regex may be too permissive)\n\t\t\tconst sim = similarity(snippet.trim(), matchText.trim());\n\t\t\tregexMatches.push({\n\t\t\t\tline: getLineNumber(content, matchIndex),\n\t\t\t\tsnippet: getSnippet(content, matchIndex, matchText.length),\n\t\t\t\tsimilarity: sim,\n\t\t\t});\n\t\t}\n\t}\n\n\t// Strategy 2: Sliding window comparison for multi-line snippets\n\t// This catches renamed variables and minor changes that regex misses\n\tconst snippetLines = snippet.trim().split(\"\\n\");\n\tif (snippetLines.length > 1) {\n\t\tconst contentLines = content.split(\"\\n\");\n\t\t// Slide a window of size |snippetLines| through the content\n\t\tfor (let i = 0; i <= contentLines.length - snippetLines.length; i++) {\n\t\t\tconst candidateLines = contentLines.slice(i, i + snippetLines.length);\n\t\t\tconst candidate = candidateLines.join(\"\\n\");\n\t\t\tconst sim = similarity(snippet.trim(), candidate.trim());\n\t\t\t// Only consider if above the minimum threshold\n\t\t\tif (sim >= SINGLE_CANDIDATE_THRESHOLD) {\n\t\t\t\t// Deduplicate: don't add if we already found this line via regex\n\t\t\t\tconst lineNum = i + 1;\n\t\t\t\tif (!regexMatches.some((m) => m.line === lineNum)) {\n\t\t\t\t\tregexMatches.push({\n\t\t\t\t\t\tline: lineNum,\n\t\t\t\t\t\t// Show first 3 lines as preview to avoid overwhelming output\n\t\t\t\t\t\tsnippet: candidateLines.slice(0, 3).join(\"\\n\").trim(),\n\t\t\t\t\t\tsimilarity: sim,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Performance guard: stop after collecting 10 candidates\n\t\t\tif (regexMatches.length >= 10) break;\n\t\t}\n\t}\n\n\t// Sort all candidates by similarity (best matches first)\n\tregexMatches.sort((a, b) => b.similarity - a.similarity);\n\n\t// Apply dynamic threshold: stricter when many candidates exist\n\t// This prevents showing 5 mediocre matches when there's one good one\n\tconst threshold =\n\t\tregexMatches.length === 1\n\t\t\t? SINGLE_CANDIDATE_THRESHOLD\n\t\t\t: MULTI_CANDIDATE_THRESHOLD;\n\n\t// Return top 5 matches above threshold, stripping internal similarity score\n\treturn regexMatches\n\t\t.filter((m) => m.similarity >= threshold)\n\t\t.slice(0, 5)\n\t\t.map(({ line, snippet, similarity }) => ({ line, snippet, similarity }));\n}\n\n/**\n * Relaxed Regex Builder - Creates whitespace-normalized pattern for fuzzy matching\n *\n * Transforms a literal search string into a regex that matches the same content\n * with flexible whitespace. This is the first strategy in approximate matching.\n *\n * ## Transformation Steps\n *\n * 1. **Trim**: Remove leading/trailing whitespace (user likely copied extra)\n * 2. **Escape metacharacters**: Treat all regex special chars as literals\n * - Characters escaped: . * + ? ^ $ { } ( ) | [ ] \\\n * 3. **Normalize whitespace**: Replace all whitespace runs with `\\s+`\n * - Matches any combination of spaces, tabs, newlines\n * - Makes indentation changes transparent\n *\n * ## Example Transformation\n *\n * Input: \"function foo( a, b ) {\"\n * Regex: \"function\\s+foo\\(\\s+a,\\s+b\\s+\\)\\s+\\{\"\n * Matches: \"function foo(a, b) {\" or \"function foo( a, b ) {\"\n *\n * ## Safety Guards\n *\n * - Empty input → null (avoid matching everything)\n * - Pattern > 500 chars → null (prevent ReDoS on very long snippets)\n * - Invalid regex → null (graceful fallback to line-by-line comparison)\n *\n * @param snippet - The text to convert into a relaxed regex\n * @returns Compiled regex with 'gi' flags, or null if construction fails\n */\nfunction buildRelaxedRegex(snippet: string): RegExp | null {\n\tconst trimmed = snippet.trim();\n\t// Empty pattern would match everything - not useful\n\tif (!trimmed) return null;\n\n\t// Step 1: Escape all regex metacharacters so they match literally\n\t// This prevents \"user.name\" from being interpreted as \"user<any-char>name\"\n\tconst escaped = trimmed\n\t\t.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")\n\t\t// Step 2: Replace whitespace runs with flexible matcher\n\t\t// This makes the pattern match regardless of indentation style\n\t\t.replace(/\\s+/g, \"\\\\s+\");\n\n\t// Guard against ReDoS: very long patterns can cause exponential backtracking\n\tif (escaped.length > 500) return null;\n\n\ttry {\n\t\t// nosemgrep: javascript.lang.security.audit.detect-non-literal-regexp.detect-non-literal-regexp\n\t\t// Flags: g = global (find all), i = case-insensitive (catches renamed vars)\n\t\treturn new RegExp(escaped, \"gi\");\n\t} catch {\n\t\t// Invalid regex (shouldn't happen after escaping, but be safe)\n\t\treturn null;\n\t}\n}\n\nfunction getLineNumber(content: string, index: number): number {\n\treturn content.slice(0, index).split(\"\\n\").length;\n}\n\nfunction getSnippet(content: string, start: number, _length: number): string {\n\tconst lines = content.split(\"\\n\");\n\tconst lineNum = getLineNumber(content, start);\n\tconst startLine = Math.max(0, lineNum - 2);\n\tconst endLine = Math.min(lines.length, lineNum + 1);\n\treturn lines.slice(startLine, endLine).join(\"\\n\").trim();\n}\n\nfunction formatMatchPreview(match: MatchPreview): string {\n\tconst simPct = match.similarity\n\t\t? ` (${Math.round(match.similarity * 100)}% similar)`\n\t\t: \"\";\n\treturn `• Line ${match.line}${simPct}: ${match.snippet}`;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../src/tools/write.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;
|
|
1
|
+
{"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../src/tools/write.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AAqBH,OAAO,EACN,KAAK,0BAA0B,EAG/B,MAAM,6BAA6B,CAAC;AAMrC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAyBjE,KAAK,gBAAgB,GAAG;IACvB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAClC,eAAe,CAAC,EAAE,0BAA0B,CAAC;IAC7C,IAAI,CAAC,EAAE,SAAS,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;EAuLpB,CAAC"}
|
package/dist/tools/write.js
CHANGED
|
@@ -54,6 +54,7 @@ import { constants } from "node:fs";
|
|
|
54
54
|
import { access, mkdir, readFile, rename, rm, writeFile, } from "node:fs/promises";
|
|
55
55
|
import { dirname, resolve as resolvePath } from "node:path";
|
|
56
56
|
import { Type } from "@sinclair/typebox";
|
|
57
|
+
import { detectMissionSessionRole, validateMissionArtifactWrite, } from "../agent/mission-artifacts.js";
|
|
57
58
|
import { captureDiagnosticBaseline, collectDiagnosticDelta, } from "../lsp/diagnostic-deltas.js";
|
|
58
59
|
import { buildDiagnosticDeltaToolSummary, formatDiagnosticDeltaForToolOutput, } from "../lsp/diagnostic-repair.js";
|
|
59
60
|
import { assertTeamMemoryContentSafe } from "../memory/team-memory.js";
|
|
@@ -87,6 +88,14 @@ export const writeTool = createTool({
|
|
|
87
88
|
requirePlanCheck("write");
|
|
88
89
|
const absolutePath = resolvePath(expandUserPath(path));
|
|
89
90
|
assertTeamMemoryContentSafe(absolutePath, content);
|
|
91
|
+
const missionArtifactWrite = validateMissionArtifactWrite({
|
|
92
|
+
filePath: absolutePath,
|
|
93
|
+
content,
|
|
94
|
+
role: detectMissionSessionRole(),
|
|
95
|
+
});
|
|
96
|
+
if (!missionArtifactWrite.ok) {
|
|
97
|
+
return respond.error(missionArtifactWrite.message);
|
|
98
|
+
}
|
|
90
99
|
// Use sandbox if available
|
|
91
100
|
if (sandbox) {
|
|
92
101
|
try {
|
package/dist/tools/write.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write.js","sourceRoot":"","sources":["../../src/tools/write.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Write Tool - Safe File Writing with Validation\n *\n * This module provides a file writing tool with built-in safety features\n * including backup creation, LSP diagnostics, validator integration, and\n * sandbox support. It creates parent directories automatically.\n *\n * ## Safety Features\n *\n * - **Backup creation**: Automatically creates .bak files before overwriting\n * - **Plan checking**: Requires plan approval in safe mode\n * - **LSP integration**: Collects diagnostics after writing\n * - **Validator support**: Runs configured validators on written files\n * - **Rollback**: Restores original content if validators fail\n *\n * ## Write Flow\n *\n * ```\n * ┌─────────────────────────────────────────────────────────────┐\n * │ Write Operation Flow │\n * ├─────────────────────────────────────────────────────────────┤\n * │ 1. Check plan approval (safe mode) │\n * │ 2. Create parent directories │\n * │ 3. Read existing content (if any) │\n * │ 4. Create backup (.bak file) │\n * │ 5. Write new content │\n * │ 6. Collect LSP diagnostics │\n * │ 7. Run validators │\n * │ 8. If validators fail → restore backup │\n * │ 9. Return success with diff preview │\n * └─────────────────────────────────────────────────────────────┘\n * ```\n *\n * ## Sandbox Mode\n *\n * When running in a sandbox environment, the tool uses the sandbox's\n * virtual filesystem instead of the real filesystem.\n *\n * ## Example\n *\n * ```typescript\n * // Write a new file\n * writeTool.execute('call-id', {\n * path: 'src/utils/helper.ts',\n * content: 'export function helper() { return 42; }',\n * backup: true,\n * previewDiff: true,\n * });\n * ```\n *\n * @module tools/write\n */\n\nimport { constants } from \"node:fs\";\nimport {\n\taccess,\n\tmkdir,\n\treadFile,\n\trename,\n\trm,\n\twriteFile,\n} from \"node:fs/promises\";\nimport { dirname, resolve as resolvePath } from \"node:path\";\nimport { Type } from \"@sinclair/typebox\";\nimport {\n\tcaptureDiagnosticBaseline,\n\tcollectDiagnosticDelta,\n} from \"../lsp/diagnostic-deltas.js\";\nimport {\n\ttype DiagnosticDeltaToolSummary,\n\tbuildDiagnosticDeltaToolSummary,\n\tformatDiagnosticDeltaForToolOutput,\n} from \"../lsp/diagnostic-repair.js\";\nimport { assertTeamMemoryContentSafe } from \"../memory/team-memory.js\";\nimport {\n\trequirePlanCheck,\n\trunValidatorsOnSuccess,\n} from \"../safety/safe-mode.js\";\nimport type { ValidatorRunResult } from \"../safety/safe-mode.js\";\nimport { formatLspDiagnostics, generateDiffString } from \"./diff-utils.js\";\nimport { createTool, expandUserPath } from \"./tool-dsl.js\";\n\nconst writeSchema = Type.Object({\n\tpath: Type.String({\n\t\tdescription: \"Path to the file to write (relative or absolute)\",\n\t\tminLength: 1,\n\t}),\n\tcontent: Type.String({\n\t\tdescription: \"Content to write to the file\",\n\t\tdefault: \"\",\n\t}),\n\tpreviewDiff: Type.Boolean({\n\t\tdescription:\n\t\t\t\"If true, return the diff between previous content and new content (when file exists)\",\n\t\tdefault: true,\n\t}),\n\tbackup: Type.Boolean({\n\t\tdescription:\n\t\t\t\"If true, writes a .bak copy alongside the file before overwriting\",\n\t\tdefault: true,\n\t}),\n});\n\ntype WriteToolDetails = {\n\tpreviousExists?: boolean;\n\tbytesWritten?: number;\n\tdiff?: string;\n\tbackupPath?: string;\n\tvalidators?: ValidatorRunResult[];\n\tdiagnosticDelta?: DiagnosticDeltaToolSummary;\n\tmode?: \"sandbox\";\n};\n\nexport const writeTool = createTool<typeof writeSchema, WriteToolDetails>({\n\tname: \"write\",\n\tlabel: \"write\",\n\tdescription:\n\t\t\"Write content to a file. Creates the file if it doesn't exist, overwrites if it does. Automatically creates parent directories.\",\n\tschema: writeSchema,\n\tasync run(\n\t\t{ path, content, previewDiff = true, backup = true },\n\t\t{ signal, respond, sandbox },\n\t) {\n\t\trequirePlanCheck(\"write\");\n\t\tconst absolutePath = resolvePath(expandUserPath(path));\n\t\tassertTeamMemoryContentSafe(absolutePath, content);\n\n\t\t// Use sandbox if available\n\t\tif (sandbox) {\n\t\t\ttry {\n\t\t\t\tlet previousContent: string | null = null;\n\t\t\t\ttry {\n\t\t\t\t\tif (await sandbox.exists(path)) {\n\t\t\t\t\t\tpreviousContent = await sandbox.readFile(path);\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// File doesn't exist\n\t\t\t\t}\n\n\t\t\t\tawait sandbox.writeFile(path, content);\n\n\t\t\t\tconst diff =\n\t\t\t\t\tpreviousContent !== null && previewDiff\n\t\t\t\t\t\t? generateDiffString(previousContent, content)\n\t\t\t\t\t\t: undefined;\n\n\t\t\t\treturn respond\n\t\t\t\t\t.text(\n\t\t\t\t\t\tpreviousContent !== null\n\t\t\t\t\t\t\t? `Updated ${path} in sandbox`\n\t\t\t\t\t\t\t: `Created ${path} in sandbox`,\n\t\t\t\t\t)\n\t\t\t\t\t.detail({ diff, mode: \"sandbox\" });\n\t\t\t} catch (err) {\n\t\t\t\treturn respond.error(\n\t\t\t\t\t`Failed to write file in sandbox: ${err instanceof Error ? err.message : String(err)}`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tconst dir = dirname(absolutePath);\n\t\tconst ensureNotAborted = () => {\n\t\t\tif (signal?.aborted) {\n\t\t\t\tthrow new Error(\"Operation aborted\");\n\t\t\t}\n\t\t};\n\n\t\tensureNotAborted();\n\t\tawait mkdir(dir, { recursive: true });\n\t\tensureNotAborted();\n\n\t\tlet previousContent: string | null = null;\n\t\tlet backupPath: string | undefined;\n\t\tlet previousExists = false;\n\n\t\ttry {\n\t\t\tawait access(absolutePath, constants.R_OK);\n\t\t\tpreviousContent = await readFile(absolutePath, \"utf-8\");\n\t\t\tpreviousExists = true;\n\t\t} catch {\n\t\t\tpreviousExists = false;\n\t\t}\n\n\t\tensureNotAborted();\n\n\t\tconst diagnosticBaseline = await captureDiagnosticBaseline(absolutePath);\n\t\tensureNotAborted();\n\n\t\tlet movedToBackup = false;\n\t\tif (previousExists && backup && previousContent !== null) {\n\t\t\tbackupPath = `${absolutePath}.bak`;\n\t\t\ttry {\n\t\t\t\tawait rename(absolutePath, backupPath);\n\t\t\t\tmovedToBackup = true;\n\t\t\t} catch {\n\t\t\t\tawait writeFile(backupPath, previousContent, \"utf-8\");\n\t\t\t}\n\t\t}\n\n\t\tensureNotAborted();\n\n\t\ttry {\n\t\t\tawait writeFile(absolutePath, content, \"utf-8\");\n\t\t} catch (error) {\n\t\t\tif (movedToBackup && backupPath) {\n\t\t\t\ttry {\n\t\t\t\t\tawait rename(backupPath, absolutePath);\n\t\t\t\t} catch {\n\t\t\t\t\t// Best-effort restore; ignore restore errors\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\n\t\tensureNotAborted();\n\n\t\tconst diff =\n\t\t\tpreviousContent !== null && previewDiff\n\t\t\t\t? generateDiffString(previousContent, content)\n\t\t\t\t: undefined;\n\n\t\tlet validatorSummaries: ValidatorRunResult[] | undefined;\n\t\tlet linterOutput = \"\";\n\t\tlet diagnosticDeltaSummary: DiagnosticDeltaToolSummary | undefined;\n\t\ttry {\n\t\t\tconst diagnosticDelta = await collectDiagnosticDelta(diagnosticBaseline);\n\t\t\tdiagnosticDeltaSummary = buildDiagnosticDeltaToolSummary({\n\t\t\t\tfile: absolutePath,\n\t\t\t\tdisplayPath: path,\n\t\t\t\tresult: diagnosticDelta,\n\t\t\t});\n\t\t\tconst visibleDiagnostics = diagnosticDelta.usedDelta\n\t\t\t\t? diagnosticDelta.newDiagnostics\n\t\t\t\t: diagnosticDelta.fileDiagnostics;\n\t\t\tif (visibleDiagnostics.length > 0) {\n\t\t\t\tlinterOutput = formatLspDiagnostics(path, visibleDiagnostics);\n\t\t\t}\n\n\t\t\tvalidatorSummaries = await runValidatorsOnSuccess(\n\t\t\t\t[absolutePath],\n\t\t\t\tdiagnosticDelta.validatorDiagnostics,\n\t\t\t);\n\t\t} catch (validatorError) {\n\t\t\tif (movedToBackup && backupPath) {\n\t\t\t\tawait rename(backupPath, absolutePath);\n\t\t\t} else if (!previousExists) {\n\t\t\t\tawait rm(absolutePath, { force: true });\n\t\t\t} else if (previousContent !== null) {\n\t\t\t\tawait writeFile(absolutePath, previousContent, \"utf-8\");\n\t\t\t}\n\t\t\tthrow validatorError;\n\t\t}\n\n\t\tconst summaryLines: string[] = [];\n\t\tsummaryLines.push(`Successfully wrote ${content.length} bytes to ${path}`);\n\t\tif (previousExists) {\n\t\t\tsummaryLines.push(\"Previous content was overwritten.\");\n\t\t\tif (backupPath) {\n\t\t\t\tsummaryLines.push(`Backup saved to ${backupPath}`);\n\t\t\t}\n\t\t\tif (diff) {\n\t\t\t\tsummaryLines.push(\"Diff preview available in tool details.\");\n\t\t\t}\n\t\t} else {\n\t\t\tsummaryLines.push(\"File did not exist; it was created.\");\n\t\t}\n\n\t\tif (linterOutput) {\n\t\t\tsummaryLines.push(linterOutput);\n\t\t}\n\t\tif (diagnosticDeltaSummary) {\n\t\t\tconst diagnosticDeltaOutput = formatDiagnosticDeltaForToolOutput(\n\t\t\t\tdiagnosticDeltaSummary,\n\t\t\t);\n\t\t\tif (diagnosticDeltaOutput) {\n\t\t\t\tsummaryLines.push(diagnosticDeltaOutput);\n\t\t\t}\n\t\t}\n\n\t\treturn respond.text(summaryLines.join(\"\\n\")).detail({\n\t\t\tpreviousExists,\n\t\t\tbytesWritten: Buffer.byteLength(content, \"utf-8\"),\n\t\t\tdiff,\n\t\t\tbackupPath,\n\t\t\tvalidators: validatorSummaries,\n\t\t\tdiagnosticDelta: diagnosticDeltaSummary,\n\t\t});\n\t},\n});\n"]}
|
|
1
|
+
{"version":3,"file":"write.js","sourceRoot":"","sources":["../../src/tools/write.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Write Tool - Safe File Writing with Validation\n *\n * This module provides a file writing tool with built-in safety features\n * including backup creation, LSP diagnostics, validator integration, and\n * sandbox support. It creates parent directories automatically.\n *\n * ## Safety Features\n *\n * - **Backup creation**: Automatically creates .bak files before overwriting\n * - **Plan checking**: Requires plan approval in safe mode\n * - **LSP integration**: Collects diagnostics after writing\n * - **Validator support**: Runs configured validators on written files\n * - **Rollback**: Restores original content if validators fail\n *\n * ## Write Flow\n *\n * ```\n * ┌─────────────────────────────────────────────────────────────┐\n * │ Write Operation Flow │\n * ├─────────────────────────────────────────────────────────────┤\n * │ 1. Check plan approval (safe mode) │\n * │ 2. Create parent directories │\n * │ 3. Read existing content (if any) │\n * │ 4. Create backup (.bak file) │\n * │ 5. Write new content │\n * │ 6. Collect LSP diagnostics │\n * │ 7. Run validators │\n * │ 8. If validators fail → restore backup │\n * │ 9. Return success with diff preview │\n * └─────────────────────────────────────────────────────────────┘\n * ```\n *\n * ## Sandbox Mode\n *\n * When running in a sandbox environment, the tool uses the sandbox's\n * virtual filesystem instead of the real filesystem.\n *\n * ## Example\n *\n * ```typescript\n * // Write a new file\n * writeTool.execute('call-id', {\n * path: 'src/utils/helper.ts',\n * content: 'export function helper() { return 42; }',\n * backup: true,\n * previewDiff: true,\n * });\n * ```\n *\n * @module tools/write\n */\n\nimport { constants } from \"node:fs\";\nimport {\n\taccess,\n\tmkdir,\n\treadFile,\n\trename,\n\trm,\n\twriteFile,\n} from \"node:fs/promises\";\nimport { dirname, resolve as resolvePath } from \"node:path\";\nimport { Type } from \"@sinclair/typebox\";\nimport {\n\tdetectMissionSessionRole,\n\tvalidateMissionArtifactWrite,\n} from \"../agent/mission-artifacts.js\";\nimport {\n\tcaptureDiagnosticBaseline,\n\tcollectDiagnosticDelta,\n} from \"../lsp/diagnostic-deltas.js\";\nimport {\n\ttype DiagnosticDeltaToolSummary,\n\tbuildDiagnosticDeltaToolSummary,\n\tformatDiagnosticDeltaForToolOutput,\n} from \"../lsp/diagnostic-repair.js\";\nimport { assertTeamMemoryContentSafe } from \"../memory/team-memory.js\";\nimport {\n\trequirePlanCheck,\n\trunValidatorsOnSuccess,\n} from \"../safety/safe-mode.js\";\nimport type { ValidatorRunResult } from \"../safety/safe-mode.js\";\nimport { formatLspDiagnostics, generateDiffString } from \"./diff-utils.js\";\nimport { createTool, expandUserPath } from \"./tool-dsl.js\";\n\nconst writeSchema = Type.Object({\n\tpath: Type.String({\n\t\tdescription: \"Path to the file to write (relative or absolute)\",\n\t\tminLength: 1,\n\t}),\n\tcontent: Type.String({\n\t\tdescription: \"Content to write to the file\",\n\t\tdefault: \"\",\n\t}),\n\tpreviewDiff: Type.Boolean({\n\t\tdescription:\n\t\t\t\"If true, return the diff between previous content and new content (when file exists)\",\n\t\tdefault: true,\n\t}),\n\tbackup: Type.Boolean({\n\t\tdescription:\n\t\t\t\"If true, writes a .bak copy alongside the file before overwriting\",\n\t\tdefault: true,\n\t}),\n});\n\ntype WriteToolDetails = {\n\tpreviousExists?: boolean;\n\tbytesWritten?: number;\n\tdiff?: string;\n\tbackupPath?: string;\n\tvalidators?: ValidatorRunResult[];\n\tdiagnosticDelta?: DiagnosticDeltaToolSummary;\n\tmode?: \"sandbox\";\n};\n\nexport const writeTool = createTool<typeof writeSchema, WriteToolDetails>({\n\tname: \"write\",\n\tlabel: \"write\",\n\tdescription:\n\t\t\"Write content to a file. Creates the file if it doesn't exist, overwrites if it does. Automatically creates parent directories.\",\n\tschema: writeSchema,\n\tasync run(\n\t\t{ path, content, previewDiff = true, backup = true },\n\t\t{ signal, respond, sandbox },\n\t) {\n\t\trequirePlanCheck(\"write\");\n\t\tconst absolutePath = resolvePath(expandUserPath(path));\n\t\tassertTeamMemoryContentSafe(absolutePath, content);\n\t\tconst missionArtifactWrite = validateMissionArtifactWrite({\n\t\t\tfilePath: absolutePath,\n\t\t\tcontent,\n\t\t\trole: detectMissionSessionRole(),\n\t\t});\n\t\tif (!missionArtifactWrite.ok) {\n\t\t\treturn respond.error(missionArtifactWrite.message);\n\t\t}\n\n\t\t// Use sandbox if available\n\t\tif (sandbox) {\n\t\t\ttry {\n\t\t\t\tlet previousContent: string | null = null;\n\t\t\t\ttry {\n\t\t\t\t\tif (await sandbox.exists(path)) {\n\t\t\t\t\t\tpreviousContent = await sandbox.readFile(path);\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// File doesn't exist\n\t\t\t\t}\n\n\t\t\t\tawait sandbox.writeFile(path, content);\n\n\t\t\t\tconst diff =\n\t\t\t\t\tpreviousContent !== null && previewDiff\n\t\t\t\t\t\t? generateDiffString(previousContent, content)\n\t\t\t\t\t\t: undefined;\n\n\t\t\t\treturn respond\n\t\t\t\t\t.text(\n\t\t\t\t\t\tpreviousContent !== null\n\t\t\t\t\t\t\t? `Updated ${path} in sandbox`\n\t\t\t\t\t\t\t: `Created ${path} in sandbox`,\n\t\t\t\t\t)\n\t\t\t\t\t.detail({ diff, mode: \"sandbox\" });\n\t\t\t} catch (err) {\n\t\t\t\treturn respond.error(\n\t\t\t\t\t`Failed to write file in sandbox: ${err instanceof Error ? err.message : String(err)}`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tconst dir = dirname(absolutePath);\n\t\tconst ensureNotAborted = () => {\n\t\t\tif (signal?.aborted) {\n\t\t\t\tthrow new Error(\"Operation aborted\");\n\t\t\t}\n\t\t};\n\n\t\tensureNotAborted();\n\t\tawait mkdir(dir, { recursive: true });\n\t\tensureNotAborted();\n\n\t\tlet previousContent: string | null = null;\n\t\tlet backupPath: string | undefined;\n\t\tlet previousExists = false;\n\n\t\ttry {\n\t\t\tawait access(absolutePath, constants.R_OK);\n\t\t\tpreviousContent = await readFile(absolutePath, \"utf-8\");\n\t\t\tpreviousExists = true;\n\t\t} catch {\n\t\t\tpreviousExists = false;\n\t\t}\n\n\t\tensureNotAborted();\n\n\t\tconst diagnosticBaseline = await captureDiagnosticBaseline(absolutePath);\n\t\tensureNotAborted();\n\n\t\tlet movedToBackup = false;\n\t\tif (previousExists && backup && previousContent !== null) {\n\t\t\tbackupPath = `${absolutePath}.bak`;\n\t\t\ttry {\n\t\t\t\tawait rename(absolutePath, backupPath);\n\t\t\t\tmovedToBackup = true;\n\t\t\t} catch {\n\t\t\t\tawait writeFile(backupPath, previousContent, \"utf-8\");\n\t\t\t}\n\t\t}\n\n\t\tensureNotAborted();\n\n\t\ttry {\n\t\t\tawait writeFile(absolutePath, content, \"utf-8\");\n\t\t} catch (error) {\n\t\t\tif (movedToBackup && backupPath) {\n\t\t\t\ttry {\n\t\t\t\t\tawait rename(backupPath, absolutePath);\n\t\t\t\t} catch {\n\t\t\t\t\t// Best-effort restore; ignore restore errors\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\n\t\tensureNotAborted();\n\n\t\tconst diff =\n\t\t\tpreviousContent !== null && previewDiff\n\t\t\t\t? generateDiffString(previousContent, content)\n\t\t\t\t: undefined;\n\n\t\tlet validatorSummaries: ValidatorRunResult[] | undefined;\n\t\tlet linterOutput = \"\";\n\t\tlet diagnosticDeltaSummary: DiagnosticDeltaToolSummary | undefined;\n\t\ttry {\n\t\t\tconst diagnosticDelta = await collectDiagnosticDelta(diagnosticBaseline);\n\t\t\tdiagnosticDeltaSummary = buildDiagnosticDeltaToolSummary({\n\t\t\t\tfile: absolutePath,\n\t\t\t\tdisplayPath: path,\n\t\t\t\tresult: diagnosticDelta,\n\t\t\t});\n\t\t\tconst visibleDiagnostics = diagnosticDelta.usedDelta\n\t\t\t\t? diagnosticDelta.newDiagnostics\n\t\t\t\t: diagnosticDelta.fileDiagnostics;\n\t\t\tif (visibleDiagnostics.length > 0) {\n\t\t\t\tlinterOutput = formatLspDiagnostics(path, visibleDiagnostics);\n\t\t\t}\n\n\t\t\tvalidatorSummaries = await runValidatorsOnSuccess(\n\t\t\t\t[absolutePath],\n\t\t\t\tdiagnosticDelta.validatorDiagnostics,\n\t\t\t);\n\t\t} catch (validatorError) {\n\t\t\tif (movedToBackup && backupPath) {\n\t\t\t\tawait rename(backupPath, absolutePath);\n\t\t\t} else if (!previousExists) {\n\t\t\t\tawait rm(absolutePath, { force: true });\n\t\t\t} else if (previousContent !== null) {\n\t\t\t\tawait writeFile(absolutePath, previousContent, \"utf-8\");\n\t\t\t}\n\t\t\tthrow validatorError;\n\t\t}\n\n\t\tconst summaryLines: string[] = [];\n\t\tsummaryLines.push(`Successfully wrote ${content.length} bytes to ${path}`);\n\t\tif (previousExists) {\n\t\t\tsummaryLines.push(\"Previous content was overwritten.\");\n\t\t\tif (backupPath) {\n\t\t\t\tsummaryLines.push(`Backup saved to ${backupPath}`);\n\t\t\t}\n\t\t\tif (diff) {\n\t\t\t\tsummaryLines.push(\"Diff preview available in tool details.\");\n\t\t\t}\n\t\t} else {\n\t\t\tsummaryLines.push(\"File did not exist; it was created.\");\n\t\t}\n\n\t\tif (linterOutput) {\n\t\t\tsummaryLines.push(linterOutput);\n\t\t}\n\t\tif (diagnosticDeltaSummary) {\n\t\t\tconst diagnosticDeltaOutput = formatDiagnosticDeltaForToolOutput(\n\t\t\t\tdiagnosticDeltaSummary,\n\t\t\t);\n\t\t\tif (diagnosticDeltaOutput) {\n\t\t\t\tsummaryLines.push(diagnosticDeltaOutput);\n\t\t\t}\n\t\t}\n\n\t\treturn respond.text(summaryLines.join(\"\\n\")).detail({\n\t\t\tpreviousExists,\n\t\t\tbytesWritten: Buffer.byteLength(content, \"utf-8\"),\n\t\t\tdiff,\n\t\t\tbackupPath,\n\t\t\tvalidators: validatorSummaries,\n\t\t\tdiagnosticDelta: diagnosticDeltaSummary,\n\t\t});\n\t},\n});\n"]}
|
package/dist/undo/tracker.d.ts
CHANGED
|
@@ -62,6 +62,11 @@ export declare class ChangeTracker {
|
|
|
62
62
|
skipped: number;
|
|
63
63
|
errors: string[];
|
|
64
64
|
};
|
|
65
|
+
/**
|
|
66
|
+
* Delete a checkpoint by name.
|
|
67
|
+
* @returns true if a checkpoint was removed, false if none matched.
|
|
68
|
+
*/
|
|
69
|
+
deleteCheckpoint(name: string): boolean;
|
|
65
70
|
/**
|
|
66
71
|
* Clear all tracked changes.
|
|
67
72
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tracker.d.ts","sourceRoot":"","sources":["../../src/undo/tracker.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,OAAO,KAAK,EACX,kBAAkB,EAClB,UAAU,EACV,UAAU,EACV,UAAU,EACV,WAAW,EACX,MAAM,YAAY,CAAC;AA6CpB;;GAEG;AACH,qBAAa,aAAa;IACzB,OAAO,CAAC,KAAK,CAAqB;gBAEtB,UAAU,SAAsB;IAQ5C;;;OAGG;IACH,YAAY,CACX,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,MAAM,GAChB,MAAM;IA8CT;;;OAGG;IACH,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAqBtC;;OAEG;IACH,UAAU,CAAC,OAAO,CAAC,EAAE;QACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,IAAI,CAAC,EAAE,MAAM,CAAC;KACd,GAAG,UAAU,EAAE;IAiBhB;;OAEG;IACH,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,EAAE;IAI3C;;OAEG;IACH,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW;IA0CvC;;;OAGG;IACH,IAAI,CACH,KAAK,EAAE,MAAM,EACb,KAAK,UAAQ,GACX;QACF,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,EAAE,CAAC;KACjB;IA2ED;;OAEG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,UAAU;IAwBhE;;OAEG;IACH,cAAc,IAAI,UAAU,EAAE;IAI9B;;OAEG;IACH,iBAAiB,CAChB,IAAI,EAAE,MAAM,EACZ,KAAK,UAAQ,GACX;QACF,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,EAAE,CAAC;KACjB;IA0BD;;OAEG;IACH,KAAK,IAAI,IAAI;IAMb;;OAEG;IACH,QAAQ,IAAI;QACX,YAAY,EAAE,MAAM,CAAC;QACrB,WAAW,EAAE,MAAM,CAAC;QACpB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC/B,MAAM,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;KACnC;IAqBD;;OAEG;IACH,MAAM,IAAI,kBAAkB;IAI5B;;OAEG;IACH,MAAM,CAAC,KAAK,EAAE,kBAAkB,GAAG,IAAI;CAGvC;AAKD,wBAAgB,gBAAgB,IAAI,aAAa,CAKhD;AAED,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC"}
|
|
1
|
+
{"version":3,"file":"tracker.d.ts","sourceRoot":"","sources":["../../src/undo/tracker.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,OAAO,KAAK,EACX,kBAAkB,EAClB,UAAU,EACV,UAAU,EACV,UAAU,EACV,WAAW,EACX,MAAM,YAAY,CAAC;AA6CpB;;GAEG;AACH,qBAAa,aAAa;IACzB,OAAO,CAAC,KAAK,CAAqB;gBAEtB,UAAU,SAAsB;IAQ5C;;;OAGG;IACH,YAAY,CACX,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,MAAM,GAChB,MAAM;IA8CT;;;OAGG;IACH,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAqBtC;;OAEG;IACH,UAAU,CAAC,OAAO,CAAC,EAAE;QACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,IAAI,CAAC,EAAE,MAAM,CAAC;KACd,GAAG,UAAU,EAAE;IAiBhB;;OAEG;IACH,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,EAAE;IAI3C;;OAEG;IACH,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW;IA0CvC;;;OAGG;IACH,IAAI,CACH,KAAK,EAAE,MAAM,EACb,KAAK,UAAQ,GACX;QACF,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,EAAE,CAAC;KACjB;IA2ED;;OAEG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,UAAU;IAwBhE;;OAEG;IACH,cAAc,IAAI,UAAU,EAAE;IAI9B;;OAEG;IACH,iBAAiB,CAChB,IAAI,EAAE,MAAM,EACZ,KAAK,UAAQ,GACX;QACF,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,EAAE,CAAC;KACjB;IA0BD;;;OAGG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAYvC;;OAEG;IACH,KAAK,IAAI,IAAI;IAMb;;OAEG;IACH,QAAQ,IAAI;QACX,YAAY,EAAE,MAAM,CAAC;QACrB,WAAW,EAAE,MAAM,CAAC;QACpB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC/B,MAAM,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;KACnC;IAqBD;;OAEG;IACH,MAAM,IAAI,kBAAkB;IAI5B;;OAEG;IACH,MAAM,CAAC,KAAK,EAAE,kBAAkB,GAAG,IAAI;CAGvC;AAKD,wBAAgB,gBAAgB,IAAI,aAAa,CAKhD;AAED,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC"}
|
package/dist/undo/tracker.js
CHANGED
|
@@ -309,6 +309,19 @@ export class ChangeTracker {
|
|
|
309
309
|
}
|
|
310
310
|
return this.undo(changesToUndo, force);
|
|
311
311
|
}
|
|
312
|
+
/**
|
|
313
|
+
* Delete a checkpoint by name.
|
|
314
|
+
* @returns true if a checkpoint was removed, false if none matched.
|
|
315
|
+
*/
|
|
316
|
+
deleteCheckpoint(name) {
|
|
317
|
+
const before = this.state.checkpoints.length;
|
|
318
|
+
this.state.checkpoints = this.state.checkpoints.filter((cp) => cp.name !== name);
|
|
319
|
+
const removed = this.state.checkpoints.length < before;
|
|
320
|
+
if (removed) {
|
|
321
|
+
logger.info("Checkpoint deleted", { name });
|
|
322
|
+
}
|
|
323
|
+
return removed;
|
|
324
|
+
}
|
|
312
325
|
/**
|
|
313
326
|
* Clear all tracked changes.
|
|
314
327
|
*/
|