@qduc/term2 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent.d.ts +1 -1
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +53 -7
- package/dist/agent.js.map +1 -1
- package/dist/agent.test.js +122 -10
- package/dist/agent.test.js.map +1 -1
- package/dist/app.d.ts +13 -0
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +63 -16
- package/dist/app.js.map +1 -1
- package/dist/app.startup-banner.test.js +48 -1
- package/dist/app.startup-banner.test.js.map +1 -1
- package/dist/cli.js +197 -28
- package/dist/cli.js.map +1 -1
- package/dist/components/ApprovalPrompt.d.ts.map +1 -1
- package/dist/components/ApprovalPrompt.js +11 -35
- package/dist/components/ApprovalPrompt.js.map +1 -1
- package/dist/components/Banner.d.ts.map +1 -1
- package/dist/components/Banner.js +2 -7
- package/dist/components/Banner.js.map +1 -1
- package/dist/components/BottomArea.d.ts +7 -1
- package/dist/components/BottomArea.d.ts.map +1 -1
- package/dist/components/BottomArea.js +2 -2
- package/dist/components/BottomArea.js.map +1 -1
- package/dist/components/CommandMessage.d.ts.map +1 -1
- package/dist/components/CommandMessage.js +38 -42
- package/dist/components/CommandMessage.js.map +1 -1
- package/dist/components/CommandMessage.test.js +69 -0
- package/dist/components/CommandMessage.test.js.map +1 -1
- package/dist/components/DiffView.d.ts +7 -0
- package/dist/components/DiffView.d.ts.map +1 -0
- package/dist/components/DiffView.js +80 -0
- package/dist/components/DiffView.js.map +1 -0
- package/dist/components/DiffView.test.d.ts +2 -0
- package/dist/components/DiffView.test.d.ts.map +1 -0
- package/dist/components/DiffView.test.js +45 -0
- package/dist/components/DiffView.test.js.map +1 -0
- package/dist/components/Input/PopupManager.d.ts +7 -0
- package/dist/components/Input/PopupManager.d.ts.map +1 -1
- package/dist/components/Input/PopupManager.js +4 -2
- package/dist/components/Input/PopupManager.js.map +1 -1
- package/dist/components/Input/determine-active-menu.d.ts.map +1 -1
- package/dist/components/Input/determine-active-menu.js +4 -1
- package/dist/components/Input/determine-active-menu.js.map +1 -1
- package/dist/components/Input/popup-props.d.ts +3 -1
- package/dist/components/Input/popup-props.d.ts.map +1 -1
- package/dist/components/Input/popup-props.js +7 -1
- package/dist/components/Input/popup-props.js.map +1 -1
- package/dist/components/InputBox.d.ts +6 -0
- package/dist/components/InputBox.d.ts.map +1 -1
- package/dist/components/InputBox.js +74 -11
- package/dist/components/InputBox.js.map +1 -1
- package/dist/components/InputBox.menu-logic.test.js +16 -1
- package/dist/components/InputBox.menu-logic.test.js.map +1 -1
- package/dist/components/InputBox.test.js +1 -0
- package/dist/components/InputBox.test.js.map +1 -1
- package/dist/components/MarkdownRenderer.d.ts.map +1 -1
- package/dist/components/MarkdownRenderer.js +52 -1
- package/dist/components/MarkdownRenderer.js.map +1 -1
- package/dist/components/MessageList.d.ts.map +1 -1
- package/dist/components/MessageList.js +3 -2
- package/dist/components/MessageList.js.map +1 -1
- package/dist/components/MessageList.test.js +16 -0
- package/dist/components/MessageList.test.js.map +1 -1
- package/dist/components/SettingsValueSelectionMenu.d.ts.map +1 -1
- package/dist/components/SettingsValueSelectionMenu.js +4 -1
- package/dist/components/SettingsValueSelectionMenu.js.map +1 -1
- package/dist/components/StatusBar.d.ts.map +1 -1
- package/dist/components/StatusBar.js +5 -3
- package/dist/components/StatusBar.js.map +1 -1
- package/dist/components/StatusBar.test.js +24 -0
- package/dist/components/StatusBar.test.js.map +1 -1
- package/dist/components/SubagentActivityMessage.d.ts.map +1 -1
- package/dist/components/SubagentActivityMessage.js +16 -1
- package/dist/components/SubagentActivityMessage.js.map +1 -1
- package/dist/components/UndoSelectionMenu.d.ts +12 -0
- package/dist/components/UndoSelectionMenu.d.ts.map +1 -0
- package/dist/components/UndoSelectionMenu.js +46 -0
- package/dist/components/UndoSelectionMenu.js.map +1 -0
- package/dist/components/UndoSelectionMenu.test.d.ts +2 -0
- package/dist/components/UndoSelectionMenu.test.d.ts.map +1 -0
- package/dist/components/UndoSelectionMenu.test.js +40 -0
- package/dist/components/UndoSelectionMenu.test.js.map +1 -0
- package/dist/components/theme.d.ts +1 -1
- package/dist/components/theme.d.ts.map +1 -1
- package/dist/components/theme.js +1 -3
- package/dist/components/theme.js.map +1 -1
- package/dist/context/InputContext.d.ts +1 -1
- package/dist/context/InputContext.d.ts.map +1 -1
- package/dist/context/InputContext.js.map +1 -1
- package/dist/hooks/use-app-commands.d.ts +14 -2
- package/dist/hooks/use-app-commands.d.ts.map +1 -1
- package/dist/hooks/use-app-commands.js +115 -32
- package/dist/hooks/use-app-commands.js.map +1 -1
- package/dist/hooks/use-app-commands.test.js +231 -1
- package/dist/hooks/use-app-commands.test.js.map +1 -1
- package/dist/hooks/use-conversation.d.ts +8 -1
- package/dist/hooks/use-conversation.d.ts.map +1 -1
- package/dist/hooks/use-conversation.js +79 -2
- package/dist/hooks/use-conversation.js.map +1 -1
- package/dist/hooks/use-conversation.resume.test.d.ts +2 -0
- package/dist/hooks/use-conversation.resume.test.d.ts.map +1 -0
- package/dist/hooks/use-conversation.resume.test.js +26 -0
- package/dist/hooks/use-conversation.resume.test.js.map +1 -0
- package/dist/hooks/use-escape-key.d.ts.map +1 -1
- package/dist/hooks/use-escape-key.js +14 -7
- package/dist/hooks/use-escape-key.js.map +1 -1
- package/dist/hooks/use-escape-key.test.js +168 -4
- package/dist/hooks/use-escape-key.test.js.map +1 -1
- package/dist/hooks/use-input-history.d.ts +4 -3
- package/dist/hooks/use-input-history.d.ts.map +1 -1
- package/dist/hooks/use-input-history.js +10 -8
- package/dist/hooks/use-input-history.js.map +1 -1
- package/dist/hooks/use-input-history.test.d.ts +2 -0
- package/dist/hooks/use-input-history.test.d.ts.map +1 -0
- package/dist/hooks/use-input-history.test.js +43 -0
- package/dist/hooks/use-input-history.test.js.map +1 -0
- package/dist/hooks/use-mode-handlers.d.ts +10 -2
- package/dist/hooks/use-mode-handlers.d.ts.map +1 -1
- package/dist/hooks/use-mode-handlers.js +21 -2
- package/dist/hooks/use-mode-handlers.js.map +1 -1
- package/dist/hooks/use-model-selection.d.ts +3 -0
- package/dist/hooks/use-model-selection.d.ts.map +1 -1
- package/dist/hooks/use-model-selection.js +3 -0
- package/dist/hooks/use-model-selection.js.map +1 -1
- package/dist/hooks/use-path-completion.test.d.ts +2 -0
- package/dist/hooks/use-path-completion.test.d.ts.map +1 -0
- package/dist/hooks/use-path-completion.test.js +54 -0
- package/dist/hooks/use-path-completion.test.js.map +1 -0
- package/dist/hooks/use-runtime-settings.d.ts.map +1 -1
- package/dist/hooks/use-runtime-settings.js +15 -6
- package/dist/hooks/use-runtime-settings.js.map +1 -1
- package/dist/hooks/use-settings-completion.d.ts.map +1 -1
- package/dist/hooks/use-settings-completion.js +0 -1
- package/dist/hooks/use-settings-completion.js.map +1 -1
- package/dist/hooks/use-settings-value-completion.d.ts +1 -0
- package/dist/hooks/use-settings-value-completion.d.ts.map +1 -1
- package/dist/hooks/use-settings-value-completion.js +25 -19
- package/dist/hooks/use-settings-value-completion.js.map +1 -1
- package/dist/hooks/use-shell-mode.d.ts.map +1 -1
- package/dist/hooks/use-shell-mode.js +2 -1
- package/dist/hooks/use-shell-mode.js.map +1 -1
- package/dist/hooks/use-slash-commands.d.ts +1 -0
- package/dist/hooks/use-slash-commands.d.ts.map +1 -1
- package/dist/hooks/use-slash-commands.js +10 -1
- package/dist/hooks/use-slash-commands.js.map +1 -1
- package/dist/hooks/use-undo-selection.d.ts +19 -0
- package/dist/hooks/use-undo-selection.d.ts.map +1 -0
- package/dist/hooks/use-undo-selection.js +76 -0
- package/dist/hooks/use-undo-selection.js.map +1 -0
- package/dist/lib/openai-agent-client.d.ts +2 -0
- package/dist/lib/openai-agent-client.d.ts.map +1 -1
- package/dist/lib/openai-agent-client.js +71 -5
- package/dist/lib/openai-agent-client.js.map +1 -1
- package/dist/lib/openai-agent-client.test.js +23 -0
- package/dist/lib/openai-agent-client.test.js.map +1 -1
- package/dist/non-interactive.d.ts +6 -1
- package/dist/non-interactive.d.ts.map +1 -1
- package/dist/non-interactive.js +70 -4
- package/dist/non-interactive.js.map +1 -1
- package/dist/non-interactive.test.js +176 -1
- package/dist/non-interactive.test.js.map +1 -1
- package/dist/prompts/gpt-5.md +7 -4
- package/dist/prompts/orchestrator.md +46 -0
- package/dist/prompts/plan-mode-info.md +17 -0
- package/dist/prompts/prompt-selector.d.ts +2 -1
- package/dist/prompts/prompt-selector.d.ts.map +1 -1
- package/dist/prompts/prompt-selector.js +5 -1
- package/dist/prompts/prompt-selector.js.map +1 -1
- package/dist/prompts/prompt-selector.test.js +7 -0
- package/dist/prompts/prompt-selector.test.js.map +1 -1
- package/dist/prompts/prompt-selector.test.ts +18 -0
- package/dist/prompts/prompt-selector.ts +7 -1
- package/dist/prompts/reasoning-efficiency.d.ts +7 -0
- package/dist/prompts/reasoning-efficiency.d.ts.map +1 -0
- package/dist/prompts/reasoning-efficiency.js +19 -0
- package/dist/prompts/reasoning-efficiency.js.map +1 -0
- package/dist/prompts/reasoning-efficiency.ts +18 -0
- package/dist/prompts/search-via-shell.test.js +17 -17
- package/dist/prompts/search-via-shell.test.js.map +1 -1
- package/dist/prompts/search-via-shell.test.ts +17 -17
- package/dist/prompts/shell-auto-approval.d.ts +3 -0
- package/dist/prompts/shell-auto-approval.d.ts.map +1 -0
- package/dist/prompts/shell-auto-approval.js +23 -0
- package/dist/prompts/shell-auto-approval.js.map +1 -0
- package/dist/prompts/shell-auto-approval.ts +23 -0
- package/dist/prompts/subagent-delegation.d.ts +10 -0
- package/dist/prompts/subagent-delegation.d.ts.map +1 -0
- package/dist/prompts/subagent-delegation.js +33 -0
- package/dist/prompts/subagent-delegation.js.map +1 -0
- package/dist/prompts/subagent-delegation.test.d.ts +2 -0
- package/dist/prompts/subagent-delegation.test.d.ts.map +1 -0
- package/dist/prompts/subagent-delegation.test.js +17 -0
- package/dist/prompts/subagent-delegation.test.js.map +1 -0
- package/dist/prompts/subagent-delegation.test.ts +21 -0
- package/dist/prompts/subagent-delegation.ts +40 -0
- package/dist/prompts/subagents/explorer.md +1 -2
- package/dist/prompts/subagents/mentor.md +0 -1
- package/dist/prompts/subagents/researcher.md +0 -1
- package/dist/prompts/subagents/worker.md +3 -4
- package/dist/providers/ai-sdk-anthropic.provider.d.ts +1 -0
- package/dist/providers/ai-sdk-anthropic.provider.d.ts.map +1 -1
- package/dist/providers/ai-sdk-anthropic.provider.js +67 -1
- package/dist/providers/ai-sdk-anthropic.provider.js.map +1 -1
- package/dist/providers/ai-sdk-anthropic.provider.test.d.ts +2 -0
- package/dist/providers/ai-sdk-anthropic.provider.test.d.ts.map +1 -0
- package/dist/providers/ai-sdk-anthropic.provider.test.js +87 -0
- package/dist/providers/ai-sdk-anthropic.provider.test.js.map +1 -0
- package/dist/providers/ai-sdk-openai-compatible.provider.d.ts +0 -2
- package/dist/providers/ai-sdk-openai-compatible.provider.d.ts.map +1 -1
- package/dist/providers/ai-sdk-openai-compatible.provider.js +4 -8
- package/dist/providers/ai-sdk-openai-compatible.provider.js.map +1 -1
- package/dist/providers/ai-sdk-openai-compatible.provider.test.js +1 -119
- package/dist/providers/ai-sdk-openai-compatible.provider.test.js.map +1 -1
- package/dist/providers/common/openai-compatible-messages.d.ts.map +1 -1
- package/dist/providers/common/openai-compatible-messages.js +10 -4
- package/dist/providers/common/openai-compatible-messages.js.map +1 -1
- package/dist/providers/common/openai-compatible-messages.test.js +22 -0
- package/dist/providers/common/openai-compatible-messages.test.js.map +1 -1
- package/dist/providers/custom-provider-adapter.test.js +39 -1
- package/dist/providers/custom-provider-adapter.test.js.map +1 -1
- package/dist/providers/openai-compatible-behavior-gate.test.js +1 -42
- package/dist/providers/openai-compatible-behavior-gate.test.js.map +1 -1
- package/dist/providers/openai-compatible.provider.d.ts +11 -1
- package/dist/providers/openai-compatible.provider.d.ts.map +1 -1
- package/dist/providers/openai-compatible.provider.js +122 -8
- package/dist/providers/openai-compatible.provider.js.map +1 -1
- package/dist/providers/openai-compatible.provider.test.js +61 -0
- package/dist/providers/openai-compatible.provider.test.js.map +1 -1
- package/dist/providers/openai.provider.test.d.ts +2 -0
- package/dist/providers/openai.provider.test.d.ts.map +1 -0
- package/dist/providers/openai.provider.test.js +22 -0
- package/dist/providers/openai.provider.test.js.map +1 -0
- package/dist/scripts/eval-auto-approval/dataset.d.ts +1 -1
- package/dist/services/agent-stream.d.ts +1 -0
- package/dist/services/agent-stream.d.ts.map +1 -1
- package/dist/services/approval-flow-coordinator.d.ts +2 -0
- package/dist/services/approval-flow-coordinator.d.ts.map +1 -1
- package/dist/services/approval-flow-coordinator.js +45 -18
- package/dist/services/approval-flow-coordinator.js.map +1 -1
- package/dist/services/approval-flow-coordinator.test.js +87 -0
- package/dist/services/approval-flow-coordinator.test.js.map +1 -1
- package/dist/services/approval-state.d.ts +4 -0
- package/dist/services/approval-state.d.ts.map +1 -1
- package/dist/services/approval-state.js +2 -0
- package/dist/services/approval-state.js.map +1 -1
- package/dist/services/approval-state.test.js +21 -0
- package/dist/services/approval-state.test.js.map +1 -1
- package/dist/services/conversation-persistence.d.ts +52 -0
- package/dist/services/conversation-persistence.d.ts.map +1 -0
- package/dist/services/conversation-persistence.js +163 -0
- package/dist/services/conversation-persistence.js.map +1 -0
- package/dist/services/conversation-persistence.test.d.ts +2 -0
- package/dist/services/conversation-persistence.test.d.ts.map +1 -0
- package/dist/services/conversation-persistence.test.js +418 -0
- package/dist/services/conversation-persistence.test.js.map +1 -0
- package/dist/services/conversation-result-builder.d.ts.map +1 -1
- package/dist/services/conversation-result-builder.js +13 -0
- package/dist/services/conversation-result-builder.js.map +1 -1
- package/dist/services/conversation-service.d.ts +22 -0
- package/dist/services/conversation-service.d.ts.map +1 -1
- package/dist/services/conversation-service.js +18 -0
- package/dist/services/conversation-service.js.map +1 -1
- package/dist/services/conversation-session.auto-approval.test.js +5 -9
- package/dist/services/conversation-session.auto-approval.test.js.map +1 -1
- package/dist/services/conversation-session.d.ts +25 -0
- package/dist/services/conversation-session.d.ts.map +1 -1
- package/dist/services/conversation-session.js +144 -10
- package/dist/services/conversation-session.js.map +1 -1
- package/dist/services/conversation-store.d.ts +42 -0
- package/dist/services/conversation-store.d.ts.map +1 -1
- package/dist/services/conversation-store.js +182 -1
- package/dist/services/conversation-store.js.map +1 -1
- package/dist/services/conversation-store.test.js +310 -1
- package/dist/services/conversation-store.test.js.map +1 -1
- package/dist/services/history-service.d.ts +6 -1
- package/dist/services/history-service.d.ts.map +1 -1
- package/dist/services/history-service.js +46 -6
- package/dist/services/history-service.js.map +1 -1
- package/dist/services/history-service.test.d.ts +2 -0
- package/dist/services/history-service.test.d.ts.map +1 -0
- package/dist/services/history-service.test.js +77 -0
- package/dist/services/history-service.test.js.map +1 -0
- package/dist/services/input-surge-guard.d.ts +37 -0
- package/dist/services/input-surge-guard.d.ts.map +1 -0
- package/dist/services/input-surge-guard.js +190 -0
- package/dist/services/input-surge-guard.js.map +1 -0
- package/dist/services/input-surge-guard.test.d.ts +2 -0
- package/dist/services/input-surge-guard.test.d.ts.map +1 -0
- package/dist/services/input-surge-guard.test.js +126 -0
- package/dist/services/input-surge-guard.test.js.map +1 -0
- package/dist/services/mode-notices.d.ts +11 -0
- package/dist/services/mode-notices.d.ts.map +1 -0
- package/dist/services/mode-notices.js +16 -0
- package/dist/services/mode-notices.js.map +1 -0
- package/dist/services/plan-mode-interceptor.d.ts +10 -0
- package/dist/services/plan-mode-interceptor.d.ts.map +1 -0
- package/dist/services/plan-mode-interceptor.js +38 -0
- package/dist/services/plan-mode-interceptor.js.map +1 -0
- package/dist/services/plan-mode-interceptor.test.d.ts +2 -0
- package/dist/services/plan-mode-interceptor.test.d.ts.map +1 -0
- package/dist/services/plan-mode-interceptor.test.js +55 -0
- package/dist/services/plan-mode-interceptor.test.js.map +1 -0
- package/dist/services/service-interfaces.d.ts +4 -1
- package/dist/services/service-interfaces.d.ts.map +1 -1
- package/dist/services/settings-persistence.js +1 -1
- package/dist/services/settings-schema.d.ts +107 -4
- package/dist/services/settings-schema.d.ts.map +1 -1
- package/dist/services/settings-schema.js +103 -5
- package/dist/services/settings-schema.js.map +1 -1
- package/dist/services/settings-schema.test.js +35 -1
- package/dist/services/settings-schema.test.js.map +1 -1
- package/dist/services/settings-service.d.ts +3 -1
- package/dist/services/settings-service.d.ts.map +1 -1
- package/dist/services/settings-service.js +40 -4
- package/dist/services/settings-service.js.map +1 -1
- package/dist/services/settings-sources.d.ts.map +1 -1
- package/dist/services/settings-sources.js +2 -1
- package/dist/services/settings-sources.js.map +1 -1
- package/dist/services/settings-sources.test.js +4 -0
- package/dist/services/settings-sources.test.js.map +1 -1
- package/dist/services/shell-auto-approval-evaluator.d.ts +2 -1
- package/dist/services/shell-auto-approval-evaluator.d.ts.map +1 -1
- package/dist/services/shell-auto-approval-evaluator.js +12 -29
- package/dist/services/shell-auto-approval-evaluator.js.map +1 -1
- package/dist/services/shell-auto-approval-evaluator.test.js +2 -4
- package/dist/services/shell-auto-approval-evaluator.test.js.map +1 -1
- package/dist/services/shell-auto-approval-resolver.test.js +1 -1
- package/dist/services/shell-auto-approval-resolver.test.js.map +1 -1
- package/dist/services/stream-event-processor.d.ts.map +1 -1
- package/dist/services/stream-event-processor.js +5 -0
- package/dist/services/stream-event-processor.js.map +1 -1
- package/dist/services/stream-event-processor.test.js +27 -0
- package/dist/services/stream-event-processor.test.js.map +1 -1
- package/dist/services/subagents/subagent-manager.d.ts.map +1 -1
- package/dist/services/subagents/subagent-manager.js +171 -31
- package/dist/services/subagents/subagent-manager.js.map +1 -1
- package/dist/services/subagents/subagent-manager.test.js +232 -42
- package/dist/services/subagents/subagent-manager.test.js.map +1 -1
- package/dist/services/subagents/types.d.ts +6 -0
- package/dist/services/subagents/types.d.ts.map +1 -1
- package/dist/services/terminal-result-collector.d.ts.map +1 -1
- package/dist/services/terminal-result-collector.js +1 -2
- package/dist/services/terminal-result-collector.js.map +1 -1
- package/dist/slash-commands.d.ts +1 -0
- package/dist/slash-commands.d.ts.map +1 -1
- package/dist/slash-commands.js +8 -1
- package/dist/slash-commands.js.map +1 -1
- package/dist/slash-commands.test.d.ts +2 -0
- package/dist/slash-commands.test.d.ts.map +1 -0
- package/dist/slash-commands.test.js +22 -0
- package/dist/slash-commands.test.js.map +1 -0
- package/dist/tools/apply-patch.d.ts.map +1 -1
- package/dist/tools/apply-patch.js +2 -6
- package/dist/tools/apply-patch.js.map +1 -1
- package/dist/tools/apply-patch.test.js +2 -13
- package/dist/tools/apply-patch.test.js.map +1 -1
- package/dist/tools/code-context.test.js +4 -3
- package/dist/tools/code-context.test.js.map +1 -1
- package/dist/tools/create-file.d.ts.map +1 -1
- package/dist/tools/create-file.js +2 -3
- package/dist/tools/create-file.js.map +1 -1
- package/dist/tools/create-file.test.js +3 -14
- package/dist/tools/create-file.test.js.map +1 -1
- package/dist/tools/edit-healing.d.ts +3 -3
- package/dist/tools/edit-healing.d.ts.map +1 -1
- package/dist/tools/edit-healing.js.map +1 -1
- package/dist/tools/edit-healing.test.js +0 -1
- package/dist/tools/edit-healing.test.js.map +1 -1
- package/dist/tools/find-files.test.js +3 -2
- package/dist/tools/find-files.test.js.map +1 -1
- package/dist/tools/grep.d.ts +1 -0
- package/dist/tools/grep.d.ts.map +1 -1
- package/dist/tools/grep.js +65 -4
- package/dist/tools/grep.js.map +1 -1
- package/dist/tools/grep.test.js +39 -0
- package/dist/tools/grep.test.js.map +1 -0
- package/dist/tools/read-file.d.ts +1 -0
- package/dist/tools/read-file.d.ts.map +1 -1
- package/dist/tools/read-file.js +7 -5
- package/dist/tools/read-file.js.map +1 -1
- package/dist/tools/read-file.test.js +3 -2
- package/dist/tools/read-file.test.js.map +1 -1
- package/dist/tools/run-subagent.d.ts +1 -1
- package/dist/tools/run-subagent.d.ts.map +1 -1
- package/dist/tools/run-subagent.js +27 -23
- package/dist/tools/run-subagent.js.map +1 -1
- package/dist/tools/run-subagent.test.js +55 -8
- package/dist/tools/run-subagent.test.js.map +1 -1
- package/dist/tools/search-replace.d.ts +13 -5
- package/dist/tools/search-replace.d.ts.map +1 -1
- package/dist/tools/search-replace.js +46 -115
- package/dist/tools/search-replace.js.map +1 -1
- package/dist/tools/search-replace.test.js +275 -240
- package/dist/tools/search-replace.test.js.map +1 -1
- package/dist/tools/shell.d.ts +1 -0
- package/dist/tools/shell.d.ts.map +1 -1
- package/dist/tools/shell.js +14 -6
- package/dist/tools/shell.js.map +1 -1
- package/dist/tools/shell.test.js +52 -0
- package/dist/tools/shell.test.js.map +1 -1
- package/dist/tools/tool-parameter-schema.test.js +13 -4
- package/dist/tools/tool-parameter-schema.test.js.map +1 -1
- package/dist/tools/types.d.ts +1 -1
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/web-fetch.d.ts.map +1 -1
- package/dist/tools/web-fetch.js +29 -4
- package/dist/tools/web-fetch.js.map +1 -1
- package/dist/tools/web-fetch.test.js +64 -0
- package/dist/tools/web-fetch.test.js.map +1 -1
- package/dist/utils/conversation-event-handler.d.ts.map +1 -1
- package/dist/utils/conversation-event-handler.js +4 -0
- package/dist/utils/conversation-event-handler.js.map +1 -1
- package/dist/utils/conversation-event-handler.test.js +22 -0
- package/dist/utils/conversation-event-handler.test.js.map +1 -1
- package/dist/utils/execute-shell.d.ts +2 -0
- package/dist/utils/execute-shell.d.ts.map +1 -1
- package/dist/utils/execute-shell.js +25 -1
- package/dist/utils/execute-shell.js.map +1 -1
- package/dist/utils/execute-shell.test.js +22 -0
- package/dist/utils/execute-shell.test.js.map +1 -1
- package/dist/utils/model-settings.d.ts.map +1 -1
- package/dist/utils/model-settings.js +18 -0
- package/dist/utils/model-settings.js.map +1 -1
- package/dist/utils/output-trim.d.ts.map +1 -1
- package/dist/utils/output-trim.js +14 -6
- package/dist/utils/output-trim.js.map +1 -1
- package/dist/utils/project-tree.d.ts +14 -0
- package/dist/utils/project-tree.d.ts.map +1 -0
- package/dist/utils/project-tree.js +111 -0
- package/dist/utils/project-tree.js.map +1 -0
- package/dist/utils/project-tree.test.d.ts +2 -0
- package/dist/utils/project-tree.test.d.ts.map +1 -0
- package/dist/utils/project-tree.test.js +149 -0
- package/dist/utils/project-tree.test.js.map +1 -0
- package/dist/utils/terminal-clear.d.ts +7 -0
- package/dist/utils/terminal-clear.d.ts.map +1 -0
- package/dist/utils/terminal-clear.js +5 -0
- package/dist/utils/terminal-clear.js.map +1 -0
- package/dist/utils/terminal-clear.test.d.ts +2 -0
- package/dist/utils/terminal-clear.test.d.ts.map +1 -0
- package/dist/utils/terminal-clear.test.js +13 -0
- package/dist/utils/terminal-clear.test.js.map +1 -0
- package/dist/utils/token-usage.test.js +31 -0
- package/dist/utils/token-usage.test.js.map +1 -1
- package/package.json +3 -3
- package/readme.md +271 -44
- package/dist/agent.lite-mode.test.d.ts +0 -2
- package/dist/agent.lite-mode.test.d.ts.map +0 -1
- package/dist/agent.lite-mode.test.js +0 -39
- package/dist/agent.lite-mode.test.js.map +0 -1
- package/dist/components/ApprovalPrompt.test.d.ts +0 -2
- package/dist/components/ApprovalPrompt.test.d.ts.map +0 -1
- package/dist/components/ApprovalPrompt.test.js +0 -23
- package/dist/components/ApprovalPrompt.test.js.map +0 -1
- package/dist/components/LiveResponse.test.d.ts +0 -2
- package/dist/components/LiveResponse.test.d.ts.map +0 -1
- package/dist/components/LiveResponse.test.js +0 -13
- package/dist/components/LiveResponse.test.js.map +0 -1
- package/dist/components/ModelSelectionMenu.error-tabs.test.d.ts +0 -2
- package/dist/components/ModelSelectionMenu.error-tabs.test.d.ts.map +0 -1
- package/dist/components/ModelSelectionMenu.error-tabs.test.js +0 -18
- package/dist/components/ModelSelectionMenu.error-tabs.test.js.map +0 -1
- package/dist/components/TextInput.d.ts +0 -42
- package/dist/components/TextInput.d.ts.map +0 -1
- package/dist/components/TextInput.js +0 -398
- package/dist/components/TextInput.js.map +0 -1
- package/dist/components/TextInput.test.d.ts +0 -2
- package/dist/components/TextInput.test.d.ts.map +0 -1
- package/dist/components/TextInput.test.js +0 -75
- package/dist/components/TextInput.test.js.map +0 -1
- package/dist/debug_ask_mentor.d.ts +0 -2
- package/dist/debug_ask_mentor.d.ts.map +0 -1
- package/dist/debug_ask_mentor.js +0 -73
- package/dist/debug_ask_mentor.js.map +0 -1
- package/dist/lib/shell.d.ts +0 -7
- package/dist/lib/shell.d.ts.map +0 -1
- package/dist/lib/shell.js +0 -56
- package/dist/lib/shell.js.map +0 -1
- package/dist/modes/companion/command-index.d.ts +0 -26
- package/dist/modes/companion/command-index.d.ts.map +0 -1
- package/dist/modes/companion/command-index.js +0 -50
- package/dist/modes/companion/command-index.js.map +0 -1
- package/dist/modes/companion/command-index.test.d.ts +0 -2
- package/dist/modes/companion/command-index.test.d.ts.map +0 -1
- package/dist/modes/companion/command-index.test.js +0 -86
- package/dist/modes/companion/command-index.test.js.map +0 -1
- package/dist/modes/companion/companion-app.d.ts +0 -12
- package/dist/modes/companion/companion-app.d.ts.map +0 -1
- package/dist/modes/companion/companion-app.js +0 -297
- package/dist/modes/companion/companion-app.js.map +0 -1
- package/dist/modes/companion/companion-session.d.ts +0 -63
- package/dist/modes/companion/companion-session.d.ts.map +0 -1
- package/dist/modes/companion/companion-session.js +0 -146
- package/dist/modes/companion/companion-session.js.map +0 -1
- package/dist/modes/companion/companion-session.test.d.ts +0 -2
- package/dist/modes/companion/companion-session.test.d.ts.map +0 -1
- package/dist/modes/companion/companion-session.test.js +0 -28
- package/dist/modes/companion/companion-session.test.js.map +0 -1
- package/dist/modes/companion/components/status-bar.d.ts +0 -13
- package/dist/modes/companion/components/status-bar.d.ts.map +0 -1
- package/dist/modes/companion/components/status-bar.js +0 -26
- package/dist/modes/companion/components/status-bar.js.map +0 -1
- package/dist/modes/companion/context-buffer.d.ts +0 -65
- package/dist/modes/companion/context-buffer.d.ts.map +0 -1
- package/dist/modes/companion/context-buffer.js +0 -156
- package/dist/modes/companion/context-buffer.js.map +0 -1
- package/dist/modes/companion/context-buffer.test.d.ts +0 -2
- package/dist/modes/companion/context-buffer.test.d.ts.map +0 -1
- package/dist/modes/companion/context-buffer.test.js +0 -154
- package/dist/modes/companion/context-buffer.test.js.map +0 -1
- package/dist/modes/companion/event-detector.d.ts +0 -46
- package/dist/modes/companion/event-detector.d.ts.map +0 -1
- package/dist/modes/companion/event-detector.js +0 -169
- package/dist/modes/companion/event-detector.js.map +0 -1
- package/dist/modes/companion/event-detector.test.d.ts +0 -2
- package/dist/modes/companion/event-detector.test.d.ts.map +0 -1
- package/dist/modes/companion/event-detector.test.js +0 -121
- package/dist/modes/companion/event-detector.test.js.map +0 -1
- package/dist/modes/companion/index.d.ts +0 -33
- package/dist/modes/companion/index.d.ts.map +0 -1
- package/dist/modes/companion/index.js +0 -21
- package/dist/modes/companion/index.js.map +0 -1
- package/dist/modes/companion/input-key-mapper.d.ts +0 -3
- package/dist/modes/companion/input-key-mapper.d.ts.map +0 -1
- package/dist/modes/companion/input-key-mapper.js +0 -31
- package/dist/modes/companion/input-key-mapper.js.map +0 -1
- package/dist/modes/companion/input-key-mapper.test.d.ts +0 -2
- package/dist/modes/companion/input-key-mapper.test.d.ts.map +0 -1
- package/dist/modes/companion/input-key-mapper.test.js +0 -26
- package/dist/modes/companion/input-key-mapper.test.js.map +0 -1
- package/dist/modes/companion/input-parser.d.ts +0 -53
- package/dist/modes/companion/input-parser.d.ts.map +0 -1
- package/dist/modes/companion/input-parser.js +0 -114
- package/dist/modes/companion/input-parser.js.map +0 -1
- package/dist/modes/companion/input-parser.test.d.ts +0 -2
- package/dist/modes/companion/input-parser.test.d.ts.map +0 -1
- package/dist/modes/companion/input-parser.test.js +0 -123
- package/dist/modes/companion/input-parser.test.js.map +0 -1
- package/dist/modes/companion/mode-manager.d.ts +0 -41
- package/dist/modes/companion/mode-manager.d.ts.map +0 -1
- package/dist/modes/companion/mode-manager.js +0 -56
- package/dist/modes/companion/mode-manager.js.map +0 -1
- package/dist/modes/companion/mode-manager.test.d.ts +0 -2
- package/dist/modes/companion/mode-manager.test.d.ts.map +0 -1
- package/dist/modes/companion/mode-manager.test.js +0 -65
- package/dist/modes/companion/mode-manager.test.js.map +0 -1
- package/dist/modes/companion/output-classifier.d.ts +0 -15
- package/dist/modes/companion/output-classifier.d.ts.map +0 -1
- package/dist/modes/companion/output-classifier.js +0 -77
- package/dist/modes/companion/output-classifier.js.map +0 -1
- package/dist/modes/companion/output-classifier.test.d.ts +0 -2
- package/dist/modes/companion/output-classifier.test.d.ts.map +0 -1
- package/dist/modes/companion/output-classifier.test.js +0 -133
- package/dist/modes/companion/output-classifier.test.js.map +0 -1
- package/dist/modes/companion/pty-wrapper.d.ts +0 -46
- package/dist/modes/companion/pty-wrapper.d.ts.map +0 -1
- package/dist/modes/companion/pty-wrapper.js +0 -143
- package/dist/modes/companion/pty-wrapper.js.map +0 -1
- package/dist/modes/companion/safety-classifier.d.ts +0 -31
- package/dist/modes/companion/safety-classifier.d.ts.map +0 -1
- package/dist/modes/companion/safety-classifier.js +0 -140
- package/dist/modes/companion/safety-classifier.js.map +0 -1
- package/dist/modes/companion/safety-classifier.test.d.ts +0 -2
- package/dist/modes/companion/safety-classifier.test.d.ts.map +0 -1
- package/dist/modes/companion/safety-classifier.test.js +0 -151
- package/dist/modes/companion/safety-classifier.test.js.map +0 -1
- package/dist/modes/companion/summarizer.d.ts +0 -24
- package/dist/modes/companion/summarizer.d.ts.map +0 -1
- package/dist/modes/companion/summarizer.js +0 -132
- package/dist/modes/companion/summarizer.js.map +0 -1
- package/dist/modes/companion/terminal-history.d.ts +0 -27
- package/dist/modes/companion/terminal-history.d.ts.map +0 -1
- package/dist/modes/companion/terminal-history.js +0 -142
- package/dist/modes/companion/terminal-history.js.map +0 -1
- package/dist/prompts/simple-mentor.md +0 -215
- package/dist/providers/ai-sdk-openai.provider.d.ts +0 -14
- package/dist/providers/ai-sdk-openai.provider.d.ts.map +0 -1
- package/dist/providers/ai-sdk-openai.provider.js +0 -18
- package/dist/providers/ai-sdk-openai.provider.js.map +0 -1
- package/dist/providers/github-copilot/converters.d.ts +0 -45
- package/dist/providers/github-copilot/converters.d.ts.map +0 -1
- package/dist/providers/github-copilot/converters.js +0 -118
- package/dist/providers/github-copilot/converters.js.map +0 -1
- package/dist/providers/github-copilot/converters.test.d.ts +0 -2
- package/dist/providers/github-copilot/converters.test.d.ts.map +0 -1
- package/dist/providers/github-copilot/converters.test.js +0 -162
- package/dist/providers/github-copilot/converters.test.js.map +0 -1
- package/dist/providers/github-copilot/github-copilot.provider.d.ts +0 -2
- package/dist/providers/github-copilot/github-copilot.provider.d.ts.map +0 -1
- package/dist/providers/github-copilot/github-copilot.provider.js +0 -75
- package/dist/providers/github-copilot/github-copilot.provider.js.map +0 -1
- package/dist/providers/github-copilot/github-copilot.provider.test.d.ts +0 -2
- package/dist/providers/github-copilot/github-copilot.provider.test.d.ts.map +0 -1
- package/dist/providers/github-copilot/github-copilot.provider.test.js +0 -26
- package/dist/providers/github-copilot/github-copilot.provider.test.js.map +0 -1
- package/dist/providers/github-copilot/index.d.ts +0 -4
- package/dist/providers/github-copilot/index.d.ts.map +0 -1
- package/dist/providers/github-copilot/index.js +0 -4
- package/dist/providers/github-copilot/index.js.map +0 -1
- package/dist/providers/github-copilot/model.d.ts +0 -24
- package/dist/providers/github-copilot/model.d.ts.map +0 -1
- package/dist/providers/github-copilot/model.delta.test.d.ts +0 -2
- package/dist/providers/github-copilot/model.delta.test.d.ts.map +0 -1
- package/dist/providers/github-copilot/model.delta.test.js +0 -15
- package/dist/providers/github-copilot/model.delta.test.js.map +0 -1
- package/dist/providers/github-copilot/model.js +0 -498
- package/dist/providers/github-copilot/model.js.map +0 -1
- package/dist/providers/github-copilot/model.test.d.ts +0 -2
- package/dist/providers/github-copilot/model.test.d.ts.map +0 -1
- package/dist/providers/github-copilot/model.test.js +0 -63
- package/dist/providers/github-copilot/model.test.js.map +0 -1
- package/dist/providers/github-copilot/provider.d.ts +0 -15
- package/dist/providers/github-copilot/provider.d.ts.map +0 -1
- package/dist/providers/github-copilot/provider.js +0 -25
- package/dist/providers/github-copilot/provider.js.map +0 -1
- package/dist/providers/github-copilot/provider.test.d.ts +0 -2
- package/dist/providers/github-copilot/provider.test.d.ts.map +0 -1
- package/dist/providers/github-copilot/provider.test.js +0 -52
- package/dist/providers/github-copilot/provider.test.js.map +0 -1
- package/dist/providers/github-copilot/utils.d.ts +0 -20
- package/dist/providers/github-copilot/utils.d.ts.map +0 -1
- package/dist/providers/github-copilot/utils.js +0 -142
- package/dist/providers/github-copilot/utils.js.map +0 -1
- package/dist/providers/github-copilot/utils.test.d.ts +0 -2
- package/dist/providers/github-copilot/utils.test.d.ts.map +0 -1
- package/dist/providers/github-copilot/utils.test.js +0 -21
- package/dist/providers/github-copilot/utils.test.js.map +0 -1
- package/dist/providers/openai-compatible/api.d.ts +0 -17
- package/dist/providers/openai-compatible/api.d.ts.map +0 -1
- package/dist/providers/openai-compatible/api.js +0 -58
- package/dist/providers/openai-compatible/api.js.map +0 -1
- package/dist/providers/openai-compatible/model.d.ts +0 -17
- package/dist/providers/openai-compatible/model.d.ts.map +0 -1
- package/dist/providers/openai-compatible/model.js +0 -473
- package/dist/providers/openai-compatible/model.js.map +0 -1
- package/dist/providers/openai-compatible/provider.d.ts +0 -22
- package/dist/providers/openai-compatible/provider.d.ts.map +0 -1
- package/dist/providers/openai-compatible/provider.js +0 -43
- package/dist/providers/openai-compatible/provider.js.map +0 -1
- package/dist/providers/openai-compatible/reasoning-content.test.d.ts +0 -2
- package/dist/providers/openai-compatible/reasoning-content.test.d.ts.map +0 -1
- package/dist/providers/openai-compatible/reasoning-content.test.js +0 -258
- package/dist/providers/openai-compatible/reasoning-content.test.js.map +0 -1
- package/dist/providers/openai-compatible/utils.d.ts +0 -3
- package/dist/providers/openai-compatible/utils.d.ts.map +0 -1
- package/dist/providers/openai-compatible/utils.js +0 -11
- package/dist/providers/openai-compatible/utils.js.map +0 -1
- package/dist/providers/openrouter/api.d.ts +0 -39
- package/dist/providers/openrouter/api.d.ts.map +0 -1
- package/dist/providers/openrouter/api.js +0 -164
- package/dist/providers/openrouter/api.js.map +0 -1
- package/dist/providers/openrouter/converters.d.ts +0 -8
- package/dist/providers/openrouter/converters.d.ts.map +0 -1
- package/dist/providers/openrouter/converters.js +0 -391
- package/dist/providers/openrouter/converters.js.map +0 -1
- package/dist/providers/openrouter/converters.test.d.ts +0 -2
- package/dist/providers/openrouter/converters.test.d.ts.map +0 -1
- package/dist/providers/openrouter/converters.test.js +0 -179
- package/dist/providers/openrouter/converters.test.js.map +0 -1
- package/dist/providers/openrouter/index.d.ts +0 -4
- package/dist/providers/openrouter/index.d.ts.map +0 -1
- package/dist/providers/openrouter/index.js +0 -4
- package/dist/providers/openrouter/index.js.map +0 -1
- package/dist/providers/openrouter/model.d.ts +0 -14
- package/dist/providers/openrouter/model.d.ts.map +0 -1
- package/dist/providers/openrouter/model.js +0 -457
- package/dist/providers/openrouter/model.js.map +0 -1
- package/dist/providers/openrouter/provider.d.ts +0 -15
- package/dist/providers/openrouter/provider.d.ts.map +0 -1
- package/dist/providers/openrouter/provider.js +0 -21
- package/dist/providers/openrouter/provider.js.map +0 -1
- package/dist/providers/openrouter/reasoning-content.test.d.ts +0 -2
- package/dist/providers/openrouter/reasoning-content.test.d.ts.map +0 -1
- package/dist/providers/openrouter/reasoning-content.test.js +0 -122
- package/dist/providers/openrouter/reasoning-content.test.js.map +0 -1
- package/dist/providers/openrouter/utils.d.ts +0 -11
- package/dist/providers/openrouter/utils.d.ts.map +0 -1
- package/dist/providers/openrouter/utils.js +0 -29
- package/dist/providers/openrouter/utils.js.map +0 -1
- package/dist/providers/openrouter.api.retry.test.d.ts +0 -2
- package/dist/providers/openrouter.api.retry.test.d.ts.map +0 -1
- package/dist/providers/openrouter.api.retry.test.js +0 -148
- package/dist/providers/openrouter.api.retry.test.js.map +0 -1
- package/dist/providers/openrouter.test.d.ts +0 -2
- package/dist/providers/openrouter.test.d.ts.map +0 -1
- package/dist/providers/openrouter.test.js +0 -1449
- package/dist/providers/openrouter.test.js.map +0 -1
- package/dist/safety-checker.js +0 -57
- package/dist/services/check_mock.d.ts +0 -2
- package/dist/services/check_mock.d.ts.map +0 -1
- package/dist/services/check_mock.js +0 -22
- package/dist/services/check_mock.js.map +0 -1
- package/dist/services/conversation-service.test.d.ts +0 -2
- package/dist/services/conversation-service.test.d.ts.map +0 -1
- package/dist/services/conversation-service.test.js +0 -156
- package/dist/services/conversation-service.test.js.map +0 -1
- package/dist/tools/bash.d.ts +0 -10
- package/dist/tools/bash.d.ts.map +0 -1
- package/dist/tools/bash.js +0 -55
- package/dist/tools/bash.js.map +0 -1
- package/dist/utils/command-safety.d.ts +0 -21
- package/dist/utils/command-safety.d.ts.map +0 -1
- package/dist/utils/command-safety.devnull.test.d.ts +0 -2
- package/dist/utils/command-safety.devnull.test.d.ts.map +0 -1
- package/dist/utils/command-safety.devnull.test.js +0 -13
- package/dist/utils/command-safety.devnull.test.js.map +0 -1
- package/dist/utils/command-safety.js +0 -348
- package/dist/utils/command-safety.js.map +0 -1
- package/dist/utils/extract-command-messages.test.d.ts +0 -2
- package/dist/utils/extract-command-messages.test.d.ts.map +0 -1
- package/dist/utils/provider-traffic-extractor.repro.test.d.ts +0 -2
- package/dist/utils/provider-traffic-extractor.repro.test.d.ts.map +0 -1
- package/dist/utils/provider-traffic-extractor.repro.test.js.map +0 -1
|
@@ -35,68 +35,80 @@ function createTool(settingsService = createMockSettingsService(), editHealing)
|
|
|
35
35
|
...(editHealing ? { editHealing } : {}),
|
|
36
36
|
});
|
|
37
37
|
}
|
|
38
|
-
test.serial('needsApproval auto-approves creation when search_content is empty and file is missing
|
|
38
|
+
test.serial('needsApproval auto-approves creation when search_content is empty and file is missing', async (t) => {
|
|
39
39
|
await withTempDir(async () => {
|
|
40
|
-
const tool = createTool(createMockSettingsService(
|
|
40
|
+
const tool = createTool(createMockSettingsService());
|
|
41
41
|
const filePath = 'new-file.txt';
|
|
42
42
|
const result = await tool.needsApproval({
|
|
43
43
|
path: filePath,
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
replacements: [
|
|
45
|
+
{
|
|
46
|
+
search_content: '',
|
|
47
|
+
replace_content: 'initial content',
|
|
48
|
+
},
|
|
49
|
+
],
|
|
47
50
|
});
|
|
48
51
|
t.false(result);
|
|
49
52
|
});
|
|
50
53
|
});
|
|
51
|
-
test.serial('needsApproval auto-approves a unique exact match
|
|
54
|
+
test.serial('needsApproval auto-approves a unique exact match', async (t) => {
|
|
52
55
|
await withTempDir(async (dir) => {
|
|
53
|
-
const tool = createTool(createMockSettingsService(
|
|
56
|
+
const tool = createTool(createMockSettingsService());
|
|
54
57
|
const filePath = 'sample.txt';
|
|
55
58
|
const absPath = path.join(dir, filePath);
|
|
56
59
|
await fs.writeFile(absPath, 'hello world');
|
|
57
60
|
const result = await tool.needsApproval({
|
|
58
61
|
path: filePath,
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
+
replacements: [
|
|
63
|
+
{
|
|
64
|
+
search_content: 'hello',
|
|
65
|
+
replace_content: 'hi',
|
|
66
|
+
},
|
|
67
|
+
],
|
|
62
68
|
});
|
|
63
69
|
t.false(result);
|
|
64
70
|
});
|
|
65
71
|
});
|
|
66
|
-
test.serial('needsApproval
|
|
72
|
+
test.serial('needsApproval auto-approves when multiple exact matches are found', async (t) => {
|
|
67
73
|
await withTempDir(async (dir) => {
|
|
68
|
-
const tool = createTool(createMockSettingsService(
|
|
74
|
+
const tool = createTool(createMockSettingsService());
|
|
69
75
|
const filePath = 'sample.txt';
|
|
70
76
|
const absPath = path.join(dir, filePath);
|
|
71
77
|
await fs.writeFile(absPath, 'hello world hello');
|
|
72
78
|
const result = await tool.needsApproval({
|
|
73
79
|
path: filePath,
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
80
|
+
replacements: [
|
|
81
|
+
{
|
|
82
|
+
search_content: 'hello',
|
|
83
|
+
replace_content: 'hi',
|
|
84
|
+
},
|
|
85
|
+
],
|
|
77
86
|
});
|
|
78
|
-
t.
|
|
87
|
+
t.false(result);
|
|
79
88
|
});
|
|
80
89
|
});
|
|
81
|
-
test.serial('execute replaces only
|
|
90
|
+
test.serial('execute replaces only a unique exact match', async (t) => {
|
|
82
91
|
await withTempDir(async (dir) => {
|
|
83
92
|
const tool = createTool();
|
|
84
93
|
const filePath = 'content.txt';
|
|
85
94
|
const absPath = path.join(dir, filePath);
|
|
86
|
-
await fs.writeFile(absPath, 'target before
|
|
95
|
+
await fs.writeFile(absPath, 'target before unique after');
|
|
87
96
|
const result = await tool.execute({
|
|
88
97
|
path: filePath,
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
98
|
+
replacements: [
|
|
99
|
+
{
|
|
100
|
+
search_content: 'target',
|
|
101
|
+
replace_content: 'done',
|
|
102
|
+
},
|
|
103
|
+
],
|
|
92
104
|
});
|
|
93
105
|
const parsed = JSON.parse(result);
|
|
94
106
|
t.true(parsed.output[0].success);
|
|
95
107
|
const updated = await fs.readFile(absPath, 'utf8');
|
|
96
|
-
t.is(updated, 'done before
|
|
108
|
+
t.is(updated, 'done before unique after');
|
|
97
109
|
});
|
|
98
110
|
});
|
|
99
|
-
test.serial('execute
|
|
111
|
+
test.serial('execute fails when multiple exact matches are found', async (t) => {
|
|
100
112
|
await withTempDir(async (dir) => {
|
|
101
113
|
const tool = createTool();
|
|
102
114
|
const filePath = 'content.txt';
|
|
@@ -104,14 +116,18 @@ test.serial('execute replaces all exact matches when replace_all is true', async
|
|
|
104
116
|
await fs.writeFile(absPath, 'foo foo foo');
|
|
105
117
|
const result = await tool.execute({
|
|
106
118
|
path: filePath,
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
119
|
+
replacements: [
|
|
120
|
+
{
|
|
121
|
+
search_content: 'foo',
|
|
122
|
+
replace_content: 'bar',
|
|
123
|
+
},
|
|
124
|
+
],
|
|
110
125
|
});
|
|
111
126
|
const parsed = JSON.parse(result);
|
|
112
|
-
t.
|
|
127
|
+
t.false(parsed.output[0].success);
|
|
128
|
+
t.regex(parsed.output[0].error, /Found 3 exact matches/);
|
|
113
129
|
const updated = await fs.readFile(absPath, 'utf8');
|
|
114
|
-
t.is(updated, '
|
|
130
|
+
t.is(updated, 'foo foo foo');
|
|
115
131
|
});
|
|
116
132
|
});
|
|
117
133
|
test.serial('execute performs relaxed match replacement when exact match is not found', async (t) => {
|
|
@@ -122,9 +138,12 @@ test.serial('execute performs relaxed match replacement when exact match is not
|
|
|
122
138
|
await fs.writeFile(absPath, ' line one\n\tline two\nremainder');
|
|
123
139
|
const result = await tool.execute({
|
|
124
140
|
path: filePath,
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
141
|
+
replacements: [
|
|
142
|
+
{
|
|
143
|
+
search_content: 'line one\nline two',
|
|
144
|
+
replace_content: 'new block\n',
|
|
145
|
+
},
|
|
146
|
+
],
|
|
128
147
|
});
|
|
129
148
|
const parsed = JSON.parse(result);
|
|
130
149
|
t.true(parsed.output[0].success);
|
|
@@ -132,25 +151,7 @@ test.serial('execute performs relaxed match replacement when exact match is not
|
|
|
132
151
|
t.is(updated, 'new block\nremainder');
|
|
133
152
|
});
|
|
134
153
|
});
|
|
135
|
-
test.serial('execute
|
|
136
|
-
await withTempDir(async (dir) => {
|
|
137
|
-
const tool = createTool();
|
|
138
|
-
const filePath = 'content.txt';
|
|
139
|
-
const absPath = path.join(dir, filePath);
|
|
140
|
-
await fs.writeFile(absPath, 'foo\nbar\n---\nfoo\nbar\n');
|
|
141
|
-
const result = await tool.execute({
|
|
142
|
-
path: filePath,
|
|
143
|
-
search_content: 'foo\nbar',
|
|
144
|
-
replace_content: 'replacement',
|
|
145
|
-
replace_all: false,
|
|
146
|
-
});
|
|
147
|
-
const parsed = JSON.parse(result);
|
|
148
|
-
t.true(parsed.output[0].success);
|
|
149
|
-
const updated = await fs.readFile(absPath, 'utf8');
|
|
150
|
-
t.is(updated, 'replacement\n---\nfoo\nbar\n');
|
|
151
|
-
});
|
|
152
|
-
});
|
|
153
|
-
test.serial('execute rejects multiple relaxed matches when replace_all is false', async (t) => {
|
|
154
|
+
test.serial('execute fails when multiple relaxed matches are found', async (t) => {
|
|
154
155
|
await withTempDir(async (dir) => {
|
|
155
156
|
const tool = createTool();
|
|
156
157
|
const filePath = 'content.txt';
|
|
@@ -158,36 +159,20 @@ test.serial('execute rejects multiple relaxed matches when replace_all is false'
|
|
|
158
159
|
await fs.writeFile(absPath, ' foo \n\tbar\n---\n foo \n\tbar\n');
|
|
159
160
|
const result = await tool.execute({
|
|
160
161
|
path: filePath,
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
162
|
+
replacements: [
|
|
163
|
+
{
|
|
164
|
+
search_content: 'foo\nbar',
|
|
165
|
+
replace_content: 'replacement',
|
|
166
|
+
},
|
|
167
|
+
],
|
|
164
168
|
});
|
|
165
169
|
const parsed = JSON.parse(result);
|
|
166
170
|
t.false(parsed.output[0].success);
|
|
167
|
-
t.true(parsed.output[0].error.includes('relaxed matches'));
|
|
171
|
+
t.true(parsed.output[0].error.includes('relaxed matches') || parsed.output[0].error.includes('Found 2 relaxed matches'));
|
|
168
172
|
const unchanged = await fs.readFile(absPath, 'utf8');
|
|
169
173
|
t.is(unchanged, ' foo \n\tbar\n---\n foo \n\tbar\n');
|
|
170
174
|
});
|
|
171
175
|
});
|
|
172
|
-
test.serial('execute replaces all relaxed matches when replace_all is true', async (t) => {
|
|
173
|
-
await withTempDir(async (dir) => {
|
|
174
|
-
const tool = createTool(createMockSettingsService({ 'tools.enableEditHealing': false }));
|
|
175
|
-
const filePath = 'content.txt';
|
|
176
|
-
const absPath = path.join(dir, filePath);
|
|
177
|
-
await fs.writeFile(absPath, ' foo \n\tbar\n---\n foo \n\tbar\n');
|
|
178
|
-
const result = await tool.execute({
|
|
179
|
-
path: filePath,
|
|
180
|
-
search_content: 'foo\nbar',
|
|
181
|
-
replace_content: 'replacement',
|
|
182
|
-
replace_all: true,
|
|
183
|
-
});
|
|
184
|
-
const parsed = JSON.parse(result);
|
|
185
|
-
t.true(parsed.output[0].success);
|
|
186
|
-
t.true(parsed.output[0].message.includes('relaxed'));
|
|
187
|
-
const updated = await fs.readFile(absPath, 'utf8');
|
|
188
|
-
t.is(updated, 'replacement---\nreplacement');
|
|
189
|
-
});
|
|
190
|
-
});
|
|
191
176
|
test.serial('execute creates a new file when search_content is empty and file is missing', async (t) => {
|
|
192
177
|
await withTempDir(async (dir) => {
|
|
193
178
|
const tool = createTool();
|
|
@@ -195,9 +180,12 @@ test.serial('execute creates a new file when search_content is empty and file is
|
|
|
195
180
|
const absPath = path.join(dir, filePath);
|
|
196
181
|
const result = await tool.execute({
|
|
197
182
|
path: filePath,
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
183
|
+
replacements: [
|
|
184
|
+
{
|
|
185
|
+
search_content: '',
|
|
186
|
+
replace_content: 'new content',
|
|
187
|
+
},
|
|
188
|
+
],
|
|
201
189
|
});
|
|
202
190
|
const parsed = JSON.parse(result);
|
|
203
191
|
t.true(parsed.output[0].success);
|
|
@@ -210,13 +198,16 @@ test.serial('execute preserves parallel edits to different regions of the same f
|
|
|
210
198
|
const tool = createTool(createMockSettingsService({ 'tools.enableEditHealing': false }));
|
|
211
199
|
const filePath = 'parallel.txt';
|
|
212
200
|
const absPath = path.join(dir, filePath);
|
|
213
|
-
const tokens = Array.from({ length: 20 }, (_, index) => `token_${index}`);
|
|
201
|
+
const tokens = Array.from({ length: 20 }, (_, index) => `token_${String(index).padStart(2, '0')}`);
|
|
214
202
|
await fs.writeFile(absPath, tokens.join('\n'));
|
|
215
203
|
const results = await Promise.all(tokens.map((token, index) => tool.execute({
|
|
216
204
|
path: filePath,
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
205
|
+
replacements: [
|
|
206
|
+
{
|
|
207
|
+
search_content: token,
|
|
208
|
+
replace_content: `done_${index}`,
|
|
209
|
+
},
|
|
210
|
+
],
|
|
220
211
|
})));
|
|
221
212
|
for (const result of results) {
|
|
222
213
|
const parsed = JSON.parse(result);
|
|
@@ -233,18 +224,15 @@ test.serial('execute applies batched replacements to one file with a single resu
|
|
|
233
224
|
const absPath = path.join(dir, filePath);
|
|
234
225
|
await fs.writeFile(absPath, 'alpha\nbeta\ngamma\n');
|
|
235
226
|
const result = await tool.execute({
|
|
227
|
+
path: filePath,
|
|
236
228
|
replacements: [
|
|
237
229
|
{
|
|
238
|
-
path: filePath,
|
|
239
230
|
search_content: 'alpha',
|
|
240
231
|
replace_content: 'ALPHA',
|
|
241
|
-
replace_all: false,
|
|
242
232
|
},
|
|
243
233
|
{
|
|
244
|
-
path: filePath,
|
|
245
234
|
search_content: 'gamma',
|
|
246
235
|
replace_content: 'GAMMA',
|
|
247
|
-
replace_all: false,
|
|
248
236
|
},
|
|
249
237
|
],
|
|
250
238
|
});
|
|
@@ -263,24 +251,19 @@ test.serial('execute keeps successful batched replacements when another replacem
|
|
|
263
251
|
const originalContent = 'alpha\nbeta\ngamma\n';
|
|
264
252
|
await fs.writeFile(absPath, originalContent);
|
|
265
253
|
const result = await tool.execute({
|
|
254
|
+
path: filePath,
|
|
266
255
|
replacements: [
|
|
267
256
|
{
|
|
268
|
-
path: filePath,
|
|
269
257
|
search_content: 'alpha',
|
|
270
258
|
replace_content: 'ALPHA',
|
|
271
|
-
replace_all: false,
|
|
272
259
|
},
|
|
273
260
|
{
|
|
274
|
-
path: filePath,
|
|
275
261
|
search_content: 'missing',
|
|
276
262
|
replace_content: 'MISSING',
|
|
277
|
-
replace_all: false,
|
|
278
263
|
},
|
|
279
264
|
{
|
|
280
|
-
path: filePath,
|
|
281
265
|
search_content: 'gamma',
|
|
282
266
|
replace_content: 'GAMMA',
|
|
283
|
-
replace_all: false,
|
|
284
267
|
},
|
|
285
268
|
],
|
|
286
269
|
});
|
|
@@ -301,9 +284,12 @@ test.serial('execute reports failure when search string is not found', async (t)
|
|
|
301
284
|
await fs.writeFile(absPath, originalContent);
|
|
302
285
|
const result = await tool.execute({
|
|
303
286
|
path: filePath,
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
287
|
+
replacements: [
|
|
288
|
+
{
|
|
289
|
+
search_content: 'nonexistent',
|
|
290
|
+
replace_content: 'replacement',
|
|
291
|
+
},
|
|
292
|
+
],
|
|
307
293
|
});
|
|
308
294
|
const parsed = JSON.parse(result);
|
|
309
295
|
t.false(parsed.output[0].success);
|
|
@@ -326,9 +312,12 @@ test.serial('execute heals search content when no match is found', async (t) =>
|
|
|
326
312
|
}));
|
|
327
313
|
const result = await tool.execute({
|
|
328
314
|
path: filePath,
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
315
|
+
replacements: [
|
|
316
|
+
{
|
|
317
|
+
search_content: 'const foo = 2;\n',
|
|
318
|
+
replace_content: 'const foo = 3;\n',
|
|
319
|
+
},
|
|
320
|
+
],
|
|
332
321
|
});
|
|
333
322
|
const parsed = JSON.parse(result);
|
|
334
323
|
t.true(parsed.output[0].success);
|
|
@@ -350,9 +339,12 @@ test.serial('execute includes auto-healing failure reason when healing does not
|
|
|
350
339
|
}));
|
|
351
340
|
const result = await tool.execute({
|
|
352
341
|
path: filePath,
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
342
|
+
replacements: [
|
|
343
|
+
{
|
|
344
|
+
search_content: 'const foo = 2;\n',
|
|
345
|
+
replace_content: 'const foo = 3;\n',
|
|
346
|
+
},
|
|
347
|
+
],
|
|
356
348
|
});
|
|
357
349
|
const parsed = JSON.parse(result);
|
|
358
350
|
t.false(parsed.output[0].success);
|
|
@@ -369,9 +361,12 @@ test.serial('execute treats special regex characters literally', async (t) => {
|
|
|
369
361
|
await fs.writeFile(absPath, originalContent);
|
|
370
362
|
const result = await tool.execute({
|
|
371
363
|
path: filePath,
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
364
|
+
replacements: [
|
|
365
|
+
{
|
|
366
|
+
search_content: '[1, 2, 3]',
|
|
367
|
+
replace_content: '[4, 5, 6]',
|
|
368
|
+
},
|
|
369
|
+
],
|
|
375
370
|
});
|
|
376
371
|
const parsed = JSON.parse(result);
|
|
377
372
|
t.true(parsed.output[0].success);
|
|
@@ -387,9 +382,12 @@ test.serial('execute deletes content when replacement is empty string', async (t
|
|
|
387
382
|
await fs.writeFile(absPath, 'before DELETE_ME after');
|
|
388
383
|
const result = await tool.execute({
|
|
389
384
|
path: filePath,
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
385
|
+
replacements: [
|
|
386
|
+
{
|
|
387
|
+
search_content: 'DELETE_ME ',
|
|
388
|
+
replace_content: '',
|
|
389
|
+
},
|
|
390
|
+
],
|
|
393
391
|
});
|
|
394
392
|
const parsed = JSON.parse(result);
|
|
395
393
|
t.true(parsed.output[0].success);
|
|
@@ -405,9 +403,12 @@ test.serial('execute performs exact multi-line match without whitespace normaliz
|
|
|
405
403
|
await fs.writeFile(absPath, 'line one\nline two\nline three');
|
|
406
404
|
const result = await tool.execute({
|
|
407
405
|
path: filePath,
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
406
|
+
replacements: [
|
|
407
|
+
{
|
|
408
|
+
search_content: 'line one\nline two',
|
|
409
|
+
replace_content: 'new content',
|
|
410
|
+
},
|
|
411
|
+
],
|
|
411
412
|
});
|
|
412
413
|
const parsed = JSON.parse(result);
|
|
413
414
|
t.true(parsed.output[0].success);
|
|
@@ -423,9 +424,12 @@ test.serial('execute handles leading/trailing whitespace differences in relaxed
|
|
|
423
424
|
await fs.writeFile(absPath, ' foo \nbar');
|
|
424
425
|
const result = await tool.execute({
|
|
425
426
|
path: filePath,
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
427
|
+
replacements: [
|
|
428
|
+
{
|
|
429
|
+
search_content: 'foo\nbar',
|
|
430
|
+
replace_content: 'replaced',
|
|
431
|
+
},
|
|
432
|
+
],
|
|
429
433
|
});
|
|
430
434
|
const parsed = JSON.parse(result);
|
|
431
435
|
t.true(parsed.output[0].success);
|
|
@@ -441,9 +445,12 @@ test.serial('execute performs normalized whitespace match across line breaks', a
|
|
|
441
445
|
await fs.writeFile(absPath, 'const foo = 1;\nconst bar = 2;\nconst baz = 3;\n');
|
|
442
446
|
const result = await tool.execute({
|
|
443
447
|
path: filePath,
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
448
|
+
replacements: [
|
|
449
|
+
{
|
|
450
|
+
search_content: 'const foo = 1; const bar = 2;',
|
|
451
|
+
replace_content: 'const foo = 1;\nconst bar = 42;',
|
|
452
|
+
},
|
|
453
|
+
],
|
|
447
454
|
});
|
|
448
455
|
const parsed = JSON.parse(result);
|
|
449
456
|
t.true(parsed.output[0].success);
|
|
@@ -451,7 +458,7 @@ test.serial('execute performs normalized whitespace match across line breaks', a
|
|
|
451
458
|
t.is(updated, 'const foo = 1;\nconst bar = 42;\nconst baz = 3;\n');
|
|
452
459
|
});
|
|
453
460
|
});
|
|
454
|
-
test.serial('execute rejects multiple normalized matches
|
|
461
|
+
test.serial('execute rejects multiple normalized matches', async (t) => {
|
|
455
462
|
await withTempDir(async (dir) => {
|
|
456
463
|
const tool = createTool(createMockSettingsService({ 'tools.enableEditHealing': false }));
|
|
457
464
|
const filePath = 'normalized-multi.txt';
|
|
@@ -459,9 +466,12 @@ test.serial('execute rejects multiple normalized matches when replace_all is fal
|
|
|
459
466
|
await fs.writeFile(absPath, 'const foo = 1;\n const bar = 2;\n---\nconst foo = 1;\tconst bar = 2;\n');
|
|
460
467
|
const result = await tool.execute({
|
|
461
468
|
path: filePath,
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
469
|
+
replacements: [
|
|
470
|
+
{
|
|
471
|
+
search_content: 'const foo = 1; const bar = 2;',
|
|
472
|
+
replace_content: 'const foo = 9; const bar = 9;',
|
|
473
|
+
},
|
|
474
|
+
],
|
|
465
475
|
});
|
|
466
476
|
const parsed = JSON.parse(result);
|
|
467
477
|
t.false(parsed.output[0].success);
|
|
@@ -477,14 +487,14 @@ test.serial('execute does not match substrings in relaxed mode', async (t) => {
|
|
|
477
487
|
const absPath = path.join(dir, filePath);
|
|
478
488
|
const originalContent = ' formatted text ';
|
|
479
489
|
await fs.writeFile(absPath, originalContent);
|
|
480
|
-
// Search for "format" with different whitespace to trigger relaxed mode
|
|
481
|
-
// Relaxed mode should NOT match because it compares entire trimmed lines,
|
|
482
|
-
// and "format" (trimmed) !== "formatted text" (trimmed)
|
|
483
490
|
const result = await tool.execute({
|
|
484
491
|
path: filePath,
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
492
|
+
replacements: [
|
|
493
|
+
{
|
|
494
|
+
search_content: ' format ',
|
|
495
|
+
replace_content: 'replacement',
|
|
496
|
+
},
|
|
497
|
+
],
|
|
488
498
|
});
|
|
489
499
|
const parsed = JSON.parse(result);
|
|
490
500
|
t.false(parsed.output[0].success);
|
|
@@ -492,22 +502,20 @@ test.serial('execute does not match substrings in relaxed mode', async (t) => {
|
|
|
492
502
|
t.is(unchanged, originalContent);
|
|
493
503
|
});
|
|
494
504
|
});
|
|
495
|
-
// ============================================================================
|
|
496
|
-
// EOL Normalization Tests
|
|
497
|
-
// ============================================================================
|
|
498
505
|
test.serial('execute normalizes CRLF search content to match LF file', async (t) => {
|
|
499
506
|
await withTempDir(async (dir) => {
|
|
500
507
|
const tool = createTool();
|
|
501
508
|
const filePath = 'lf-file.txt';
|
|
502
509
|
const absPath = path.join(dir, filePath);
|
|
503
|
-
// File has LF line endings
|
|
504
510
|
await fs.writeFile(absPath, 'line one\nline two\nline three');
|
|
505
|
-
// Search content has CRLF line endings
|
|
506
511
|
const result = await tool.execute({
|
|
507
512
|
path: filePath,
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
513
|
+
replacements: [
|
|
514
|
+
{
|
|
515
|
+
search_content: 'line one\r\nline two',
|
|
516
|
+
replace_content: 'replaced',
|
|
517
|
+
},
|
|
518
|
+
],
|
|
511
519
|
});
|
|
512
520
|
const parsed = JSON.parse(result);
|
|
513
521
|
t.true(parsed.output[0].success);
|
|
@@ -520,19 +528,19 @@ test.serial('execute normalizes LF search content to match CRLF file', async (t)
|
|
|
520
528
|
const tool = createTool();
|
|
521
529
|
const filePath = 'crlf-file.txt';
|
|
522
530
|
const absPath = path.join(dir, filePath);
|
|
523
|
-
// File has CRLF line endings
|
|
524
531
|
await fs.writeFile(absPath, 'line one\r\nline two\r\nline three');
|
|
525
|
-
// Search content has LF line endings
|
|
526
532
|
const result = await tool.execute({
|
|
527
533
|
path: filePath,
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
534
|
+
replacements: [
|
|
535
|
+
{
|
|
536
|
+
search_content: 'line one\nline two',
|
|
537
|
+
replace_content: 'replaced',
|
|
538
|
+
},
|
|
539
|
+
],
|
|
531
540
|
});
|
|
532
541
|
const parsed = JSON.parse(result);
|
|
533
542
|
t.true(parsed.output[0].success);
|
|
534
543
|
const updated = await fs.readFile(absPath, 'utf8');
|
|
535
|
-
// Result should preserve the file's CRLF style
|
|
536
544
|
t.is(updated, 'replaced\r\nline three');
|
|
537
545
|
});
|
|
538
546
|
});
|
|
@@ -541,36 +549,36 @@ test.serial('execute preserves CRLF in replacement content when file uses CRLF',
|
|
|
541
549
|
const tool = createTool();
|
|
542
550
|
const filePath = 'crlf-file.txt';
|
|
543
551
|
const absPath = path.join(dir, filePath);
|
|
544
|
-
// File has CRLF line endings
|
|
545
552
|
await fs.writeFile(absPath, 'hello\r\nworld');
|
|
546
553
|
const result = await tool.execute({
|
|
547
554
|
path: filePath,
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
555
|
+
replacements: [
|
|
556
|
+
{
|
|
557
|
+
search_content: 'hello',
|
|
558
|
+
replace_content: 'new\nline',
|
|
559
|
+
},
|
|
560
|
+
],
|
|
551
561
|
});
|
|
552
562
|
const parsed = JSON.parse(result);
|
|
553
563
|
t.true(parsed.output[0].success);
|
|
554
564
|
const updated = await fs.readFile(absPath, 'utf8');
|
|
555
|
-
// Replacement should use file's CRLF style
|
|
556
565
|
t.is(updated, 'new\r\nline\r\nworld');
|
|
557
566
|
});
|
|
558
567
|
});
|
|
559
|
-
// ============================================================================
|
|
560
|
-
// Leading Filepath Comment Stripping Tests
|
|
561
|
-
// ============================================================================
|
|
562
568
|
test.serial('execute strips leading filepath comment from search content', async (t) => {
|
|
563
569
|
await withTempDir(async (dir) => {
|
|
564
570
|
const tool = createTool();
|
|
565
571
|
const filePath = 'sample.ts';
|
|
566
572
|
const absPath = path.join(dir, filePath);
|
|
567
573
|
await fs.writeFile(absPath, 'const x = 1;\nconst y = 2;');
|
|
568
|
-
// Search content has a leading filepath comment (common model behavior)
|
|
569
574
|
const result = await tool.execute({
|
|
570
575
|
path: filePath,
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
576
|
+
replacements: [
|
|
577
|
+
{
|
|
578
|
+
search_content: '// sample.ts\nconst x = 1;',
|
|
579
|
+
replace_content: 'const x = 42;',
|
|
580
|
+
},
|
|
581
|
+
],
|
|
574
582
|
});
|
|
575
583
|
const parsed = JSON.parse(result);
|
|
576
584
|
t.true(parsed.output[0].success);
|
|
@@ -586,9 +594,12 @@ test.serial('execute strips leading hash filepath comment from search content',
|
|
|
586
594
|
await fs.writeFile(absPath, 'x = 1\ny = 2');
|
|
587
595
|
const result = await tool.execute({
|
|
588
596
|
path: filePath,
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
597
|
+
replacements: [
|
|
598
|
+
{
|
|
599
|
+
search_content: '# script.py\nx = 1',
|
|
600
|
+
replace_content: 'x = 42',
|
|
601
|
+
},
|
|
602
|
+
],
|
|
592
603
|
});
|
|
593
604
|
const parsed = JSON.parse(result);
|
|
594
605
|
t.true(parsed.output[0].success);
|
|
@@ -602,12 +613,14 @@ test.serial('execute does not strip non-filepath leading comments', async (t) =>
|
|
|
602
613
|
const filePath = 'code.ts';
|
|
603
614
|
const absPath = path.join(dir, filePath);
|
|
604
615
|
await fs.writeFile(absPath, '// TODO: fix this\nconst x = 1;');
|
|
605
|
-
// This comment is not a filepath, so it should NOT be stripped
|
|
606
616
|
const result = await tool.execute({
|
|
607
617
|
path: filePath,
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
618
|
+
replacements: [
|
|
619
|
+
{
|
|
620
|
+
search_content: '// TODO: fix this\nconst x = 1;',
|
|
621
|
+
replace_content: 'const x = 42;',
|
|
622
|
+
},
|
|
623
|
+
],
|
|
611
624
|
});
|
|
612
625
|
const parsed = JSON.parse(result);
|
|
613
626
|
t.true(parsed.output[0].success);
|
|
@@ -615,9 +628,6 @@ test.serial('execute does not strip non-filepath leading comments', async (t) =>
|
|
|
615
628
|
t.is(updated, 'const x = 42;');
|
|
616
629
|
});
|
|
617
630
|
});
|
|
618
|
-
// ============================================================================
|
|
619
|
-
// Summarization Marker Detection Tests
|
|
620
|
-
// ============================================================================
|
|
621
631
|
test.serial('execute rejects search content with "Lines X-Y omitted" marker', async (t) => {
|
|
622
632
|
await withTempDir(async (dir) => {
|
|
623
633
|
const tool = createTool();
|
|
@@ -626,9 +636,12 @@ test.serial('execute rejects search content with "Lines X-Y omitted" marker', as
|
|
|
626
636
|
await fs.writeFile(absPath, 'line 1\nline 2\nline 3');
|
|
627
637
|
const result = await tool.execute({
|
|
628
638
|
path: filePath,
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
639
|
+
replacements: [
|
|
640
|
+
{
|
|
641
|
+
search_content: 'line 1\nLines 2-50 omitted\nline 3',
|
|
642
|
+
replace_content: 'replaced',
|
|
643
|
+
},
|
|
644
|
+
],
|
|
632
645
|
});
|
|
633
646
|
const parsed = JSON.parse(result);
|
|
634
647
|
t.false(parsed.output[0].success);
|
|
@@ -643,9 +656,12 @@ test.serial('execute rejects search content with ellipsis marker {…}', async (
|
|
|
643
656
|
await fs.writeFile(absPath, 'function foo() { /* code */ }');
|
|
644
657
|
const result = await tool.execute({
|
|
645
658
|
path: filePath,
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
659
|
+
replacements: [
|
|
660
|
+
{
|
|
661
|
+
search_content: 'function foo() {…}',
|
|
662
|
+
replace_content: 'replaced',
|
|
663
|
+
},
|
|
664
|
+
],
|
|
649
665
|
});
|
|
650
666
|
const parsed = JSON.parse(result);
|
|
651
667
|
t.false(parsed.output[0].success);
|
|
@@ -660,9 +676,12 @@ test.serial('execute rejects search content with /*...*/ marker', async (t) => {
|
|
|
660
676
|
await fs.writeFile(absPath, 'function foo() { return 1; }');
|
|
661
677
|
const result = await tool.execute({
|
|
662
678
|
path: filePath,
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
679
|
+
replacements: [
|
|
680
|
+
{
|
|
681
|
+
search_content: 'function foo() { /*...*/ }',
|
|
682
|
+
replace_content: 'replaced',
|
|
683
|
+
},
|
|
684
|
+
],
|
|
666
685
|
});
|
|
667
686
|
const parsed = JSON.parse(result);
|
|
668
687
|
t.false(parsed.output[0].success);
|
|
@@ -677,18 +696,18 @@ test.serial('execute rejects search content with // ... marker', async (t) => {
|
|
|
677
696
|
await fs.writeFile(absPath, 'const a = 1;\nconst b = 2;\nconst c = 3;');
|
|
678
697
|
const result = await tool.execute({
|
|
679
698
|
path: filePath,
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
699
|
+
replacements: [
|
|
700
|
+
{
|
|
701
|
+
search_content: 'const a = 1;\n// ...\nconst c = 3;',
|
|
702
|
+
replace_content: 'replaced',
|
|
703
|
+
},
|
|
704
|
+
],
|
|
683
705
|
});
|
|
684
706
|
const parsed = JSON.parse(result);
|
|
685
707
|
t.false(parsed.output[0].success);
|
|
686
708
|
t.true(parsed.output[0].error.includes('// ...'));
|
|
687
709
|
});
|
|
688
710
|
});
|
|
689
|
-
// ============================================================================
|
|
690
|
-
// Search and Replace Equality Validation Tests
|
|
691
|
-
// ============================================================================
|
|
692
711
|
test.serial('execute rejects search content when search and replace content are identical', async (t) => {
|
|
693
712
|
await withTempDir(async (dir) => {
|
|
694
713
|
const tool = createTool();
|
|
@@ -697,9 +716,12 @@ test.serial('execute rejects search content when search and replace content are
|
|
|
697
716
|
await fs.writeFile(absPath, 'hello world');
|
|
698
717
|
const result = await tool.execute({
|
|
699
718
|
path: filePath,
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
719
|
+
replacements: [
|
|
720
|
+
{
|
|
721
|
+
search_content: 'hello',
|
|
722
|
+
replace_content: 'hello',
|
|
723
|
+
},
|
|
724
|
+
],
|
|
703
725
|
});
|
|
704
726
|
const parsed = JSON.parse(result);
|
|
705
727
|
t.false(parsed.output[0].success);
|
|
@@ -714,17 +736,16 @@ test.serial('needsApproval auto-approves when search and replace content are ide
|
|
|
714
736
|
await fs.writeFile(absPath, 'hello world');
|
|
715
737
|
const result = await tool.needsApproval({
|
|
716
738
|
path: filePath,
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
739
|
+
replacements: [
|
|
740
|
+
{
|
|
741
|
+
search_content: 'hello',
|
|
742
|
+
replace_content: 'hello',
|
|
743
|
+
},
|
|
744
|
+
],
|
|
720
745
|
});
|
|
721
|
-
// Should auto-approve so execute can return the error gracefully
|
|
722
746
|
t.false(result);
|
|
723
747
|
});
|
|
724
748
|
});
|
|
725
|
-
// ============================================================================
|
|
726
|
-
// Gap Matching Tests (<...> marker)
|
|
727
|
-
// ============================================================================
|
|
728
749
|
test.serial('execute performs gap match: head <...> tail replaces entire region', async (t) => {
|
|
729
750
|
await withTempDir(async (dir) => {
|
|
730
751
|
const tool = createTool(createMockSettingsService({ 'tools.enableEditHealing': false }));
|
|
@@ -733,9 +754,12 @@ test.serial('execute performs gap match: head <...> tail replaces entire region'
|
|
|
733
754
|
await fs.writeFile(absPath, 'function foo() {\n const x = 1;\n const y = 2;\n const z = 3;\n return x + y + z;\n}\n');
|
|
734
755
|
const result = await tool.execute({
|
|
735
756
|
path: filePath,
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
757
|
+
replacements: [
|
|
758
|
+
{
|
|
759
|
+
search_content: 'function foo() {\n const x = 1;\n<...>\n return x + y + z;\n}',
|
|
760
|
+
replace_content: 'function foo() {\n return 6;\n}\n',
|
|
761
|
+
},
|
|
762
|
+
],
|
|
739
763
|
});
|
|
740
764
|
const parsed = JSON.parse(result);
|
|
741
765
|
t.true(parsed.output[0].success);
|
|
@@ -752,9 +776,12 @@ test.serial('execute performs gap match with single-line head and tail', async (
|
|
|
752
776
|
await fs.writeFile(absPath, 'start\nmiddle1\nmiddle2\nend\nafter');
|
|
753
777
|
const result = await tool.execute({
|
|
754
778
|
path: filePath,
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
779
|
+
replacements: [
|
|
780
|
+
{
|
|
781
|
+
search_content: 'start\n<...>\nend',
|
|
782
|
+
replace_content: 'replaced\n',
|
|
783
|
+
},
|
|
784
|
+
],
|
|
758
785
|
});
|
|
759
786
|
const parsed = JSON.parse(result);
|
|
760
787
|
t.true(parsed.output[0].success);
|
|
@@ -770,9 +797,12 @@ test.serial('execute performs gap match with adjacent head and tail (no actual g
|
|
|
770
797
|
await fs.writeFile(absPath, 'line1\nline2\nline3');
|
|
771
798
|
const result = await tool.execute({
|
|
772
799
|
path: filePath,
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
800
|
+
replacements: [
|
|
801
|
+
{
|
|
802
|
+
search_content: 'line1\n<...>\nline2',
|
|
803
|
+
replace_content: 'replaced\n',
|
|
804
|
+
},
|
|
805
|
+
],
|
|
776
806
|
});
|
|
777
807
|
const parsed = JSON.parse(result);
|
|
778
808
|
t.true(parsed.output[0].success);
|
|
@@ -788,9 +818,12 @@ test.serial('execute performs gap match with multiple <...> markers', async (t)
|
|
|
788
818
|
await fs.writeFile(absPath, 'function a() {\n body1;\n}\nfunction b() {\n body2;\n}\nfunction c() {\n body3;\n}\n');
|
|
789
819
|
const result = await tool.execute({
|
|
790
820
|
path: filePath,
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
821
|
+
replacements: [
|
|
822
|
+
{
|
|
823
|
+
search_content: 'function a() {\n<...>\nfunction b() {\n<...>\nfunction c() {\n body3;\n}',
|
|
824
|
+
replace_content: 'function abc() {\n combined;\n}\n',
|
|
825
|
+
},
|
|
826
|
+
],
|
|
794
827
|
});
|
|
795
828
|
const parsed = JSON.parse(result);
|
|
796
829
|
t.true(parsed.output[0].success);
|
|
@@ -806,9 +839,12 @@ test.serial('execute gap match fails when head is not found', async (t) => {
|
|
|
806
839
|
await fs.writeFile(absPath, 'line1\nline2\nline3');
|
|
807
840
|
const result = await tool.execute({
|
|
808
841
|
path: filePath,
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
842
|
+
replacements: [
|
|
843
|
+
{
|
|
844
|
+
search_content: 'nonexistent\n<...>\nline3',
|
|
845
|
+
replace_content: 'replaced',
|
|
846
|
+
},
|
|
847
|
+
],
|
|
812
848
|
});
|
|
813
849
|
const parsed = JSON.parse(result);
|
|
814
850
|
t.false(parsed.output[0].success);
|
|
@@ -822,9 +858,12 @@ test.serial('execute gap match fails when tail is not found after head', async (
|
|
|
822
858
|
await fs.writeFile(absPath, 'line1\nline2\nline3');
|
|
823
859
|
const result = await tool.execute({
|
|
824
860
|
path: filePath,
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
861
|
+
replacements: [
|
|
862
|
+
{
|
|
863
|
+
search_content: 'line1\n<...>\nnonexistent',
|
|
864
|
+
replace_content: 'replaced',
|
|
865
|
+
},
|
|
866
|
+
],
|
|
828
867
|
});
|
|
829
868
|
const parsed = JSON.parse(result);
|
|
830
869
|
t.false(parsed.output[0].success);
|
|
@@ -841,9 +880,12 @@ test.serial('execute does not invoke healing for a failed gap pattern and report
|
|
|
841
880
|
await fs.writeFile(path.join(dir, filePath), 'line1\nline2\nline3');
|
|
842
881
|
const result = await tool.execute({
|
|
843
882
|
path: filePath,
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
883
|
+
replacements: [
|
|
884
|
+
{
|
|
885
|
+
search_content: 'nonexistent\n<...>\nline3',
|
|
886
|
+
replace_content: 'replaced',
|
|
887
|
+
},
|
|
888
|
+
],
|
|
847
889
|
});
|
|
848
890
|
const parsed = JSON.parse(result);
|
|
849
891
|
t.false(parsed.output[0].success);
|
|
@@ -863,16 +905,19 @@ test.serial('execute gap diagnostic identifies the anchor that failed after the
|
|
|
863
905
|
await fs.writeFile(path.join(dir, filePath), 'line1\nline2\nline3');
|
|
864
906
|
const result = await tool.execute({
|
|
865
907
|
path: filePath,
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
908
|
+
replacements: [
|
|
909
|
+
{
|
|
910
|
+
search_content: 'line1\n<...>\nnonexistent',
|
|
911
|
+
replace_content: 'replaced',
|
|
912
|
+
},
|
|
913
|
+
],
|
|
869
914
|
});
|
|
870
915
|
const parsed = JSON.parse(result);
|
|
871
916
|
t.false(parsed.output[0].success);
|
|
872
917
|
t.regex(parsed.output[0].error, /not found after/i);
|
|
873
918
|
});
|
|
874
919
|
});
|
|
875
|
-
test.serial('execute gap match rejects multiple matches
|
|
920
|
+
test.serial('execute gap match rejects multiple matches', async (t) => {
|
|
876
921
|
await withTempDir(async (dir) => {
|
|
877
922
|
const tool = createTool(createMockSettingsService({ 'tools.enableEditHealing': false }));
|
|
878
923
|
const filePath = 'content.txt';
|
|
@@ -880,33 +925,18 @@ test.serial('execute gap match rejects multiple matches when replace_all is fals
|
|
|
880
925
|
await fs.writeFile(absPath, 'start\nmiddle1\nend\nstart\nmiddle2\nend\n');
|
|
881
926
|
const result = await tool.execute({
|
|
882
927
|
path: filePath,
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
928
|
+
replacements: [
|
|
929
|
+
{
|
|
930
|
+
search_content: 'start\n<...>\nend',
|
|
931
|
+
replace_content: 'replaced',
|
|
932
|
+
},
|
|
933
|
+
],
|
|
886
934
|
});
|
|
887
935
|
const parsed = JSON.parse(result);
|
|
888
936
|
t.false(parsed.output[0].success);
|
|
889
937
|
t.true(parsed.output[0].error.includes('gap'));
|
|
890
938
|
});
|
|
891
939
|
});
|
|
892
|
-
test.serial('execute gap match replaces all when replace_all is true', async (t) => {
|
|
893
|
-
await withTempDir(async (dir) => {
|
|
894
|
-
const tool = createTool(createMockSettingsService({ 'tools.enableEditHealing': false }));
|
|
895
|
-
const filePath = 'content.txt';
|
|
896
|
-
const absPath = path.join(dir, filePath);
|
|
897
|
-
await fs.writeFile(absPath, 'start\nmiddle1\nend\nstart\nmiddle2\nend\n');
|
|
898
|
-
const result = await tool.execute({
|
|
899
|
-
path: filePath,
|
|
900
|
-
search_content: 'start\n<...>\nend',
|
|
901
|
-
replace_content: 'replaced\n',
|
|
902
|
-
replace_all: true,
|
|
903
|
-
});
|
|
904
|
-
const parsed = JSON.parse(result);
|
|
905
|
-
t.true(parsed.output[0].success);
|
|
906
|
-
const updated = await fs.readFile(absPath, 'utf8');
|
|
907
|
-
t.is(updated, 'replaced\nreplaced\n');
|
|
908
|
-
});
|
|
909
|
-
});
|
|
910
940
|
test.serial('execute gap match works with relaxed whitespace matching in segments', async (t) => {
|
|
911
941
|
await withTempDir(async (dir) => {
|
|
912
942
|
const tool = createTool(createMockSettingsService({ 'tools.enableEditHealing': false }));
|
|
@@ -915,9 +945,12 @@ test.serial('execute gap match works with relaxed whitespace matching in segment
|
|
|
915
945
|
await fs.writeFile(absPath, ' function foo() {\n const x = 1;\n const y = 2;\n return x;\n }\n');
|
|
916
946
|
const result = await tool.execute({
|
|
917
947
|
path: filePath,
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
948
|
+
replacements: [
|
|
949
|
+
{
|
|
950
|
+
search_content: 'function foo() {\n<...>\nreturn x;\n}',
|
|
951
|
+
replace_content: 'function foo() {\n return 42;\n}\n',
|
|
952
|
+
},
|
|
953
|
+
],
|
|
921
954
|
});
|
|
922
955
|
const parsed = JSON.parse(result);
|
|
923
956
|
t.true(parsed.output[0].success);
|
|
@@ -925,19 +958,21 @@ test.serial('execute gap match works with relaxed whitespace matching in segment
|
|
|
925
958
|
t.is(updated, 'function foo() {\n return 42;\n}\n');
|
|
926
959
|
});
|
|
927
960
|
});
|
|
928
|
-
test.serial('needsApproval handles gap match
|
|
961
|
+
test.serial('needsApproval handles gap match', async (t) => {
|
|
929
962
|
await withTempDir(async (dir) => {
|
|
930
|
-
const tool = createTool(createMockSettingsService(
|
|
963
|
+
const tool = createTool(createMockSettingsService());
|
|
931
964
|
const filePath = 'content.txt';
|
|
932
965
|
const absPath = path.join(dir, filePath);
|
|
933
966
|
await fs.writeFile(absPath, 'start\nmiddle\nend\n');
|
|
934
967
|
const result = await tool.needsApproval({
|
|
935
968
|
path: filePath,
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
969
|
+
replacements: [
|
|
970
|
+
{
|
|
971
|
+
search_content: 'start\n<...>\nend',
|
|
972
|
+
replace_content: 'replaced',
|
|
973
|
+
},
|
|
974
|
+
],
|
|
939
975
|
});
|
|
940
|
-
// In edit mode with a unique gap match, should auto-approve
|
|
941
976
|
t.false(result);
|
|
942
977
|
});
|
|
943
978
|
});
|