@tyvm/knowhow 0.0.158 → 0.0.160
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/package.json +2 -2
- package/ts_build/package.json +2 -2
- package/ts_build/src/chat/CliChatService.d.ts +2 -1
- package/ts_build/src/chat/CliChatService.js +29 -3
- package/ts_build/src/chat/CliChatService.js.map +1 -1
- package/ts_build/src/chat/modules/AgentModule.js +21 -17
- package/ts_build/src/chat/modules/AgentModule.js.map +1 -1
- package/ts_build/src/chat/renderer/ConsoleRenderer.js +32 -25
- package/ts_build/src/chat/renderer/ConsoleRenderer.js.map +1 -1
- package/ts_build/src/logger.d.ts +1 -0
- package/ts_build/src/logger.js +13 -1
- package/ts_build/src/logger.js.map +1 -1
- package/ts_build/src/utils/InputQueueManager.d.ts +8 -1
- package/ts_build/src/utils/InputQueueManager.js +72 -2
- package/ts_build/src/utils/InputQueueManager.js.map +1 -1
- package/ts_build/src/utils/index.d.ts +3 -1
- package/ts_build/src/utils/index.js +11 -3
- package/ts_build/src/utils/index.js.map +1 -1
- package/CONFIG.md +0 -429
- package/PROCESSING.md +0 -450
- package/WORKER.md +0 -260
- package/autodoc/README.md +0 -324
- package/autodoc/chat-guide.md +0 -444
- package/autodoc/cli-reference.md +0 -720
- package/autodoc/config-reference.md +0 -642
- package/autodoc/embeddings-guide.md +0 -467
- package/autodoc/generate-guide.md +0 -437
- package/autodoc/language-plugin-guide.md +0 -417
- package/autodoc/modules-guide.md +0 -379
- package/autodoc/plugins-guide.md +0 -721
- package/autodoc/quickstart-guide.md +0 -126
- package/autodoc/skills-guide.md +0 -584
- package/autodoc/worker-guide.md +0 -519
- package/docs/input-queue-manager.md +0 -142
- package/docs/multi-worker-management.md +0 -142
- package/docs/shell-commands.md +0 -174
- package/jest.config.js +0 -19
- package/jest.manual.config.js +0 -19
- package/scripts/README.md +0 -119
- package/scripts/build-for-node.sh +0 -148
- package/scripts/cache-miss-debug.ts +0 -365
- package/scripts/check-isolated-deps.sh +0 -69
- package/scripts/check-model-pricing.ts +0 -509
- package/scripts/compare-openrouter-coverage.ts +0 -576
- package/scripts/migrate-usage-json.js +0 -147
- package/scripts/publish.sh +0 -86
- package/scripts/restore_keys.sh +0 -59
- package/scripts/test-repetition-hint.ts +0 -302
- package/scripts/unset_keys.sh +0 -60
- package/src/agents/base/base.ts +0 -1963
- package/src/agents/base/prompt.ts +0 -55
- package/src/agents/configurable/ConfigAgent.ts +0 -24
- package/src/agents/developer/developer.ts +0 -76
- package/src/agents/historyRollback.ts +0 -36
- package/src/agents/index.ts +0 -52
- package/src/agents/interface.ts +0 -11
- package/src/agents/patcher/codebase.md +0 -27
- package/src/agents/patcher/patcher.ts +0 -131
- package/src/agents/researcher/researcher.ts +0 -115
- package/src/agents/setup/setup.ts +0 -63
- package/src/agents/tools/addInternalTools.ts +0 -21
- package/src/agents/tools/agentCall.ts +0 -34
- package/src/agents/tools/aiClient.ts +0 -178
- package/src/agents/tools/askHuman.ts +0 -10
- package/src/agents/tools/callPlugin.ts +0 -10
- package/src/agents/tools/connectAgent.ts +0 -355
- package/src/agents/tools/embeddingSearch.ts +0 -6
- package/src/agents/tools/execCommand.ts +0 -162
- package/src/agents/tools/fileSearch.ts +0 -35
- package/src/agents/tools/finalAnswer.ts +0 -4
- package/src/agents/tools/googleSearch.ts +0 -243
- package/src/agents/tools/index.ts +0 -33
- package/src/agents/tools/language/definitions.ts +0 -105
- package/src/agents/tools/language/index.ts +0 -20
- package/src/agents/tools/lazy/definitions.ts +0 -72
- package/src/agents/tools/lazy/disableTools.ts +0 -16
- package/src/agents/tools/lazy/enableTools.ts +0 -16
- package/src/agents/tools/lazy/index.ts +0 -3
- package/src/agents/tools/lazy/listAvailableTools.ts +0 -17
- package/src/agents/tools/lintFile.ts +0 -19
- package/src/agents/tools/list.ts +0 -739
- package/src/agents/tools/loadImageAsBase64.ts +0 -83
- package/src/agents/tools/loadWebpage.ts +0 -19
- package/src/agents/tools/mcp/connectMcpServer.ts +0 -40
- package/src/agents/tools/mcp/definitions.ts +0 -67
- package/src/agents/tools/mcp/disconnectMcpServer.ts +0 -40
- package/src/agents/tools/mcp/index.ts +0 -3
- package/src/agents/tools/mcp/listAvailableMcpServers.ts +0 -28
- package/src/agents/tools/minimal/callTool.ts +0 -45
- package/src/agents/tools/minimal/definitions.ts +0 -50
- package/src/agents/tools/minimal/index.ts +0 -3
- package/src/agents/tools/minimal/inspectTools.ts +0 -27
- package/src/agents/tools/modifyFile.ts +0 -53
- package/src/agents/tools/observe.ts +0 -247
- package/src/agents/tools/patch.ts +0 -1287
- package/src/agents/tools/readBlocks.ts +0 -83
- package/src/agents/tools/readFile.ts +0 -105
- package/src/agents/tools/replyToParent.ts +0 -123
- package/src/agents/tools/runGenerate.ts +0 -210
- package/src/agents/tools/scanFile.ts +0 -16
- package/src/agents/tools/sendAgentMessage.ts +0 -139
- package/src/agents/tools/skills.ts +0 -79
- package/src/agents/tools/startAgentTask.ts +0 -393
- package/src/agents/tools/stringReplace.ts +0 -105
- package/src/agents/tools/textSearch.ts +0 -128
- package/src/agents/tools/types/fileblock.ts +0 -5
- package/src/agents/tools/visionTool.ts +0 -35
- package/src/agents/tools/waitForAgentCompleted.ts +0 -270
- package/src/agents/tools/writeFile.ts +0 -106
- package/src/agents/tools/ycmd/client.ts +0 -608
- package/src/agents/tools/ycmd/definitions.ts +0 -294
- package/src/agents/tools/ycmd/detection.ts +0 -211
- package/src/agents/tools/ycmd/index.ts +0 -11
- package/src/agents/tools/ycmd/installer.ts +0 -251
- package/src/agents/tools/ycmd/server.ts +0 -545
- package/src/agents/tools/ycmd/serverManager.ts +0 -316
- package/src/agents/tools/ycmd/tools/completion.ts +0 -113
- package/src/agents/tools/ycmd/tools/diagnostics.ts +0 -166
- package/src/agents/tools/ycmd/tools/getLocations.ts +0 -173
- package/src/agents/tools/ycmd/tools/goto.ts +0 -169
- package/src/agents/tools/ycmd/tools/refactor.ts +0 -204
- package/src/agents/tools/ycmd/tools/signature.ts +0 -174
- package/src/agents/tools/ycmd/tools/start.ts +0 -95
- package/src/agents/tools/ycmd/utils/pathUtils.ts +0 -59
- package/src/ai.ts +0 -306
- package/src/auth/browserLogin.ts +0 -406
- package/src/auth/environmentAuth.ts +0 -51
- package/src/auth/errors.ts +0 -6
- package/src/auth/jwtStore.ts +0 -70
- package/src/auth/keyAuth.ts +0 -142
- package/src/auth/keyManager.ts +0 -331
- package/src/auth/registerIdentity.ts +0 -67
- package/src/auth/spinner.ts +0 -23
- package/src/chat/CliChatService.ts +0 -438
- package/src/chat/modules/AgentModule.ts +0 -1664
- package/src/chat/modules/AskModule.ts +0 -98
- package/src/chat/modules/BaseChatModule.ts +0 -65
- package/src/chat/modules/ClipboardImageModule.ts +0 -136
- package/src/chat/modules/CustomCommandsModule.ts +0 -80
- package/src/chat/modules/InternalChatModule.ts +0 -216
- package/src/chat/modules/RemoteSyncModule.ts +0 -482
- package/src/chat/modules/RendererModule.ts +0 -139
- package/src/chat/modules/SearchModule.ts +0 -168
- package/src/chat/modules/SessionsModule.ts +0 -969
- package/src/chat/modules/SetupModule.ts +0 -185
- package/src/chat/modules/ShellCommandModule.ts +0 -98
- package/src/chat/modules/SystemModule.ts +0 -161
- package/src/chat/modules/ToolCommandModule.ts +0 -102
- package/src/chat/modules/VoiceModule.ts +0 -70
- package/src/chat/modules/index.ts +0 -8
- package/src/chat/renderer/CompactRenderer.ts +0 -229
- package/src/chat/renderer/ConsoleRenderer.ts +0 -160
- package/src/chat/renderer/FancyRenderer.ts +0 -440
- package/src/chat/renderer/PlainRenderer.ts +0 -218
- package/src/chat/renderer/index.ts +0 -6
- package/src/chat/renderer/loadRenderer.ts +0 -316
- package/src/chat/renderer/messagesToRenderEvents.ts +0 -96
- package/src/chat/renderer/types.ts +0 -99
- package/src/chat/types.ts +0 -146
- package/src/chat.ts +0 -140
- package/src/cli.ts +0 -180
- package/src/clients/anthropic.ts +0 -772
- package/src/clients/attribution.ts +0 -53
- package/src/clients/cerebras.ts +0 -10
- package/src/clients/contextLimits.ts +0 -263
- package/src/clients/copilot.ts +0 -23
- package/src/clients/deepseek.ts +0 -16
- package/src/clients/fireworks.ts +0 -71
- package/src/clients/gemini.ts +0 -1169
- package/src/clients/github.ts +0 -16
- package/src/clients/groq.ts +0 -15
- package/src/clients/http.ts +0 -719
- package/src/clients/index.ts +0 -1153
- package/src/clients/knowhow.ts +0 -130
- package/src/clients/knowhowMcp.ts +0 -118
- package/src/clients/llama.ts +0 -16
- package/src/clients/meta.ts +0 -27
- package/src/clients/mistral.ts +0 -16
- package/src/clients/nvidia.ts +0 -16
- package/src/clients/openai.ts +0 -1186
- package/src/clients/openrouter.ts +0 -24
- package/src/clients/pricing/anthropic.ts +0 -149
- package/src/clients/pricing/cerebras.ts +0 -11
- package/src/clients/pricing/copilot.ts +0 -60
- package/src/clients/pricing/deepseek.ts +0 -15
- package/src/clients/pricing/fireworks.ts +0 -182
- package/src/clients/pricing/github.ts +0 -69
- package/src/clients/pricing/google.ts +0 -385
- package/src/clients/pricing/groq.ts +0 -56
- package/src/clients/pricing/index.ts +0 -44
- package/src/clients/pricing/llama.ts +0 -18
- package/src/clients/pricing/meta.ts +0 -12
- package/src/clients/pricing/mistral.ts +0 -34
- package/src/clients/pricing/models.ts +0 -25
- package/src/clients/pricing/nvidia.ts +0 -102
- package/src/clients/pricing/openai.ts +0 -409
- package/src/clients/pricing/openrouter.ts +0 -36
- package/src/clients/pricing/qwen.ts +0 -80
- package/src/clients/pricing/types.ts +0 -125
- package/src/clients/pricing/xai.ts +0 -137
- package/src/clients/qwen.ts +0 -16
- package/src/clients/responseMetadata.ts +0 -221
- package/src/clients/types.ts +0 -531
- package/src/clients/withRetry.ts +0 -89
- package/src/clients/xai.ts +0 -693
- package/src/cloudWorker.ts +0 -394
- package/src/commands/agent.ts +0 -342
- package/src/commands/agents.ts +0 -1037
- package/src/commands/behaviors.ts +0 -47
- package/src/commands/convert.ts +0 -291
- package/src/commands/hash.ts +0 -179
- package/src/commands/mcp.ts +0 -743
- package/src/commands/misc.ts +0 -373
- package/src/commands/modules.ts +0 -704
- package/src/commands/processes.ts +0 -248
- package/src/commands/remote.ts +0 -77
- package/src/commands/replay.ts +0 -503
- package/src/commands/sandbox.ts +0 -566
- package/src/commands/services.ts +0 -168
- package/src/commands/skills.ts +0 -107
- package/src/commands/workers.ts +0 -168
- package/src/config.ts +0 -468
- package/src/conversion.ts +0 -69
- package/src/dataset/diffs/README.md +0 -12
- package/src/dataset/diffs/debug-errors.ts +0 -29
- package/src/dataset/diffs/debug.ts +0 -64
- package/src/dataset/diffs/generate.ts +0 -71
- package/src/dataset/diffs/jsonl.ts +0 -53
- package/src/dataset/diffs/test.ts +0 -194
- package/src/embeddings.ts +0 -494
- package/src/fileSync.ts +0 -369
- package/src/generate.ts +0 -529
- package/src/hashes.ts +0 -180
- package/src/index.ts +0 -261
- package/src/logger.ts +0 -197
- package/src/login.ts +0 -209
- package/src/microphone.ts +0 -141
- package/src/migrations.ts +0 -151
- package/src/plugins/AgentsMdPlugin.ts +0 -118
- package/src/plugins/GitPlugin.ts +0 -598
- package/src/plugins/LinterPlugin.ts +0 -214
- package/src/plugins/PluginBase.ts +0 -70
- package/src/plugins/SkillsPlugin.ts +0 -37
- package/src/plugins/embedding.ts +0 -82
- package/src/plugins/exec.ts +0 -70
- package/src/plugins/language.ts +0 -290
- package/src/plugins/plugins.ts +0 -175
- package/src/plugins/tmux.ts +0 -132
- package/src/plugins/types.ts +0 -36
- package/src/plugins/url.ts +0 -101
- package/src/plugins/vim.ts +0 -89
- package/src/processes/ProcessManager.ts +0 -96
- package/src/processes/managedProcessShim.ts +0 -138
- package/src/processors/Base64ImageDetector.ts +0 -502
- package/src/processors/CustomVariables.ts +0 -693
- package/src/processors/GemmaToolProcessor.ts +0 -163
- package/src/processors/HarmonyToolProcessor.ts +0 -264
- package/src/processors/JsonCompressor.ts +0 -510
- package/src/processors/MinimalToolsMessageProcessor.ts +0 -113
- package/src/processors/TokenCompressor.ts +0 -620
- package/src/processors/ToolResponseCache.ts +0 -322
- package/src/processors/XmlToolCallProcessor.ts +0 -533
- package/src/processors/index.ts +0 -14
- package/src/processors/tools/boundedToolResponse.ts +0 -49
- package/src/processors/tools/grepToolResponse.ts +0 -230
- package/src/processors/tools/index.ts +0 -23
- package/src/processors/tools/jqToolResponse.ts +0 -159
- package/src/processors/tools/listStoredToolResponses.ts +0 -124
- package/src/processors/tools/tailToolResponse.ts +0 -148
- package/src/prompts/BasicCodeDocumenter.ts +0 -1
- package/src/prompts/BasicProjectDocumenter.ts +0 -1
- package/src/prompts/EmbeddingSeachHelper.ts +0 -1
- package/src/prompts/KnowhowConfigExamples.ts +0 -376
- package/src/prompts/index.ts +0 -9
- package/src/remotes.ts +0 -110
- package/src/server/index.ts +0 -16
- package/src/services/AgentService.ts +0 -134
- package/src/services/AgentSyncFs.ts +0 -775
- package/src/services/AgentSyncKnowhowWeb.ts +0 -389
- package/src/services/BehaviorsService.ts +0 -466
- package/src/services/DockerService.ts +0 -511
- package/src/services/EmbeddingService.ts +0 -427
- package/src/services/EmbeddingsService.ts +0 -73
- package/src/services/EventService.ts +0 -279
- package/src/services/ExtensionsService.ts +0 -25
- package/src/services/KnowhowClient.ts +0 -928
- package/src/services/LazyToolsService.ts +0 -210
- package/src/services/Mcp.ts +0 -727
- package/src/services/McpServer.ts +0 -155
- package/src/services/McpWebsocketTransport.ts +0 -87
- package/src/services/MediaProcessorService.ts +0 -669
- package/src/services/MessageProcessor.ts +0 -114
- package/src/services/MinimalToolsService.ts +0 -177
- package/src/services/RuntimeReloadService.ts +0 -31
- package/src/services/S3.ts +0 -61
- package/src/services/SessionManager.ts +0 -358
- package/src/services/SkillsService.ts +0 -822
- package/src/services/SyncedAgentWatcher.ts +0 -124
- package/src/services/SyncerService.ts +0 -191
- package/src/services/TaskRegistry.ts +0 -110
- package/src/services/Tools.ts +0 -580
- package/src/services/TracingService.ts +0 -116
- package/src/services/conversion/ConversionService.ts +0 -757
- package/src/services/conversion/index.ts +0 -2
- package/src/services/conversion/types.ts +0 -87
- package/src/services/flags.ts +0 -51
- package/src/services/index.ts +0 -117
- package/src/services/modules/computerUse.ts +0 -218
- package/src/services/modules/index.ts +0 -314
- package/src/services/modules/types.ts +0 -109
- package/src/services/types.ts +0 -60
- package/src/services/watchers/FsSyncer.ts +0 -199
- package/src/services/watchers/RemoteSyncer.ts +0 -196
- package/src/services/watchers/index.ts +0 -2
- package/src/tunnel.ts +0 -243
- package/src/types.ts +0 -282
- package/src/util/Trace.ts +0 -236
- package/src/utils/InputQueueManager.ts +0 -493
- package/src/utils/errors.ts +0 -0
- package/src/utils/http.ts +0 -150
- package/src/utils/index.ts +0 -111
- package/src/worker.ts +0 -696
- package/src/workerRegistry.ts +0 -152
- package/src/workers/auth/PasskeySetup.ts +0 -181
- package/src/workers/auth/WorkerPasskeyAuth.ts +0 -190
- package/src/workers/auth/WsMiddleware.ts +0 -99
- package/src/workers/auth/authMiddleware.ts +0 -104
- package/src/workers/auth/types.ts +0 -70
- package/src/workers/tools/getChallenge.ts +0 -33
- package/src/workers/tools/index.ts +0 -20
- package/src/workers/tools/listAllowedPorts.ts +0 -30
- package/src/workers/tools/lock.ts +0 -31
- package/src/workers/tools/reloadConfig.ts +0 -84
- package/src/workers/tools/unlock.ts +0 -116
- package/tests/XmlToolCallProcessor.test.ts +0 -468
- package/tests/agents/interrupt.test.ts +0 -200
- package/tests/agents/observe-base.test.ts +0 -183
- package/tests/agents/tools/connectAgent.test.ts +0 -138
- package/tests/agents/tools/observe.test.ts +0 -179
- package/tests/agents/tools/readFile.test.ts +0 -88
- package/tests/agents/tools/replyToParent.test.ts +0 -125
- package/tests/agents/tools/sendAgentMessage.test.ts +0 -99
- package/tests/agents/tools/waitForAgentCompleted.test.ts +0 -147
- package/tests/chat/detach-attach-rendering.test.ts +0 -315
- package/tests/clients/AIClient.test.ts +0 -668
- package/tests/clients/anthropic.test.ts +0 -202
- package/tests/clients/contextLimits.test.ts +0 -97
- package/tests/clients/fireworks.test.ts +0 -65
- package/tests/clients/openai.images.test.ts +0 -105
- package/tests/clients/pricing.test.ts +0 -206
- package/tests/clients/reasoningEffort.test.ts +0 -140
- package/tests/compressor/bigstring.test.ts +0 -450
- package/tests/compressor/bigstring.txt +0 -1
- package/tests/compressor/githubjson.txt +0 -1
- package/tests/compressor/toolResponseCache.test.ts +0 -304
- package/tests/compressor/usageBase64.json +0 -159
- package/tests/compressor/usageBase64.test.ts +0 -175
- package/tests/fixtures/fake-secret.txt +0 -1
- package/tests/manual/agent-events/run-test.ts +0 -203
- package/tests/manual/browser-login/README.md +0 -189
- package/tests/manual/browser-login/test_browser_login_basic.ts +0 -115
- package/tests/manual/browser-login/test_cli_integration.ts +0 -169
- package/tests/manual/browser-login/test_cross_platform_browser.ts +0 -186
- package/tests/manual/browser-login/test_error_scenarios.ts +0 -223
- package/tests/manual/cli/no-env.sh +0 -274
- package/tests/manual/clients/completions.json +0 -1151
- package/tests/manual/clients/completions.test.ts +0 -198
- package/tests/manual/file-edits/figma.test.ts +0 -3
- package/tests/manual/file-edits/fileblocks/readwrite.test.ts +0 -100
- package/tests/manual/file-edits/patching/input.txt +0 -145
- package/tests/manual/file-edits/patching/output.txt +0 -145
- package/tests/manual/file-edits/patching/patch.txt +0 -15
- package/tests/manual/file-edits/patching/unseen.txt +0 -80
- package/tests/manual/file-edits/patching.test.ts +0 -139
- package/tests/manual/modalities/README.md +0 -157
- package/tests/manual/modalities/google.modalities.test.ts +0 -335
- package/tests/manual/modalities/openai.modalities.test.ts +0 -329
- package/tests/manual/modalities/streaming.test.ts +0 -260
- package/tests/manual/modalities/xai.modalities.test.ts +0 -294
- package/tests/manual/test-concurrent-ask.ts +0 -43
- package/tests/manual/ycmd/debug_diagnostics_test.ts +0 -127
- package/tests/manual/ycmd/fixtures/debug_diagnostics.ts +0 -26
- package/tests/manual/ycmd/fixtures/file_change_test.ts +0 -17
- package/tests/manual/ycmd/minimal_advanced_test.ts +0 -108
- package/tests/manual/ycmd/simple_diagnostics_test.ts +0 -61
- package/tests/manual/ycmd/simple_test.ts +0 -74
- package/tests/manual/ycmd/test-typescript-sample.ts +0 -34
- package/tests/manual/ycmd/test_advanced_features.ts +0 -407
- package/tests/manual/ycmd/test_advanced_with_tools.ts +0 -320
- package/tests/manual/ycmd/test_comprehensive_typescript.ts +0 -179
- package/tests/manual/ycmd/test_diagnostics_file_changes.ts +0 -249
- package/tests/manual/ycmd/test_diagnostics_fix.ts +0 -99
- package/tests/manual/ycmd/test_diagnostics_simple.ts +0 -100
- package/tests/manual/ycmd/test_diagnostics_timing.ts +0 -120
- package/tests/manual/ycmd/test_discover_commands.ts +0 -310
- package/tests/manual/ycmd/test_endpoints.ts +0 -115
- package/tests/manual/ycmd/test_final_comprehensive.ts +0 -218
- package/tests/manual/ycmd/test_final_validation.ts +0 -150
- package/tests/manual/ycmd/test_implementation.js +0 -42
- package/tests/manual/ycmd/test_individual_ycmd_tool.ts +0 -39
- package/tests/manual/ycmd/test_server_manager.ts +0 -52
- package/tests/manual/ycmd/test_simple_debug.ts +0 -86
- package/tests/manual/ycmd/test_tsserver_workflow.js +0 -83
- package/tests/manual/ycmd/test_tsserver_workflow.ts +0 -122
- package/tests/manual/ycmd/test_typescript_simple.ts +0 -48
- package/tests/manual/ycmd/test_typescript_ycmd.ts +0 -105
- package/tests/manual/ycmd/test_workspace_config.ts +0 -90
- package/tests/manual/ycmd/test_ycmd_auto_start.ts +0 -137
- package/tests/manual/ycmd/test_ycmd_comprehensive.ts +0 -73
- package/tests/manual/ycmd/test_ycmd_connection.py +0 -10
- package/tests/manual/ycmd/test_ycmd_direct.ts +0 -142
- package/tests/manual/ycmd/test_ycmd_experiment.ts +0 -48
- package/tests/manual/ycmd/test_ycmd_final.ts +0 -200
- package/tests/manual/ycmd/test_ycmd_fixed.py +0 -18
- package/tests/manual/ycmd/test_ycmd_integration.ts +0 -112
- package/tests/manual/ycmd/test_ycmd_simple.ts +0 -45
- package/tests/manual/ycmd/test_ycmd_usage.py +0 -27
- package/tests/manual/ycmd/working_simple_test.ts +0 -134
- package/tests/patching/corrupted.test.ts +0 -78
- package/tests/patching/fixtures/transcript-mangles/agent-sync-fs-nested-catch.json +0 -9
- package/tests/patching/fixtures/transcript-mangles/automation-functions-crossed.json +0 -9
- package/tests/patching/fixtures/transcript-mangles/fruit-ninja-confirmed-retirement.json +0 -8
- package/tests/patching/imports.patch.txt +0 -11
- package/tests/patching/imports.test.ts +0 -43
- package/tests/patching/imports.txt +0 -11
- package/tests/patching/interface.patch.txt +0 -15
- package/tests/patching/interface.txt +0 -7
- package/tests/patching/patchFileOutput.test.ts +0 -328
- package/tests/patching/regression-2026.test.ts +0 -752
- package/tests/patching/transcriptMangleRegression.test.ts +0 -125
- package/tests/plugins/language/languagePlugin-content-triggers.test.ts +0 -346
- package/tests/plugins/language/languagePlugin-integration.test.ts +0 -471
- package/tests/plugins/language/languagePlugin.test.ts +0 -385
- package/tests/processes/managedProcessShim.test.ts +0 -59
- package/tests/processors/Base64ImageDetector.test.ts +0 -979
- package/tests/processors/CustomVariables.test.ts +0 -981
- package/tests/processors/CustomVariablesBenchmark.test.ts +0 -237
- package/tests/processors/HarmonyToolProcessor.test.ts +0 -490
- package/tests/processors/TokenCompressor.test.ts +0 -674
- package/tests/processors/ToolResponseCache.test.ts +0 -864
- package/tests/processors/tools/boundedRetrievalTools.test.ts +0 -68
- package/tests/processors/tools/grepToolResponse.test.ts +0 -159
- package/tests/services/ConversionService.test.ts +0 -154
- package/tests/services/DockerService.test.ts +0 -24
- package/tests/services/Tools.test.ts +0 -1738
- package/tests/services/ToolsService.setFunction.test.ts +0 -68
- package/tests/services/WorkerReloadConfig.test.ts +0 -141
- package/tests/test.spec.ts +0 -163
- package/tests/unit/InputQueueManager.test.ts +0 -174
- package/tests/unit/McpWebsocketTransport.test.ts +0 -56
- package/tests/unit/agents/historyRollback.test.ts +0 -53
- package/tests/unit/agents/tools/loadImageAsBase64.test.ts +0 -44
- package/tests/unit/auth/jwtStore.test.ts +0 -55
- package/tests/unit/auth/keyAuth.test.ts +0 -152
- package/tests/unit/auth/keyManager.test.ts +0 -130
- package/tests/unit/auth/registerIdentity.test.ts +0 -99
- package/tests/unit/chat/ToolCommandModule.test.ts +0 -71
- package/tests/unit/chat/historyCommandArgs.test.ts +0 -37
- package/tests/unit/clients/AIClient.test.ts +0 -454
- package/tests/unit/clients/anthropic.responseMetadata.test.ts +0 -81
- package/tests/unit/clients/attribution.test.ts +0 -185
- package/tests/unit/clients/http.responseMetadata.test.ts +0 -86
- package/tests/unit/clients/openai.responseMetadata.test.ts +0 -90
- package/tests/unit/clients/responseMetadata.test.ts +0 -123
- package/tests/unit/clients/withRetry.test.ts +0 -319
- package/tests/unit/commands/agents.test.ts +0 -111
- package/tests/unit/commands/github-credentials.test.ts +0 -210
- package/tests/unit/commands/misc.test.ts +0 -85
- package/tests/unit/commands/remote.test.ts +0 -79
- package/tests/unit/commands/sandbox.test.ts +0 -350
- package/tests/unit/hashes.test.ts +0 -23
- package/tests/unit/input-queue.test.ts +0 -80
- package/tests/unit/login.test.ts +0 -218
- package/tests/unit/modules/moduleLoading.test.ts +0 -305
- package/tests/unit/plugins/pluginLoading.test.ts +0 -97
- package/tests/unit/services/AgentSyncKnowhowWeb.test.ts +0 -38
- package/tests/unit/services/KnowhowClient.test.ts +0 -84
- package/tests/unit/services/LazyToolsService.test.ts +0 -53
- package/tests/unit/services/Mcp.test.ts +0 -56
- package/tests/unit/services/MinimalToolsService.test.ts +0 -424
- package/tests/unit/services/RuntimeReloadService.test.ts +0 -29
- package/tests/unit/services/SessionManager.test.ts +0 -43
- package/tests/unit/services/SyncedAgentWatcher.test.ts +0 -89
- package/tests/unit/services/SyncerService.test.ts +0 -45
- package/tests/unit/tunnel.test.ts +0 -51
- package/tests/unit/util/Trace.test.ts +0 -119
- package/tests/unit/utils/http.test.ts +0 -43
- package/ts_build/tests/XmlToolCallProcessor.test.d.ts +0 -1
- package/ts_build/tests/XmlToolCallProcessor.test.js +0 -376
- package/ts_build/tests/XmlToolCallProcessor.test.js.map +0 -1
- package/ts_build/tests/agents/interrupt.test.d.ts +0 -14
- package/ts_build/tests/agents/interrupt.test.js +0 -136
- package/ts_build/tests/agents/interrupt.test.js.map +0 -1
- package/ts_build/tests/agents/observe-base.test.d.ts +0 -1
- package/ts_build/tests/agents/observe-base.test.js +0 -149
- package/ts_build/tests/agents/observe-base.test.js.map +0 -1
- package/ts_build/tests/agents/tools/connectAgent.test.d.ts +0 -1
- package/ts_build/tests/agents/tools/connectAgent.test.js +0 -142
- package/ts_build/tests/agents/tools/connectAgent.test.js.map +0 -1
- package/ts_build/tests/agents/tools/observe.test.d.ts +0 -1
- package/ts_build/tests/agents/tools/observe.test.js +0 -148
- package/ts_build/tests/agents/tools/observe.test.js.map +0 -1
- package/ts_build/tests/agents/tools/readFile.test.d.ts +0 -1
- package/ts_build/tests/agents/tools/readFile.test.js +0 -90
- package/ts_build/tests/agents/tools/readFile.test.js.map +0 -1
- package/ts_build/tests/agents/tools/replyToParent.test.d.ts +0 -1
- package/ts_build/tests/agents/tools/replyToParent.test.js +0 -116
- package/ts_build/tests/agents/tools/replyToParent.test.js.map +0 -1
- package/ts_build/tests/agents/tools/sendAgentMessage.test.d.ts +0 -1
- package/ts_build/tests/agents/tools/sendAgentMessage.test.js +0 -112
- package/ts_build/tests/agents/tools/sendAgentMessage.test.js.map +0 -1
- package/ts_build/tests/agents/tools/waitForAgentCompleted.test.d.ts +0 -1
- package/ts_build/tests/agents/tools/waitForAgentCompleted.test.js +0 -147
- package/ts_build/tests/agents/tools/waitForAgentCompleted.test.js.map +0 -1
- package/ts_build/tests/chat/detach-attach-rendering.test.d.ts +0 -1
- package/ts_build/tests/chat/detach-attach-rendering.test.js +0 -168
- package/ts_build/tests/chat/detach-attach-rendering.test.js.map +0 -1
- package/ts_build/tests/clients/AIClient.test.d.ts +0 -1
- package/ts_build/tests/clients/AIClient.test.js +0 -483
- package/ts_build/tests/clients/AIClient.test.js.map +0 -1
- package/ts_build/tests/clients/anthropic.test.d.ts +0 -1
- package/ts_build/tests/clients/anthropic.test.js +0 -159
- package/ts_build/tests/clients/anthropic.test.js.map +0 -1
- package/ts_build/tests/clients/contextLimits.test.d.ts +0 -1
- package/ts_build/tests/clients/contextLimits.test.js +0 -69
- package/ts_build/tests/clients/contextLimits.test.js.map +0 -1
- package/ts_build/tests/clients/fireworks.test.d.ts +0 -1
- package/ts_build/tests/clients/fireworks.test.js +0 -65
- package/ts_build/tests/clients/fireworks.test.js.map +0 -1
- package/ts_build/tests/clients/openai.images.test.d.ts +0 -1
- package/ts_build/tests/clients/openai.images.test.js +0 -94
- package/ts_build/tests/clients/openai.images.test.js.map +0 -1
- package/ts_build/tests/clients/pricing.test.d.ts +0 -1
- package/ts_build/tests/clients/pricing.test.js +0 -124
- package/ts_build/tests/clients/pricing.test.js.map +0 -1
- package/ts_build/tests/clients/reasoningEffort.test.d.ts +0 -1
- package/ts_build/tests/clients/reasoningEffort.test.js +0 -116
- package/ts_build/tests/clients/reasoningEffort.test.js.map +0 -1
- package/ts_build/tests/compressor/bigstring.test.d.ts +0 -1
- package/ts_build/tests/compressor/bigstring.test.js +0 -275
- package/ts_build/tests/compressor/bigstring.test.js.map +0 -1
- package/ts_build/tests/compressor/toolResponseCache.test.d.ts +0 -1
- package/ts_build/tests/compressor/toolResponseCache.test.js +0 -250
- package/ts_build/tests/compressor/toolResponseCache.test.js.map +0 -1
- package/ts_build/tests/compressor/usageBase64.test.d.ts +0 -1
- package/ts_build/tests/compressor/usageBase64.test.js +0 -109
- package/ts_build/tests/compressor/usageBase64.test.js.map +0 -1
- package/ts_build/tests/manual/agent-events/run-test.d.ts +0 -2
- package/ts_build/tests/manual/agent-events/run-test.js +0 -148
- package/ts_build/tests/manual/agent-events/run-test.js.map +0 -1
- package/ts_build/tests/manual/browser-login/test_browser_login_basic.d.ts +0 -2
- package/ts_build/tests/manual/browser-login/test_browser_login_basic.js +0 -118
- package/ts_build/tests/manual/browser-login/test_browser_login_basic.js.map +0 -1
- package/ts_build/tests/manual/browser-login/test_cli_integration.d.ts +0 -2
- package/ts_build/tests/manual/browser-login/test_cli_integration.js +0 -163
- package/ts_build/tests/manual/browser-login/test_cli_integration.js.map +0 -1
- package/ts_build/tests/manual/browser-login/test_cross_platform_browser.d.ts +0 -2
- package/ts_build/tests/manual/browser-login/test_cross_platform_browser.js +0 -169
- package/ts_build/tests/manual/browser-login/test_cross_platform_browser.js.map +0 -1
- package/ts_build/tests/manual/browser-login/test_error_scenarios.d.ts +0 -2
- package/ts_build/tests/manual/browser-login/test_error_scenarios.js +0 -207
- package/ts_build/tests/manual/browser-login/test_error_scenarios.js.map +0 -1
- package/ts_build/tests/manual/clients/completions.test.d.ts +0 -1
- package/ts_build/tests/manual/clients/completions.test.js +0 -151
- package/ts_build/tests/manual/clients/completions.test.js.map +0 -1
- package/ts_build/tests/manual/file-edits/figma.test.d.ts +0 -0
- package/ts_build/tests/manual/file-edits/figma.test.js +0 -2
- package/ts_build/tests/manual/file-edits/figma.test.js.map +0 -1
- package/ts_build/tests/manual/file-edits/fileblocks/readwrite.test.d.ts +0 -1
- package/ts_build/tests/manual/file-edits/fileblocks/readwrite.test.js +0 -110
- package/ts_build/tests/manual/file-edits/fileblocks/readwrite.test.js.map +0 -1
- package/ts_build/tests/manual/file-edits/patching.test.d.ts +0 -1
- package/ts_build/tests/manual/file-edits/patching.test.js +0 -129
- package/ts_build/tests/manual/file-edits/patching.test.js.map +0 -1
- package/ts_build/tests/manual/modalities/google.modalities.test.d.ts +0 -1
- package/ts_build/tests/manual/modalities/google.modalities.test.js +0 -262
- package/ts_build/tests/manual/modalities/google.modalities.test.js.map +0 -1
- package/ts_build/tests/manual/modalities/openai.modalities.test.d.ts +0 -1
- package/ts_build/tests/manual/modalities/openai.modalities.test.js +0 -262
- package/ts_build/tests/manual/modalities/openai.modalities.test.js.map +0 -1
- package/ts_build/tests/manual/modalities/streaming.test.d.ts +0 -1
- package/ts_build/tests/manual/modalities/streaming.test.js +0 -216
- package/ts_build/tests/manual/modalities/streaming.test.js.map +0 -1
- package/ts_build/tests/manual/modalities/xai.modalities.test.d.ts +0 -1
- package/ts_build/tests/manual/modalities/xai.modalities.test.js +0 -219
- package/ts_build/tests/manual/modalities/xai.modalities.test.js.map +0 -1
- package/ts_build/tests/manual/test-concurrent-ask.d.ts +0 -1
- package/ts_build/tests/manual/test-concurrent-ask.js +0 -22
- package/ts_build/tests/manual/test-concurrent-ask.js.map +0 -1
- package/ts_build/tests/manual/ycmd/debug_diagnostics_test.d.ts +0 -1
- package/ts_build/tests/manual/ycmd/debug_diagnostics_test.js +0 -124
- package/ts_build/tests/manual/ycmd/debug_diagnostics_test.js.map +0 -1
- package/ts_build/tests/manual/ycmd/minimal_advanced_test.d.ts +0 -2
- package/ts_build/tests/manual/ycmd/minimal_advanced_test.js +0 -114
- package/ts_build/tests/manual/ycmd/minimal_advanced_test.js.map +0 -1
- package/ts_build/tests/manual/ycmd/simple_diagnostics_test.d.ts +0 -1
- package/ts_build/tests/manual/ycmd/simple_diagnostics_test.js +0 -84
- package/ts_build/tests/manual/ycmd/simple_diagnostics_test.js.map +0 -1
- package/ts_build/tests/manual/ycmd/simple_test.d.ts +0 -2
- package/ts_build/tests/manual/ycmd/simple_test.js +0 -92
- package/ts_build/tests/manual/ycmd/simple_test.js.map +0 -1
- package/ts_build/tests/manual/ycmd/test-typescript-sample.d.ts +0 -14
- package/ts_build/tests/manual/ycmd/test-typescript-sample.js +0 -20
- package/ts_build/tests/manual/ycmd/test-typescript-sample.js.map +0 -1
- package/ts_build/tests/manual/ycmd/test_advanced_features.d.ts +0 -2
- package/ts_build/tests/manual/ycmd/test_advanced_features.js +0 -306
- package/ts_build/tests/manual/ycmd/test_advanced_features.js.map +0 -1
- package/ts_build/tests/manual/ycmd/test_advanced_with_tools.d.ts +0 -3
- package/ts_build/tests/manual/ycmd/test_advanced_with_tools.js +0 -271
- package/ts_build/tests/manual/ycmd/test_advanced_with_tools.js.map +0 -1
- package/ts_build/tests/manual/ycmd/test_comprehensive_typescript.d.ts +0 -2
- package/ts_build/tests/manual/ycmd/test_comprehensive_typescript.js +0 -196
- package/ts_build/tests/manual/ycmd/test_comprehensive_typescript.js.map +0 -1
- package/ts_build/tests/manual/ycmd/test_diagnostics_file_changes.d.ts +0 -1
- package/ts_build/tests/manual/ycmd/test_diagnostics_file_changes.js +0 -184
- package/ts_build/tests/manual/ycmd/test_diagnostics_file_changes.js.map +0 -1
- package/ts_build/tests/manual/ycmd/test_diagnostics_fix.d.ts +0 -2
- package/ts_build/tests/manual/ycmd/test_diagnostics_fix.js +0 -116
- package/ts_build/tests/manual/ycmd/test_diagnostics_fix.js.map +0 -1
- package/ts_build/tests/manual/ycmd/test_diagnostics_simple.d.ts +0 -1
- package/ts_build/tests/manual/ycmd/test_diagnostics_simple.js +0 -114
- package/ts_build/tests/manual/ycmd/test_diagnostics_simple.js.map +0 -1
- package/ts_build/tests/manual/ycmd/test_diagnostics_timing.d.ts +0 -1
- package/ts_build/tests/manual/ycmd/test_diagnostics_timing.js +0 -129
- package/ts_build/tests/manual/ycmd/test_diagnostics_timing.js.map +0 -1
- package/ts_build/tests/manual/ycmd/test_discover_commands.d.ts +0 -2
- package/ts_build/tests/manual/ycmd/test_discover_commands.js +0 -252
- package/ts_build/tests/manual/ycmd/test_discover_commands.js.map +0 -1
- package/ts_build/tests/manual/ycmd/test_endpoints.d.ts +0 -2
- package/ts_build/tests/manual/ycmd/test_endpoints.js +0 -130
- package/ts_build/tests/manual/ycmd/test_endpoints.js.map +0 -1
- package/ts_build/tests/manual/ycmd/test_final_comprehensive.d.ts +0 -2
- package/ts_build/tests/manual/ycmd/test_final_comprehensive.js +0 -231
- package/ts_build/tests/manual/ycmd/test_final_comprehensive.js.map +0 -1
- package/ts_build/tests/manual/ycmd/test_final_validation.d.ts +0 -2
- package/ts_build/tests/manual/ycmd/test_final_validation.js +0 -170
- package/ts_build/tests/manual/ycmd/test_final_validation.js.map +0 -1
- package/ts_build/tests/manual/ycmd/test_individual_ycmd_tool.d.ts +0 -2
- package/ts_build/tests/manual/ycmd/test_individual_ycmd_tool.js +0 -37
- package/ts_build/tests/manual/ycmd/test_individual_ycmd_tool.js.map +0 -1
- package/ts_build/tests/manual/ycmd/test_server_manager.d.ts +0 -1
- package/ts_build/tests/manual/ycmd/test_server_manager.js +0 -38
- package/ts_build/tests/manual/ycmd/test_server_manager.js.map +0 -1
- package/ts_build/tests/manual/ycmd/test_simple_debug.d.ts +0 -2
- package/ts_build/tests/manual/ycmd/test_simple_debug.js +0 -109
- package/ts_build/tests/manual/ycmd/test_simple_debug.js.map +0 -1
- package/ts_build/tests/manual/ycmd/test_tsserver_workflow.d.ts +0 -1
- package/ts_build/tests/manual/ycmd/test_tsserver_workflow.js +0 -138
- package/ts_build/tests/manual/ycmd/test_tsserver_workflow.js.map +0 -1
- package/ts_build/tests/manual/ycmd/test_typescript_simple.d.ts +0 -1
- package/ts_build/tests/manual/ycmd/test_typescript_simple.js +0 -76
- package/ts_build/tests/manual/ycmd/test_typescript_simple.js.map +0 -1
- package/ts_build/tests/manual/ycmd/test_typescript_ycmd.d.ts +0 -1
- package/ts_build/tests/manual/ycmd/test_typescript_ycmd.js +0 -115
- package/ts_build/tests/manual/ycmd/test_typescript_ycmd.js.map +0 -1
- package/ts_build/tests/manual/ycmd/test_workspace_config.d.ts +0 -1
- package/ts_build/tests/manual/ycmd/test_workspace_config.js +0 -99
- package/ts_build/tests/manual/ycmd/test_workspace_config.js.map +0 -1
- package/ts_build/tests/manual/ycmd/test_ycmd_auto_start.d.ts +0 -2
- package/ts_build/tests/manual/ycmd/test_ycmd_auto_start.js +0 -140
- package/ts_build/tests/manual/ycmd/test_ycmd_auto_start.js.map +0 -1
- package/ts_build/tests/manual/ycmd/test_ycmd_comprehensive.d.ts +0 -1
- package/ts_build/tests/manual/ycmd/test_ycmd_comprehensive.js +0 -93
- package/ts_build/tests/manual/ycmd/test_ycmd_comprehensive.js.map +0 -1
- package/ts_build/tests/manual/ycmd/test_ycmd_direct.d.ts +0 -2
- package/ts_build/tests/manual/ycmd/test_ycmd_direct.js +0 -159
- package/ts_build/tests/manual/ycmd/test_ycmd_direct.js.map +0 -1
- package/ts_build/tests/manual/ycmd/test_ycmd_experiment.d.ts +0 -15
- package/ts_build/tests/manual/ycmd/test_ycmd_experiment.js +0 -68
- package/ts_build/tests/manual/ycmd/test_ycmd_experiment.js.map +0 -1
- package/ts_build/tests/manual/ycmd/test_ycmd_final.d.ts +0 -2
- package/ts_build/tests/manual/ycmd/test_ycmd_final.js +0 -205
- package/ts_build/tests/manual/ycmd/test_ycmd_final.js.map +0 -1
- package/ts_build/tests/manual/ycmd/test_ycmd_integration.d.ts +0 -3
- package/ts_build/tests/manual/ycmd/test_ycmd_integration.js +0 -119
- package/ts_build/tests/manual/ycmd/test_ycmd_integration.js.map +0 -1
- package/ts_build/tests/manual/ycmd/test_ycmd_simple.d.ts +0 -2
- package/ts_build/tests/manual/ycmd/test_ycmd_simple.js +0 -36
- package/ts_build/tests/manual/ycmd/test_ycmd_simple.js.map +0 -1
- package/ts_build/tests/manual/ycmd/working_simple_test.d.ts +0 -2
- package/ts_build/tests/manual/ycmd/working_simple_test.js +0 -144
- package/ts_build/tests/manual/ycmd/working_simple_test.js.map +0 -1
- package/ts_build/tests/patching/corrupted.test.d.ts +0 -1
- package/ts_build/tests/patching/corrupted.test.js +0 -53
- package/ts_build/tests/patching/corrupted.test.js.map +0 -1
- package/ts_build/tests/patching/imports.test.d.ts +0 -1
- package/ts_build/tests/patching/imports.test.js +0 -71
- package/ts_build/tests/patching/imports.test.js.map +0 -1
- package/ts_build/tests/patching/patchFileOutput.test.d.ts +0 -1
- package/ts_build/tests/patching/patchFileOutput.test.js +0 -269
- package/ts_build/tests/patching/patchFileOutput.test.js.map +0 -1
- package/ts_build/tests/patching/regression-2026.test.d.ts +0 -1
- package/ts_build/tests/patching/regression-2026.test.js +0 -528
- package/ts_build/tests/patching/regression-2026.test.js.map +0 -1
- package/ts_build/tests/patching/transcriptMangleRegression.test.d.ts +0 -1
- package/ts_build/tests/patching/transcriptMangleRegression.test.js +0 -104
- package/ts_build/tests/patching/transcriptMangleRegression.test.js.map +0 -1
- package/ts_build/tests/plugins/language/languagePlugin-content-triggers.test.d.ts +0 -1
- package/ts_build/tests/plugins/language/languagePlugin-content-triggers.test.js +0 -294
- package/ts_build/tests/plugins/language/languagePlugin-content-triggers.test.js.map +0 -1
- package/ts_build/tests/plugins/language/languagePlugin-integration.test.d.ts +0 -1
- package/ts_build/tests/plugins/language/languagePlugin-integration.test.js +0 -343
- package/ts_build/tests/plugins/language/languagePlugin-integration.test.js.map +0 -1
- package/ts_build/tests/plugins/language/languagePlugin.test.d.ts +0 -1
- package/ts_build/tests/plugins/language/languagePlugin.test.js +0 -315
- package/ts_build/tests/plugins/language/languagePlugin.test.js.map +0 -1
- package/ts_build/tests/processes/managedProcessShim.test.d.ts +0 -1
- package/ts_build/tests/processes/managedProcessShim.test.js +0 -92
- package/ts_build/tests/processes/managedProcessShim.test.js.map +0 -1
- package/ts_build/tests/processors/Base64ImageDetector.test.d.ts +0 -1
- package/ts_build/tests/processors/Base64ImageDetector.test.js +0 -792
- package/ts_build/tests/processors/Base64ImageDetector.test.js.map +0 -1
- package/ts_build/tests/processors/CustomVariables.test.d.ts +0 -1
- package/ts_build/tests/processors/CustomVariables.test.js +0 -764
- package/ts_build/tests/processors/CustomVariables.test.js.map +0 -1
- package/ts_build/tests/processors/CustomVariablesBenchmark.test.d.ts +0 -1
- package/ts_build/tests/processors/CustomVariablesBenchmark.test.js +0 -179
- package/ts_build/tests/processors/CustomVariablesBenchmark.test.js.map +0 -1
- package/ts_build/tests/processors/HarmonyToolProcessor.test.d.ts +0 -1
- package/ts_build/tests/processors/HarmonyToolProcessor.test.js +0 -382
- package/ts_build/tests/processors/HarmonyToolProcessor.test.js.map +0 -1
- package/ts_build/tests/processors/TokenCompressor.test.d.ts +0 -1
- package/ts_build/tests/processors/TokenCompressor.test.js +0 -473
- package/ts_build/tests/processors/TokenCompressor.test.js.map +0 -1
- package/ts_build/tests/processors/ToolResponseCache.test.d.ts +0 -1
- package/ts_build/tests/processors/ToolResponseCache.test.js +0 -657
- package/ts_build/tests/processors/ToolResponseCache.test.js.map +0 -1
- package/ts_build/tests/processors/tools/boundedRetrievalTools.test.d.ts +0 -1
- package/ts_build/tests/processors/tools/boundedRetrievalTools.test.js +0 -57
- package/ts_build/tests/processors/tools/boundedRetrievalTools.test.js.map +0 -1
- package/ts_build/tests/processors/tools/grepToolResponse.test.d.ts +0 -1
- package/ts_build/tests/processors/tools/grepToolResponse.test.js +0 -77
- package/ts_build/tests/processors/tools/grepToolResponse.test.js.map +0 -1
- package/ts_build/tests/services/ConversionService.test.d.ts +0 -1
- package/ts_build/tests/services/ConversionService.test.js +0 -154
- package/ts_build/tests/services/ConversionService.test.js.map +0 -1
- package/ts_build/tests/services/DockerService.test.d.ts +0 -1
- package/ts_build/tests/services/DockerService.test.js +0 -22
- package/ts_build/tests/services/DockerService.test.js.map +0 -1
- package/ts_build/tests/services/Tools.test.d.ts +0 -1
- package/ts_build/tests/services/Tools.test.js +0 -1365
- package/ts_build/tests/services/Tools.test.js.map +0 -1
- package/ts_build/tests/services/ToolsService.setFunction.test.d.ts +0 -1
- package/ts_build/tests/services/ToolsService.setFunction.test.js +0 -51
- package/ts_build/tests/services/ToolsService.setFunction.test.js.map +0 -1
- package/ts_build/tests/services/WorkerReloadConfig.test.d.ts +0 -1
- package/ts_build/tests/services/WorkerReloadConfig.test.js +0 -86
- package/ts_build/tests/services/WorkerReloadConfig.test.js.map +0 -1
- package/ts_build/tests/test.spec.d.ts +0 -1
- package/ts_build/tests/test.spec.js +0 -139
- package/ts_build/tests/test.spec.js.map +0 -1
- package/ts_build/tests/unit/InputQueueManager.test.d.ts +0 -1
- package/ts_build/tests/unit/InputQueueManager.test.js +0 -104
- package/ts_build/tests/unit/InputQueueManager.test.js.map +0 -1
- package/ts_build/tests/unit/McpWebsocketTransport.test.d.ts +0 -1
- package/ts_build/tests/unit/McpWebsocketTransport.test.js +0 -47
- package/ts_build/tests/unit/McpWebsocketTransport.test.js.map +0 -1
- package/ts_build/tests/unit/agents/historyRollback.test.d.ts +0 -1
- package/ts_build/tests/unit/agents/historyRollback.test.js +0 -42
- package/ts_build/tests/unit/agents/historyRollback.test.js.map +0 -1
- package/ts_build/tests/unit/agents/tools/loadImageAsBase64.test.d.ts +0 -1
- package/ts_build/tests/unit/agents/tools/loadImageAsBase64.test.js +0 -67
- package/ts_build/tests/unit/agents/tools/loadImageAsBase64.test.js.map +0 -1
- package/ts_build/tests/unit/auth/jwtStore.test.d.ts +0 -1
- package/ts_build/tests/unit/auth/jwtStore.test.js +0 -46
- package/ts_build/tests/unit/auth/jwtStore.test.js.map +0 -1
- package/ts_build/tests/unit/auth/keyAuth.test.d.ts +0 -1
- package/ts_build/tests/unit/auth/keyAuth.test.js +0 -118
- package/ts_build/tests/unit/auth/keyAuth.test.js.map +0 -1
- package/ts_build/tests/unit/auth/keyManager.test.d.ts +0 -1
- package/ts_build/tests/unit/auth/keyManager.test.js +0 -96
- package/ts_build/tests/unit/auth/keyManager.test.js.map +0 -1
- package/ts_build/tests/unit/auth/registerIdentity.test.d.ts +0 -1
- package/ts_build/tests/unit/auth/registerIdentity.test.js +0 -92
- package/ts_build/tests/unit/auth/registerIdentity.test.js.map +0 -1
- package/ts_build/tests/unit/chat/ToolCommandModule.test.d.ts +0 -1
- package/ts_build/tests/unit/chat/ToolCommandModule.test.js +0 -61
- package/ts_build/tests/unit/chat/ToolCommandModule.test.js.map +0 -1
- package/ts_build/tests/unit/chat/historyCommandArgs.test.d.ts +0 -1
- package/ts_build/tests/unit/chat/historyCommandArgs.test.js +0 -29
- package/ts_build/tests/unit/chat/historyCommandArgs.test.js.map +0 -1
- package/ts_build/tests/unit/clients/AIClient.test.d.ts +0 -1
- package/ts_build/tests/unit/clients/AIClient.test.js +0 -342
- package/ts_build/tests/unit/clients/AIClient.test.js.map +0 -1
- package/ts_build/tests/unit/clients/anthropic.responseMetadata.test.d.ts +0 -1
- package/ts_build/tests/unit/clients/anthropic.responseMetadata.test.js +0 -77
- package/ts_build/tests/unit/clients/anthropic.responseMetadata.test.js.map +0 -1
- package/ts_build/tests/unit/clients/attribution.test.d.ts +0 -1
- package/ts_build/tests/unit/clients/attribution.test.js +0 -153
- package/ts_build/tests/unit/clients/attribution.test.js.map +0 -1
- package/ts_build/tests/unit/clients/http.responseMetadata.test.d.ts +0 -1
- package/ts_build/tests/unit/clients/http.responseMetadata.test.js +0 -77
- package/ts_build/tests/unit/clients/http.responseMetadata.test.js.map +0 -1
- package/ts_build/tests/unit/clients/openai.responseMetadata.test.d.ts +0 -1
- package/ts_build/tests/unit/clients/openai.responseMetadata.test.js +0 -86
- package/ts_build/tests/unit/clients/openai.responseMetadata.test.js.map +0 -1
- package/ts_build/tests/unit/clients/responseMetadata.test.d.ts +0 -1
- package/ts_build/tests/unit/clients/responseMetadata.test.js +0 -96
- package/ts_build/tests/unit/clients/responseMetadata.test.js.map +0 -1
- package/ts_build/tests/unit/clients/withRetry.test.d.ts +0 -1
- package/ts_build/tests/unit/clients/withRetry.test.js +0 -225
- package/ts_build/tests/unit/clients/withRetry.test.js.map +0 -1
- package/ts_build/tests/unit/commands/agents.test.d.ts +0 -1
- package/ts_build/tests/unit/commands/agents.test.js +0 -119
- package/ts_build/tests/unit/commands/agents.test.js.map +0 -1
- package/ts_build/tests/unit/commands/github-credentials.test.d.ts +0 -1
- package/ts_build/tests/unit/commands/github-credentials.test.js +0 -145
- package/ts_build/tests/unit/commands/github-credentials.test.js.map +0 -1
- package/ts_build/tests/unit/commands/misc.test.d.ts +0 -1
- package/ts_build/tests/unit/commands/misc.test.js +0 -70
- package/ts_build/tests/unit/commands/misc.test.js.map +0 -1
- package/ts_build/tests/unit/commands/remote.test.d.ts +0 -1
- package/ts_build/tests/unit/commands/remote.test.js +0 -70
- package/ts_build/tests/unit/commands/remote.test.js.map +0 -1
- package/ts_build/tests/unit/commands/sandbox.test.d.ts +0 -1
- package/ts_build/tests/unit/commands/sandbox.test.js +0 -258
- package/ts_build/tests/unit/commands/sandbox.test.js.map +0 -1
- package/ts_build/tests/unit/hashes.test.d.ts +0 -1
- package/ts_build/tests/unit/hashes.test.js +0 -25
- package/ts_build/tests/unit/hashes.test.js.map +0 -1
- package/ts_build/tests/unit/input-queue.test.d.ts +0 -1
- package/ts_build/tests/unit/input-queue.test.js +0 -32
- package/ts_build/tests/unit/input-queue.test.js.map +0 -1
- package/ts_build/tests/unit/login.test.d.ts +0 -1
- package/ts_build/tests/unit/login.test.js +0 -166
- package/ts_build/tests/unit/login.test.js.map +0 -1
- package/ts_build/tests/unit/modules/moduleLoading.test.d.ts +0 -1
- package/ts_build/tests/unit/modules/moduleLoading.test.js +0 -272
- package/ts_build/tests/unit/modules/moduleLoading.test.js.map +0 -1
- package/ts_build/tests/unit/plugins/pluginLoading.test.d.ts +0 -1
- package/ts_build/tests/unit/plugins/pluginLoading.test.js +0 -117
- package/ts_build/tests/unit/plugins/pluginLoading.test.js.map +0 -1
- package/ts_build/tests/unit/services/AgentSyncKnowhowWeb.test.d.ts +0 -1
- package/ts_build/tests/unit/services/AgentSyncKnowhowWeb.test.js +0 -32
- package/ts_build/tests/unit/services/AgentSyncKnowhowWeb.test.js.map +0 -1
- package/ts_build/tests/unit/services/KnowhowClient.test.d.ts +0 -1
- package/ts_build/tests/unit/services/KnowhowClient.test.js +0 -69
- package/ts_build/tests/unit/services/KnowhowClient.test.js.map +0 -1
- package/ts_build/tests/unit/services/LazyToolsService.test.d.ts +0 -1
- package/ts_build/tests/unit/services/LazyToolsService.test.js +0 -47
- package/ts_build/tests/unit/services/LazyToolsService.test.js.map +0 -1
- package/ts_build/tests/unit/services/Mcp.test.d.ts +0 -1
- package/ts_build/tests/unit/services/Mcp.test.js +0 -45
- package/ts_build/tests/unit/services/Mcp.test.js.map +0 -1
- package/ts_build/tests/unit/services/MinimalToolsService.test.d.ts +0 -1
- package/ts_build/tests/unit/services/MinimalToolsService.test.js +0 -320
- package/ts_build/tests/unit/services/MinimalToolsService.test.js.map +0 -1
- package/ts_build/tests/unit/services/RuntimeReloadService.test.d.ts +0 -1
- package/ts_build/tests/unit/services/RuntimeReloadService.test.js +0 -26
- package/ts_build/tests/unit/services/RuntimeReloadService.test.js.map +0 -1
- package/ts_build/tests/unit/services/SessionManager.test.d.ts +0 -1
- package/ts_build/tests/unit/services/SessionManager.test.js +0 -72
- package/ts_build/tests/unit/services/SessionManager.test.js.map +0 -1
- package/ts_build/tests/unit/services/SyncedAgentWatcher.test.d.ts +0 -1
- package/ts_build/tests/unit/services/SyncedAgentWatcher.test.js +0 -78
- package/ts_build/tests/unit/services/SyncedAgentWatcher.test.js.map +0 -1
- package/ts_build/tests/unit/services/SyncerService.test.d.ts +0 -1
- package/ts_build/tests/unit/services/SyncerService.test.js +0 -40
- package/ts_build/tests/unit/services/SyncerService.test.js.map +0 -1
- package/ts_build/tests/unit/tunnel.test.d.ts +0 -1
- package/ts_build/tests/unit/tunnel.test.js +0 -47
- package/ts_build/tests/unit/tunnel.test.js.map +0 -1
- package/ts_build/tests/unit/util/Trace.test.d.ts +0 -1
- package/ts_build/tests/unit/util/Trace.test.js +0 -107
- package/ts_build/tests/unit/util/Trace.test.js.map +0 -1
- package/ts_build/tests/unit/utils/http.test.d.ts +0 -1
- package/ts_build/tests/unit/utils/http.test.js +0 -69
- package/ts_build/tests/unit/utils/http.test.js.map +0 -1
- package/tsconfig.json +0 -34
- package/tslint.json +0 -11
|
@@ -1,1287 +0,0 @@
|
|
|
1
|
-
import * as fs from "fs";
|
|
2
|
-
import * as util from "util";
|
|
3
|
-
// Assuming 'diff' library provides applyPatch and createTwoFilesPatch (or similar for basic patch creation if needed later)
|
|
4
|
-
import { applyPatch, createTwoFilesPatch } from "diff";
|
|
5
|
-
import {
|
|
6
|
-
writeFile,
|
|
7
|
-
readFile,
|
|
8
|
-
fileExists,
|
|
9
|
-
mkdir,
|
|
10
|
-
splitByNewLines,
|
|
11
|
-
} from "../../utils"; // Assuming these utils exist
|
|
12
|
-
import { services, ToolsService } from "../../services";
|
|
13
|
-
|
|
14
|
-
// --- Utility Functions (Keep or Simplify) ---
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Finds all 1-based line numbers where a line (trimmed) matches the search text.
|
|
18
|
-
*/
|
|
19
|
-
function findAllLineNumbers(fullText: string, searchText: string): number[] {
|
|
20
|
-
const lines = splitByNewLines(fullText);
|
|
21
|
-
const search =
|
|
22
|
-
searchText.startsWith("+") || searchText.startsWith("-")
|
|
23
|
-
? searchText.slice(1).trim()
|
|
24
|
-
: searchText.trim();
|
|
25
|
-
|
|
26
|
-
if (!search) return []; // Don't match empty lines everywhere
|
|
27
|
-
|
|
28
|
-
const lineNumbers: number[] = [];
|
|
29
|
-
lines.forEach((line, index) => {
|
|
30
|
-
if (line.trim() === search) {
|
|
31
|
-
lineNumbers.push(index + 1);
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
return lineNumbers;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Finds the number in a list closest to the goal number.
|
|
39
|
-
*/
|
|
40
|
-
function findClosestNumber(
|
|
41
|
-
numbers: number[],
|
|
42
|
-
goal: number
|
|
43
|
-
): number | undefined {
|
|
44
|
-
if (!numbers || numbers.length === 0) {
|
|
45
|
-
return undefined; // Return undefined if no numbers to choose from
|
|
46
|
-
}
|
|
47
|
-
return numbers.reduce((prev, curr) => {
|
|
48
|
-
return Math.abs(curr - goal) < Math.abs(prev - goal) ? curr : prev;
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Finds the starting index (0-based) of a sequence (needle) within a larger array (haystack),
|
|
54
|
-
* using a while loop.
|
|
55
|
-
* * @param haystack The array to search within.
|
|
56
|
-
* @param needle The sequence of strings to find.
|
|
57
|
-
* @returns The 0-based starting index of the first occurrence of the needle, or -1 if not found.
|
|
58
|
-
*/
|
|
59
|
-
function findSequenceIndex(haystack: string[], needle: string[]): number {
|
|
60
|
-
// Basic edge cases
|
|
61
|
-
if (!needle || needle.length === 0) {
|
|
62
|
-
// console.warn("findSequenceIndex: Needle is empty."); // Or return 0 depending on desired behavior for empty needle
|
|
63
|
-
return -1; // Cannot find an empty sequence according to original logic
|
|
64
|
-
}
|
|
65
|
-
if (!haystack || needle.length > haystack.length) {
|
|
66
|
-
return -1; // Needle cannot exist if it's longer than haystack
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
let haystackIndex = 0; // Current position to start searching for needle[0] in haystack
|
|
70
|
-
|
|
71
|
-
// Continue searching as long as there's enough space left in the haystack
|
|
72
|
-
// for the needle to potentially fit.
|
|
73
|
-
while (haystackIndex <= haystack.length - needle.length) {
|
|
74
|
-
// Find the *next* occurrence of the *first* element of the needle
|
|
75
|
-
// starting from the current haystackIndex.
|
|
76
|
-
const potentialStartIndex = haystack.indexOf(needle[0], haystackIndex);
|
|
77
|
-
|
|
78
|
-
// If the first element of the needle is not found anymore, the sequence cannot be found.
|
|
79
|
-
if (potentialStartIndex === -1) {
|
|
80
|
-
return -1;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Optimization: If the found index doesn't leave enough room for the rest of the needle, stop.
|
|
84
|
-
if (potentialStartIndex > haystack.length - needle.length) {
|
|
85
|
-
return -1;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// Found the first element, now check if the rest of the sequence matches.
|
|
89
|
-
let sequenceMatches = true;
|
|
90
|
-
for (let needleIndex = 1; needleIndex < needle.length; needleIndex++) {
|
|
91
|
-
// If any element in the sequence doesn't match, break the inner loop.
|
|
92
|
-
if (haystack[potentialStartIndex + needleIndex] !== needle[needleIndex]) {
|
|
93
|
-
sequenceMatches = false;
|
|
94
|
-
break;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// If the inner loop completed without breaking, the sequence matches.
|
|
99
|
-
if (sequenceMatches) {
|
|
100
|
-
return potentialStartIndex; // Return the index where the sequence starts.
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// If the sequence didn't match starting at potentialStartIndex,
|
|
104
|
-
// continue searching for needle[0] *after* the current potentialStartIndex.
|
|
105
|
-
haystackIndex = potentialStartIndex + 1;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// If the while loop finishes without returning, the sequence was not found.
|
|
109
|
-
return -1;
|
|
110
|
-
} // --- Hunk Parsing and Formatting (Keep as is) ---
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Like findSequenceIndex but compares lines by trimmed content, so it tolerates
|
|
114
|
-
* leading/trailing whitespace drift between a hand-written patch and the file.
|
|
115
|
-
* Returns the 0-based start index in haystack, or -1.
|
|
116
|
-
*/
|
|
117
|
-
function findSequenceIndexTrimmed(
|
|
118
|
-
haystack: string[],
|
|
119
|
-
needle: string[]
|
|
120
|
-
): number {
|
|
121
|
-
if (!needle || needle.length === 0) return -1;
|
|
122
|
-
if (!haystack || needle.length > haystack.length) return -1;
|
|
123
|
-
const needleTrim = needle.map((l) => l.trim());
|
|
124
|
-
for (let start = 0; start <= haystack.length - needle.length; start++) {
|
|
125
|
-
let matches = true;
|
|
126
|
-
for (let i = 0; i < needle.length; i++) {
|
|
127
|
-
if (haystack[start + i].trim() !== needleTrim[i]) {
|
|
128
|
-
matches = false;
|
|
129
|
-
break;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
if (matches) return start;
|
|
133
|
-
}
|
|
134
|
-
return -1;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
export interface Hunk {
|
|
138
|
-
header: string;
|
|
139
|
-
originalStartLine: number; // Parsed from -s,l
|
|
140
|
-
originalLineCount: number; // Parsed from -s,l
|
|
141
|
-
newStartLine: number; // Parsed from +s,l
|
|
142
|
-
newLineCount: number; // Parsed from +s,l
|
|
143
|
-
lines: string[]; // All lines in the hunk body (context, -, +)
|
|
144
|
-
// Derived properties for convenience
|
|
145
|
-
additions: string[];
|
|
146
|
-
subtractions: string[];
|
|
147
|
-
contextLines: string[];
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
export function parseHunks(patch: string): Hunk[] {
|
|
151
|
-
const patchLines = splitByNewLines(patch);
|
|
152
|
-
const hunks: Hunk[] = [];
|
|
153
|
-
let currentHunkLines: string[] = [];
|
|
154
|
-
let currentHeader = "";
|
|
155
|
-
let originalStart = 0;
|
|
156
|
-
let originalCount = 0;
|
|
157
|
-
let newStart = 0;
|
|
158
|
-
let newCount = 0;
|
|
159
|
-
|
|
160
|
-
for (const line of patchLines) {
|
|
161
|
-
if (line.startsWith("@@")) {
|
|
162
|
-
// Finalize previous hunk
|
|
163
|
-
if (currentHeader) {
|
|
164
|
-
const additions = currentHunkLines.filter((l) => l.startsWith("+"));
|
|
165
|
-
const subtractions = currentHunkLines.filter((l) => l.startsWith("-"));
|
|
166
|
-
const contextLines = currentHunkLines.filter((l) => l.startsWith(" "));
|
|
167
|
-
hunks.push({
|
|
168
|
-
header: currentHeader,
|
|
169
|
-
originalStartLine: originalStart,
|
|
170
|
-
originalLineCount: originalCount,
|
|
171
|
-
newStartLine: newStart,
|
|
172
|
-
newLineCount: newCount,
|
|
173
|
-
lines: currentHunkLines,
|
|
174
|
-
additions,
|
|
175
|
-
subtractions,
|
|
176
|
-
contextLines,
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
// Start new hunk
|
|
180
|
-
currentHeader = line;
|
|
181
|
-
currentHunkLines = [];
|
|
182
|
-
const match = line.match(/@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/);
|
|
183
|
-
if (match) {
|
|
184
|
-
originalStart = parseInt(match[1], 10);
|
|
185
|
-
originalCount = parseInt(match[2] || "1", 10); // Default length is 1 if omitted
|
|
186
|
-
newStart = parseInt(match[3], 10);
|
|
187
|
-
newCount = parseInt(match[4] || "1", 10); // Default length is 1 if omitted
|
|
188
|
-
} else {
|
|
189
|
-
// Malformed header, use defaults or throw error? Using defaults for robustness.
|
|
190
|
-
originalStart = 0;
|
|
191
|
-
originalCount = 0;
|
|
192
|
-
newStart = 0;
|
|
193
|
-
newCount = 0;
|
|
194
|
-
console.warn("Could not parse hunk header:", line);
|
|
195
|
-
}
|
|
196
|
-
} else if (
|
|
197
|
-
currentHeader &&
|
|
198
|
-
(line.startsWith(" ") ||
|
|
199
|
-
line.startsWith("+") ||
|
|
200
|
-
line.startsWith("-") ||
|
|
201
|
-
line === "\")
|
|
202
|
-
) {
|
|
203
|
-
currentHunkLines.push(line);
|
|
204
|
-
}
|
|
205
|
-
// Ignore lines before first header or lines not part of hunk content (like index, ---, +++)
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
// Finalize the last hunk
|
|
209
|
-
if (currentHeader) {
|
|
210
|
-
const additions = currentHunkLines.filter((l) => l.startsWith("+"));
|
|
211
|
-
const subtractions = currentHunkLines.filter((l) => l.startsWith("-"));
|
|
212
|
-
const contextLines = currentHunkLines.filter((l) => l.startsWith(" "));
|
|
213
|
-
hunks.push({
|
|
214
|
-
header: currentHeader,
|
|
215
|
-
originalStartLine: originalStart,
|
|
216
|
-
originalLineCount: originalCount,
|
|
217
|
-
newStartLine: newStart,
|
|
218
|
-
newLineCount: newCount,
|
|
219
|
-
lines: currentHunkLines,
|
|
220
|
-
additions,
|
|
221
|
-
subtractions,
|
|
222
|
-
contextLines,
|
|
223
|
-
});
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
return hunks;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
export function hunksToPatch(hunks: Hunk[]): string {
|
|
230
|
-
const noNewLineMessage = "\";
|
|
231
|
-
return hunks
|
|
232
|
-
.map((hunk) => {
|
|
233
|
-
// Check if the last line might be the no-newline indicator and handle it
|
|
234
|
-
let lines = [...hunk.lines];
|
|
235
|
-
let endsWithNoNewline = false;
|
|
236
|
-
if (lines[lines.length - 1]?.trim() === noNewLineMessage.trim()) {
|
|
237
|
-
endsWithNoNewline = true;
|
|
238
|
-
lines = lines.slice(0, -1); // Temporarily remove for join
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
let hunkContent = lines.join("\n");
|
|
242
|
-
if (endsWithNoNewline) {
|
|
243
|
-
hunkContent += "\n" + noNewLineMessage;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
return [hunk.header, hunkContent].join("\n");
|
|
247
|
-
})
|
|
248
|
-
.join("\n");
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
/**
|
|
252
|
-
* Checks if a hunk results in no effective change.
|
|
253
|
-
*/
|
|
254
|
-
export function hunkIsEmpty(hunk: Hunk): boolean {
|
|
255
|
-
const noLines = hunk.lines.length === 0;
|
|
256
|
-
const noChanges =
|
|
257
|
-
hunk.additions.length === 0 && hunk.subtractions.length === 0;
|
|
258
|
-
|
|
259
|
-
// Check if additions and subtractions exactly cancel each other out
|
|
260
|
-
const additionsText = hunk.additions.map((l) => l.slice(1)).join("\n");
|
|
261
|
-
const subtractionsText = hunk.subtractions.map((l) => l.slice(1)).join("\n");
|
|
262
|
-
const noEffectiveChange = additionsText === subtractionsText;
|
|
263
|
-
|
|
264
|
-
return noLines || noChanges || noEffectiveChange;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
// --- Core Patch Fixing Logic (Rewrite) ---
|
|
268
|
-
|
|
269
|
-
const CONTEXT_LINES = 3; // Standard number of context lines
|
|
270
|
-
|
|
271
|
-
/**
|
|
272
|
-
* Attempts to fix a single hunk by anchoring it to the original content
|
|
273
|
-
* and regenerating context and header.
|
|
274
|
-
*/
|
|
275
|
-
function fixSingleHunk(hunk: Hunk, originalContent: string): Hunk | null {
|
|
276
|
-
const originalLines = splitByNewLines(originalContent);
|
|
277
|
-
|
|
278
|
-
// Special case: pure creation hunk on empty file (@@ -0,0 +1,N @@)
|
|
279
|
-
if (originalContent === "" && hunk.originalStartLine === 0 && hunk.originalLineCount === 0) {
|
|
280
|
-
return hunk; // Already valid, pass through as-is
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
const deletionLinesContent = hunk.subtractions.map((l) => l.slice(1));
|
|
284
|
-
const additionLinesContent = hunk.additions.map((l) => l.slice(1));
|
|
285
|
-
|
|
286
|
-
let actualOriginalStartLine = -1; // 1-based line number of the first deletion/change
|
|
287
|
-
|
|
288
|
-
// 1. Try to anchor using the exact sequence of deleted lines
|
|
289
|
-
if (deletionLinesContent.length > 0) {
|
|
290
|
-
const deletionStartIndex = findSequenceIndex(
|
|
291
|
-
originalLines,
|
|
292
|
-
deletionLinesContent
|
|
293
|
-
);
|
|
294
|
-
if (deletionStartIndex !== -1) {
|
|
295
|
-
actualOriginalStartLine = deletionStartIndex + 1; // Convert 0-based index to 1-based line number
|
|
296
|
-
console.log(
|
|
297
|
-
`Anchor found via deletion sequence at line ${actualOriginalStartLine}`
|
|
298
|
-
);
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
// 1b. If full sequence not found (non-contiguous deletions), anchor on first deletion alone
|
|
302
|
-
if (actualOriginalStartLine === -1) {
|
|
303
|
-
const firstDeletionLines = findAllLineNumbers(originalContent, deletionLinesContent[0]);
|
|
304
|
-
const closest = findClosestNumber(firstDeletionLines, hunk.originalStartLine);
|
|
305
|
-
if (closest !== undefined) {
|
|
306
|
-
actualOriginalStartLine = closest;
|
|
307
|
-
console.log(`Anchor found via first deletion line at line ${actualOriginalStartLine}`);
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
// 2. If deletions didn't anchor, try anchoring using context *before* the first change
|
|
313
|
-
// (This is more complex and heuristic, let's focus on deletion anchor first for simplicity)
|
|
314
|
-
// ... (Could add logic here using findAllLineNumbers/findClosestNumber for context lines near hunk.originalStartLine if needed as fallback) ...
|
|
315
|
-
|
|
316
|
-
// 3. If only additions, try anchoring using context *before* the first addition.
|
|
317
|
-
if (
|
|
318
|
-
actualOriginalStartLine === -1 &&
|
|
319
|
-
deletionLinesContent.length === 0 &&
|
|
320
|
-
additionLinesContent.length > 0
|
|
321
|
-
) {
|
|
322
|
-
// Collect the FULL leading context block (all context lines that appear before the
|
|
323
|
-
// first addition) so we can anchor on the whole sequence. This is far more reliable
|
|
324
|
-
// than a single preceding line when that line (e.g. a closing `}`) is ambiguous and
|
|
325
|
-
// appears multiple times in the file.
|
|
326
|
-
const leadingContextBlock: string[] = [];
|
|
327
|
-
for (const line of hunk.lines) {
|
|
328
|
-
if (line.startsWith("+")) break; // Stop when we hit the first addition
|
|
329
|
-
if (line.startsWith(" ")) {
|
|
330
|
-
leadingContextBlock.push(line.slice(1));
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
// 3a. Try to anchor on the full leading context sequence first (unambiguous).
|
|
335
|
-
if (leadingContextBlock.length > 1) {
|
|
336
|
-
const seqIdx = findSequenceIndex(originalLines, leadingContextBlock);
|
|
337
|
-
if (seqIdx !== -1) {
|
|
338
|
-
// Additions go AFTER the full leading context block.
|
|
339
|
-
actualOriginalStartLine = seqIdx + leadingContextBlock.length + 1;
|
|
340
|
-
console.log(
|
|
341
|
-
`Anchor found via leading context sequence (${leadingContextBlock.length} lines), targeting line ${actualOriginalStartLine}`
|
|
342
|
-
);
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
// 3b. Fall back to the single preceding context line (closest to the header hint).
|
|
347
|
-
if (actualOriginalStartLine === -1 && leadingContextBlock.length > 0) {
|
|
348
|
-
const precedingContextLine =
|
|
349
|
-
leadingContextBlock[leadingContextBlock.length - 1];
|
|
350
|
-
const potentialLines = findAllLineNumbers(
|
|
351
|
-
originalContent,
|
|
352
|
-
precedingContextLine
|
|
353
|
-
);
|
|
354
|
-
const closestLine = findClosestNumber(
|
|
355
|
-
potentialLines,
|
|
356
|
-
hunk.originalStartLine
|
|
357
|
-
); // Use original header as hint
|
|
358
|
-
if (closestLine !== undefined) {
|
|
359
|
-
// The change happens *after* this context line
|
|
360
|
-
actualOriginalStartLine = closestLine + 1;
|
|
361
|
-
console.log(
|
|
362
|
-
`Anchor found via preceding context '${precedingContextLine}' targeting line ${actualOriginalStartLine}`
|
|
363
|
-
);
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
// If we couldn't find a reliable anchor, we can't fix this hunk.
|
|
369
|
-
if (actualOriginalStartLine === -1) {
|
|
370
|
-
console.warn("Could not determine anchor point for hunk:", hunk.header);
|
|
371
|
-
// Try a last resort: Assume the original header's start line was roughly correct
|
|
372
|
-
// Find *any* non-added line from the hunk in the original source near the expected start.
|
|
373
|
-
let fallbackAnchorFound = false;
|
|
374
|
-
for (let i = 0; i < hunk.lines.length; i++) {
|
|
375
|
-
const line = hunk.lines[i];
|
|
376
|
-
if (line.startsWith("+")) continue; // Skip additions
|
|
377
|
-
|
|
378
|
-
const lineContent = line.slice(1);
|
|
379
|
-
const potentialLines = findAllLineNumbers(originalContent, lineContent);
|
|
380
|
-
if (potentialLines.length > 0) {
|
|
381
|
-
const closestLine = findClosestNumber(
|
|
382
|
-
potentialLines,
|
|
383
|
-
hunk.originalStartLine + i
|
|
384
|
-
); // Estimate position
|
|
385
|
-
if (closestLine !== undefined) {
|
|
386
|
-
// Calculate the *start* based on this line's position in the hunk
|
|
387
|
-
let offset = 0;
|
|
388
|
-
for (let j = 0; j < i; j++) {
|
|
389
|
-
if (!hunk.lines[j].startsWith("+")) {
|
|
390
|
-
// Count original lines before this one
|
|
391
|
-
offset++;
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
actualOriginalStartLine = closestLine - offset;
|
|
395
|
-
console.log(
|
|
396
|
-
`Fallback anchor found via line '${lineContent}' near ${hunk.originalStartLine}, estimated start: ${actualOriginalStartLine}`
|
|
397
|
-
);
|
|
398
|
-
fallbackAnchorFound = true;
|
|
399
|
-
break;
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
if (!fallbackAnchorFound) {
|
|
404
|
-
console.error("Failed to find any anchor for hunk:", hunk.header);
|
|
405
|
-
return null;
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
// Ensure start line is at least 1
|
|
410
|
-
actualOriginalStartLine = Math.max(1, actualOriginalStartLine);
|
|
411
|
-
|
|
412
|
-
// 4a. Detect interleaved hunks (context lines between change blocks)
|
|
413
|
-
// If so, preserve original body order, just filter ghost context lines and fix header
|
|
414
|
-
let hasInterleavedChanges = false;
|
|
415
|
-
let seenChange = false;
|
|
416
|
-
let seenContextAfterChange = false;
|
|
417
|
-
for (const line of hunk.lines) {
|
|
418
|
-
if (line.startsWith("+") || line.startsWith("-")) {
|
|
419
|
-
if (seenContextAfterChange) { hasInterleavedChanges = true; break; }
|
|
420
|
-
seenChange = true;
|
|
421
|
-
} else if (line.startsWith(" ") && seenChange) {
|
|
422
|
-
seenContextAfterChange = true;
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
// Check if there are more changes after a context block
|
|
426
|
-
if (seenContextAfterChange) {
|
|
427
|
-
for (const line of hunk.lines.slice(hunk.lines.findIndex((l, i) => {
|
|
428
|
-
let sc = false;
|
|
429
|
-
for (let j = 0; j <= i; j++) {
|
|
430
|
-
if (hunk.lines[j].startsWith("+") || hunk.lines[j].startsWith("-")) sc = true;
|
|
431
|
-
if (sc && hunk.lines[j].startsWith(" ") && j === i) return true;
|
|
432
|
-
}
|
|
433
|
-
return false;
|
|
434
|
-
}))) {
|
|
435
|
-
if (line.startsWith("+") || line.startsWith("-")) { hasInterleavedChanges = true; break; }
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
if (hasInterleavedChanges) {
|
|
440
|
-
// Preferred strategy: in-order reconstruction.
|
|
441
|
-
//
|
|
442
|
-
// The block-grouping fallback below is lossy — it skips addition-only
|
|
443
|
-
// blocks (dropping inserted lines) and re-orders additions relative to
|
|
444
|
-
// surrounding context, which corrupts nested scopes (e.g. moving a
|
|
445
|
-
// replaced object property outside of its `{ ... }`). Before falling back
|
|
446
|
-
// to it, try to anchor the hunk's "original side" (context + deletions, in
|
|
447
|
-
// order) as a contiguous region of the file and rebuild that region by
|
|
448
|
-
// walking the hunk body in order. This preserves the exact author intent.
|
|
449
|
-
{
|
|
450
|
-
// The sequence of lines the hunk expects to exist in the original file,
|
|
451
|
-
// in order (context lines and deletions; additions are new).
|
|
452
|
-
const originalSideLines: string[] = [];
|
|
453
|
-
for (const line of hunk.lines) {
|
|
454
|
-
if (line.startsWith("+")) continue;
|
|
455
|
-
originalSideLines.push(line.startsWith(" ") || line.startsWith("-") ? line.slice(1) : line);
|
|
456
|
-
}
|
|
457
|
-
// Drop trailing blank context lines that patches sometimes include after
|
|
458
|
-
// the last real line — they aren't part of the file region and break the
|
|
459
|
-
// contiguous anchor match.
|
|
460
|
-
while (
|
|
461
|
-
originalSideLines.length > 0 &&
|
|
462
|
-
originalSideLines[originalSideLines.length - 1].trim() === ""
|
|
463
|
-
) {
|
|
464
|
-
originalSideLines.pop();
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
if (originalSideLines.length > 0) {
|
|
468
|
-
// Prefer an exact anchor; fall back to a whitespace-tolerant match so
|
|
469
|
-
// hand-written patches with slightly off indentation still apply.
|
|
470
|
-
let anchorIdx = findSequenceIndex(originalLines, originalSideLines);
|
|
471
|
-
let usedTrimmed = false;
|
|
472
|
-
if (anchorIdx === -1) {
|
|
473
|
-
anchorIdx = findSequenceIndexTrimmed(originalLines, originalSideLines);
|
|
474
|
-
usedTrimmed = anchorIdx !== -1;
|
|
475
|
-
}
|
|
476
|
-
if (anchorIdx !== -1) {
|
|
477
|
-
// The file's actual lines for this region (authoritative indentation).
|
|
478
|
-
const fileRegion = originalLines.slice(
|
|
479
|
-
anchorIdx,
|
|
480
|
-
anchorIdx + originalSideLines.length
|
|
481
|
-
);
|
|
482
|
-
// Compute indentation correction: difference between the file's first
|
|
483
|
-
// context line indentation and the patch's first original-side line.
|
|
484
|
-
const fileIndent = (fileRegion[0].match(/^\s*/) || [""])[0];
|
|
485
|
-
const patchIndent = (originalSideLines[0].match(/^\s*/) || [""])[0];
|
|
486
|
-
const indentDelta =
|
|
487
|
-
usedTrimmed && fileIndent.length >= patchIndent.length
|
|
488
|
-
? fileIndent.slice(patchIndent.length)
|
|
489
|
-
: "";
|
|
490
|
-
// Rebuild the anchored region by replaying the hunk body in order.
|
|
491
|
-
// For context lines we use the file's authoritative version; for
|
|
492
|
-
// additions we re-indent by the computed delta.
|
|
493
|
-
const rebuilt: string[] = [];
|
|
494
|
-
let origCursor = 0; // index into fileRegion for context/deletion lines
|
|
495
|
-
for (const line of hunk.lines) {
|
|
496
|
-
if (line.startsWith("+")) {
|
|
497
|
-
rebuilt.push(indentDelta + line.slice(1));
|
|
498
|
-
} else if (line.startsWith("-")) {
|
|
499
|
-
origCursor++; // consume a file line, drop it
|
|
500
|
-
} else {
|
|
501
|
-
// context line. If it is a trailing line beyond the anchored
|
|
502
|
-
// region (e.g. a formatting-artifact blank line), ignore it.
|
|
503
|
-
if (origCursor >= fileRegion.length) continue;
|
|
504
|
-
// Otherwise keep the file's authoritative version.
|
|
505
|
-
rebuilt.push(fileRegion[origCursor]);
|
|
506
|
-
origCursor++;
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
// Emit a pure replacement hunk: delete the file's authoritative
|
|
511
|
-
// region and insert the rebuilt content. The deletion content is an
|
|
512
|
-
// exact, contiguous slice of the file, so the diff library anchors it
|
|
513
|
-
// unambiguously without needing surrounding context lines.
|
|
514
|
-
const newBody: string[] = [
|
|
515
|
-
...fileRegion.map((l) => `-${l}`),
|
|
516
|
-
...rebuilt.map((l) => `+${l}`),
|
|
517
|
-
];
|
|
518
|
-
|
|
519
|
-
const origCountR = fileRegion.length;
|
|
520
|
-
const newCountR = rebuilt.length;
|
|
521
|
-
const headerR = `@@ -${anchorIdx + 1},${origCountR} +${anchorIdx + 1},${newCountR} @@`;
|
|
522
|
-
|
|
523
|
-
return {
|
|
524
|
-
header: headerR,
|
|
525
|
-
originalStartLine: anchorIdx + 1,
|
|
526
|
-
originalLineCount: origCountR,
|
|
527
|
-
newStartLine: anchorIdx + 1,
|
|
528
|
-
newLineCount: newCountR,
|
|
529
|
-
lines: newBody,
|
|
530
|
-
additions: newBody.filter((l) => l.startsWith("+")),
|
|
531
|
-
subtractions: newBody.filter((l) => l.startsWith("-")),
|
|
532
|
-
contextLines: newBody.filter((l) => l.startsWith(" ")),
|
|
533
|
-
};
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
// Group hunk lines into change-blocks separated by context
|
|
539
|
-
// Each block: { deletions, additions }
|
|
540
|
-
type ChangeBlock = { deletions: string[]; additions: string[]; };
|
|
541
|
-
const blocks: ChangeBlock[] = [];
|
|
542
|
-
let curBlock: ChangeBlock = { deletions: [], additions: [] };
|
|
543
|
-
let inBlock = false;
|
|
544
|
-
for (const line of hunk.lines) {
|
|
545
|
-
if (line.startsWith("-")) { curBlock.deletions.push(line.slice(1)); inBlock = true; }
|
|
546
|
-
else if (line.startsWith("+")) { curBlock.additions.push(line.slice(1)); inBlock = true; }
|
|
547
|
-
else if (inBlock) {
|
|
548
|
-
blocks.push(curBlock);
|
|
549
|
-
curBlock = { deletions: [], additions: [] };
|
|
550
|
-
inBlock = false;
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
if (inBlock || curBlock.deletions.length > 0 || curBlock.additions.length > 0) blocks.push(curBlock);
|
|
554
|
-
|
|
555
|
-
// For each block, try to apply as line-level or substring replacement
|
|
556
|
-
let resultLines = [...originalLines];
|
|
557
|
-
let lineOffset = 0;
|
|
558
|
-
let anyApplied = false;
|
|
559
|
-
for (const block of blocks) {
|
|
560
|
-
if (block.deletions.length === 0) continue;
|
|
561
|
-
// Try exact line match first
|
|
562
|
-
const seqIdx = findSequenceIndex(resultLines, block.deletions);
|
|
563
|
-
if (seqIdx !== -1) {
|
|
564
|
-
resultLines = [
|
|
565
|
-
...resultLines.slice(0, seqIdx),
|
|
566
|
-
...block.additions,
|
|
567
|
-
...resultLines.slice(seqIdx + block.deletions.length),
|
|
568
|
-
];
|
|
569
|
-
lineOffset += block.additions.length - block.deletions.length;
|
|
570
|
-
anyApplied = true;
|
|
571
|
-
continue;
|
|
572
|
-
}
|
|
573
|
-
// Try substring replacement: find a line containing all deletion content
|
|
574
|
-
const delContent = block.deletions.join(" ").trim();
|
|
575
|
-
const addContent = block.additions.join(" ").trim();
|
|
576
|
-
const matchIdx = resultLines.findIndex((l) => l.includes(delContent.split(" ")[0]) && block.deletions.every((d) => l.includes(d.trim())));
|
|
577
|
-
if (matchIdx !== -1) {
|
|
578
|
-
let newLine = resultLines[matchIdx];
|
|
579
|
-
for (let i = 0; i < block.deletions.length; i++) {
|
|
580
|
-
newLine = newLine.replace(block.deletions[i].trim(), block.additions[i]?.trim() ?? "");
|
|
581
|
-
}
|
|
582
|
-
resultLines = [...resultLines.slice(0, matchIdx), newLine, ...resultLines.slice(matchIdx + 1)];
|
|
583
|
-
anyApplied = true;
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
if (anyApplied) {
|
|
588
|
-
// Build a replacement patch from original -> result
|
|
589
|
-
const origStr = originalLines.join("\n");
|
|
590
|
-
const newStr = resultLines.join("\n");
|
|
591
|
-
// Find first differing line
|
|
592
|
-
let firstDiff = 0;
|
|
593
|
-
while (firstDiff < originalLines.length && firstDiff < resultLines.length && originalLines[firstDiff] === resultLines[firstDiff]) firstDiff++;
|
|
594
|
-
let lastDiffOrig = originalLines.length - 1;
|
|
595
|
-
let lastDiffNew = resultLines.length - 1;
|
|
596
|
-
while (lastDiffOrig > firstDiff && lastDiffNew > firstDiff && originalLines[lastDiffOrig] === resultLines[lastDiffNew]) { lastDiffOrig--; lastDiffNew--; }
|
|
597
|
-
const ctxStart = Math.max(0, firstDiff - 1);
|
|
598
|
-
const ctxEndOrig = Math.min(originalLines.length - 1, lastDiffOrig + 1);
|
|
599
|
-
const ctxEndNew = Math.min(resultLines.length - 1, lastDiffNew + 1);
|
|
600
|
-
const patchLines: string[] = [];
|
|
601
|
-
for (let i = ctxStart; i <= ctxEndOrig; i++) {
|
|
602
|
-
if (i >= firstDiff && i <= lastDiffOrig) patchLines.push(`-${originalLines[i]}`);
|
|
603
|
-
else patchLines.push(` ${originalLines[i]}`);
|
|
604
|
-
}
|
|
605
|
-
// Insert additions at right position
|
|
606
|
-
const finalLines: string[] = [];
|
|
607
|
-
for (let i = ctxStart; i <= ctxEndOrig; i++) {
|
|
608
|
-
if (i >= firstDiff && i <= lastDiffOrig) { finalLines.push(`-${originalLines[i]}`); }
|
|
609
|
-
else finalLines.push(` ${originalLines[i]}`);
|
|
610
|
-
}
|
|
611
|
-
// Add additions after last deletion
|
|
612
|
-
for (let i = firstDiff; i <= lastDiffNew; i++) {
|
|
613
|
-
if (i >= firstDiff && i <= lastDiffNew && (i > lastDiffOrig || originalLines[i] !== resultLines[i])) {
|
|
614
|
-
if (!finalLines.some((l) => l === `+${resultLines[i]}`)) finalLines.push(`+${resultLines[i]}`);
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
const origCount2 = finalLines.filter((l) => !l.startsWith("+")).length;
|
|
618
|
-
const newCount2 = finalLines.filter((l) => !l.startsWith("-")).length;
|
|
619
|
-
const newHeader2 = `@@ -${ctxStart + 1},${origCount2} +${ctxStart + 1},${newCount2} @@`;
|
|
620
|
-
return {
|
|
621
|
-
header: newHeader2,
|
|
622
|
-
originalStartLine: ctxStart + 1,
|
|
623
|
-
originalLineCount: origCount2,
|
|
624
|
-
newStartLine: ctxStart + 1,
|
|
625
|
-
newLineCount: newCount2,
|
|
626
|
-
lines: finalLines,
|
|
627
|
-
additions: finalLines.filter((l) => l.startsWith("+")),
|
|
628
|
-
subtractions: finalLines.filter((l) => l.startsWith("-")),
|
|
629
|
-
contextLines: finalLines.filter((l) => l.startsWith(" ")),
|
|
630
|
-
};
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
// Fallback: filter valid lines and return
|
|
634
|
-
const validLines = hunk.lines.filter((l) => {
|
|
635
|
-
if (l.startsWith("+") || l.startsWith("-")) return true;
|
|
636
|
-
if (!l.startsWith(" ") && l.trim() !== "") return false;
|
|
637
|
-
const content = l.startsWith(" ") ? l.slice(1) : l;
|
|
638
|
-
if (content.trim() === "") return originalLines.includes(content);
|
|
639
|
-
return originalLines.some((fl) => fl.trim() === content.trim());
|
|
640
|
-
}).map((l) => (!l.startsWith("+") && !l.startsWith("-") && !l.startsWith(" ")) ? ` ${l}` : l);
|
|
641
|
-
const origCount = validLines.filter((l) => !l.startsWith("+")).length;
|
|
642
|
-
const newCount = validLines.filter((l) => !l.startsWith("-")).length;
|
|
643
|
-
const newHeader = `@@ -${actualOriginalStartLine},${origCount} +${actualOriginalStartLine},${newCount} @@`;
|
|
644
|
-
return {
|
|
645
|
-
header: newHeader,
|
|
646
|
-
originalStartLine: actualOriginalStartLine,
|
|
647
|
-
originalLineCount: origCount,
|
|
648
|
-
newStartLine: actualOriginalStartLine,
|
|
649
|
-
newLineCount: newCount,
|
|
650
|
-
lines: validLines,
|
|
651
|
-
additions: hunk.additions,
|
|
652
|
-
subtractions: hunk.subtractions,
|
|
653
|
-
contextLines: validLines.filter((l) => !l.startsWith("+") && !l.startsWith("-")),
|
|
654
|
-
};
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
// Pure insertion: wrap the additions in real surrounding context from the file so the
|
|
658
|
-
// insertion position is unambiguous. A context-less `@@ -N,0 +N,M @@` hunk is applied
|
|
659
|
-
// inconsistently by the diff library (it can land the additions AFTER the anchor line
|
|
660
|
-
// instead of BEFORE it), which corrupts scopes (e.g. injecting a new function inside an
|
|
661
|
-
// existing function body). `actualOriginalStartLine` is the 1-based line that the new
|
|
662
|
-
// lines should be inserted *before*.
|
|
663
|
-
if (deletionLinesContent.length === 0 && additionLinesContent.length > 0) {
|
|
664
|
-
// Insertion index (0-based) within originalLines where additions are placed.
|
|
665
|
-
const insertIdx = actualOriginalStartLine - 1;
|
|
666
|
-
|
|
667
|
-
// Take up to CONTEXT_LINES real lines before and after the insertion point.
|
|
668
|
-
const beforeStart = Math.max(0, insertIdx - CONTEXT_LINES);
|
|
669
|
-
const contextBeforeLines: string[] = [];
|
|
670
|
-
for (let i = beforeStart; i < insertIdx && i < originalLines.length; i++) {
|
|
671
|
-
contextBeforeLines.push(` ${originalLines[i]}`);
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
const contextAfterLines: string[] = [];
|
|
675
|
-
for (
|
|
676
|
-
let i = insertIdx;
|
|
677
|
-
i < insertIdx + CONTEXT_LINES && i < originalLines.length;
|
|
678
|
-
i++
|
|
679
|
-
) {
|
|
680
|
-
contextAfterLines.push(` ${originalLines[i]}`);
|
|
681
|
-
}
|
|
682
|
-
|
|
683
|
-
const pureLines = [
|
|
684
|
-
...contextBeforeLines,
|
|
685
|
-
...hunk.additions,
|
|
686
|
-
...contextAfterLines,
|
|
687
|
-
];
|
|
688
|
-
|
|
689
|
-
const pureOrigStart = insertIdx - contextBeforeLines.length + 1; // 1-based
|
|
690
|
-
const pureOrigCount = contextBeforeLines.length + contextAfterLines.length;
|
|
691
|
-
const pureNewCount =
|
|
692
|
-
contextBeforeLines.length +
|
|
693
|
-
hunk.additions.length +
|
|
694
|
-
contextAfterLines.length;
|
|
695
|
-
|
|
696
|
-
const pureHeader = `@@ -${pureOrigStart},${pureOrigCount} +${pureOrigStart},${pureNewCount} @@`;
|
|
697
|
-
return {
|
|
698
|
-
header: pureHeader,
|
|
699
|
-
originalStartLine: pureOrigStart,
|
|
700
|
-
originalLineCount: pureOrigCount,
|
|
701
|
-
newStartLine: pureOrigStart,
|
|
702
|
-
newLineCount: pureNewCount,
|
|
703
|
-
lines: pureLines,
|
|
704
|
-
additions: hunk.additions,
|
|
705
|
-
subtractions: [],
|
|
706
|
-
contextLines: [...contextBeforeLines, ...contextAfterLines],
|
|
707
|
-
};
|
|
708
|
-
}
|
|
709
|
-
|
|
710
|
-
// 4. Extract context lines from the original hunk body
|
|
711
|
-
const hunkContextBefore: string[] = [];
|
|
712
|
-
const hunkContextAfter: string[] = [];
|
|
713
|
-
let pastChanges = false;
|
|
714
|
-
for (const line of hunk.lines) {
|
|
715
|
-
if (line.startsWith("+") || line.startsWith("-")) {
|
|
716
|
-
pastChanges = true;
|
|
717
|
-
} else if (line.startsWith(" ")) {
|
|
718
|
-
if (!pastChanges) hunkContextBefore.push(line);
|
|
719
|
-
else hunkContextAfter.push(line);
|
|
720
|
-
}
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
// Validate context lines against the file (reject ghost lines not present in file)
|
|
724
|
-
// Replace context lines with the actual line from the file to fix indentation divergence
|
|
725
|
-
const validContextBefore = hunkContextBefore
|
|
726
|
-
.map((l) => {
|
|
727
|
-
const match = originalLines.find((fl) => fl.trim() === l.slice(1).trim() && l.slice(1).trim() !== "");
|
|
728
|
-
return match !== undefined ? ` ${match}` : null;
|
|
729
|
-
})
|
|
730
|
-
.filter((l): l is string => l !== null);
|
|
731
|
-
const validContextAfter = hunkContextAfter
|
|
732
|
-
.map((l) => {
|
|
733
|
-
const match = originalLines.find((fl) => fl.trim() === l.slice(1).trim() && l.slice(1).trim() !== "");
|
|
734
|
-
return match !== undefined ? ` ${match}` : null;
|
|
735
|
-
})
|
|
736
|
-
.filter((l): l is string => l !== null);
|
|
737
|
-
|
|
738
|
-
// For deletion-anchored hunks, derive the leading context directly from the file just
|
|
739
|
-
// above the deletion start. This is far more reliable than mapping the hunk's context
|
|
740
|
-
// lines via `.find()` (which returns the FIRST match and mis-aligns when lines like a
|
|
741
|
-
// blank or a closing `}` repeat earlier in the file, producing duplicated context).
|
|
742
|
-
const fileContextBefore: string[] = [];
|
|
743
|
-
if (deletionLinesContent.length > 0) {
|
|
744
|
-
// Match the amount of leading context the original hunk carried (plus one extra
|
|
745
|
-
// anchor line, as the legacy implementation did), capped at CONTEXT_LINES. This keeps
|
|
746
|
-
// the header line counts stable while still deriving the *content* from the correct
|
|
747
|
-
// file position (avoiding the `.find()` duplication bug).
|
|
748
|
-
const desiredBeforeCount = Math.min(
|
|
749
|
-
CONTEXT_LINES,
|
|
750
|
-
validContextBefore.length + 1
|
|
751
|
-
);
|
|
752
|
-
const ctxStartIdx = Math.max(0, actualOriginalStartLine - 1 - desiredBeforeCount); // 0-based
|
|
753
|
-
for (let i = ctxStartIdx; i < actualOriginalStartLine - 1; i++) {
|
|
754
|
-
fileContextBefore.push(` ${originalLines[i]}`);
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
const contextBefore =
|
|
758
|
-
deletionLinesContent.length > 0 ? fileContextBefore : validContextBefore;
|
|
759
|
-
|
|
760
|
-
// For context after: use valid context from hunk; if none, take 1 line from file
|
|
761
|
-
const originalContentEndLine = actualOriginalStartLine + deletionLinesContent.length;
|
|
762
|
-
let contextAfter: string[];
|
|
763
|
-
if (deletionLinesContent.length === 0) {
|
|
764
|
-
// Pure insertion: always take the line at the insertion point from file (don't trust hunk context position)
|
|
765
|
-
const afterIdx = actualOriginalStartLine - 1; // 0-based index of line at insertion point
|
|
766
|
-
contextAfter = afterIdx < originalLines.length ? [` ${originalLines[afterIdx]}`] : [];
|
|
767
|
-
} else {
|
|
768
|
-
// Derive trailing context directly from the file just below the deleted block, for the
|
|
769
|
-
// same reliability reasons as the leading context above. Match the amount of trailing
|
|
770
|
-
// context the original hunk carried (at least one line), capped at CONTEXT_LINES, so the
|
|
771
|
-
// header line counts stay stable.
|
|
772
|
-
contextAfter = [];
|
|
773
|
-
const desiredAfterCount = Math.max(
|
|
774
|
-
1,
|
|
775
|
-
Math.min(CONTEXT_LINES, validContextAfter.length)
|
|
776
|
-
);
|
|
777
|
-
const afterStartIdx = originalContentEndLine - 1; // 0-based index after deletions
|
|
778
|
-
for (
|
|
779
|
-
let i = afterStartIdx;
|
|
780
|
-
i < afterStartIdx + desiredAfterCount && i < originalLines.length;
|
|
781
|
-
i++
|
|
782
|
-
) {
|
|
783
|
-
contextAfter.push(` ${originalLines[i]}`);
|
|
784
|
-
}
|
|
785
|
-
}
|
|
786
|
-
|
|
787
|
-
// For pure-insertion hunks (no deletions), don't supplement before - keep only hunk context
|
|
788
|
-
const finalContextBefore = deletionLinesContent.length === 0 ? validContextBefore : contextBefore;
|
|
789
|
-
|
|
790
|
-
const newHunkLines = [
|
|
791
|
-
...finalContextBefore,
|
|
792
|
-
...hunk.subtractions, // Use the original subtraction lines from the input hunk
|
|
793
|
-
...hunk.additions, // Use the original addition lines from the input hunk
|
|
794
|
-
...contextAfter,
|
|
795
|
-
];
|
|
796
|
-
|
|
797
|
-
// 5. Recalculate the header
|
|
798
|
-
const newOriginalStart =
|
|
799
|
-
finalContextBefore.length > 0
|
|
800
|
-
? actualOriginalStartLine - finalContextBefore.length
|
|
801
|
-
: actualOriginalStartLine;
|
|
802
|
-
const newOriginalCount =
|
|
803
|
-
finalContextBefore.length + hunk.subtractions.length + contextAfter.length;
|
|
804
|
-
|
|
805
|
-
// The new start line depends on how many lines were added/removed *before* this hunk.
|
|
806
|
-
// For an isolated hunk fix, we often just base it on the original start.
|
|
807
|
-
// A more robust diff tool might recalculate this based on cumulative changes.
|
|
808
|
-
// Let's keep it simple and relative to the original start for now.
|
|
809
|
-
const newNewStart = newOriginalStart; // Simplification: Assume start line number matches original unless offset by prior hunks (which we don't know here)
|
|
810
|
-
const newNewCount =
|
|
811
|
-
finalContextBefore.length + hunk.additions.length + contextAfter.length;
|
|
812
|
-
|
|
813
|
-
// Handle edge case where count is 0 (e.g., adding to an empty file) - header format needs >= 1
|
|
814
|
-
const finalOriginalStart = Math.max(1, newOriginalStart);
|
|
815
|
-
const finalOriginalCount = Math.max(1, newOriginalCount); // Should be at least 1 if start is specified, unless file was empty
|
|
816
|
-
const finalNewStart = Math.max(1, newNewStart);
|
|
817
|
-
const finalNewCount = Math.max(1, newNewCount); // Should be at least 1 if start is specified
|
|
818
|
-
|
|
819
|
-
// Adjust count for empty file scenario
|
|
820
|
-
const displayOriginalCount =
|
|
821
|
-
originalLines.length === 0 && newOriginalCount === 0
|
|
822
|
-
? 0
|
|
823
|
-
: finalOriginalCount;
|
|
824
|
-
const displayNewCount =
|
|
825
|
-
originalLines.length === 0 && newNewCount === 0 ? 0 : finalNewCount; // Handle adding to empty file
|
|
826
|
-
|
|
827
|
-
const newHeader = `@@ -${finalOriginalStart},${displayOriginalCount} +${finalNewStart},${displayNewCount} @@`;
|
|
828
|
-
|
|
829
|
-
const fixedHunk: Hunk = {
|
|
830
|
-
header: newHeader,
|
|
831
|
-
originalStartLine: finalOriginalStart,
|
|
832
|
-
originalLineCount: displayOriginalCount,
|
|
833
|
-
newStartLine: finalNewStart,
|
|
834
|
-
newLineCount: displayNewCount,
|
|
835
|
-
lines: newHunkLines,
|
|
836
|
-
additions: hunk.additions, // Keep original intended changes
|
|
837
|
-
subtractions: hunk.subtractions, // Keep original intended changes
|
|
838
|
-
contextLines: [...finalContextBefore, ...contextAfter], // Store the newly generated context
|
|
839
|
-
};
|
|
840
|
-
|
|
841
|
-
// 6. Filter out empty hunks
|
|
842
|
-
if (hunkIsEmpty(fixedHunk)) {
|
|
843
|
-
console.log("Hunk became empty after fixing:", fixedHunk.header);
|
|
844
|
-
return null;
|
|
845
|
-
}
|
|
846
|
-
|
|
847
|
-
return fixedHunk;
|
|
848
|
-
}
|
|
849
|
-
|
|
850
|
-
/**
|
|
851
|
-
* Takes a potentially corrupted patch and attempts to fix its hunks
|
|
852
|
-
* by aligning them with the original content.
|
|
853
|
-
*/
|
|
854
|
-
export function fixPatch(originalContent: string, patch: string): string {
|
|
855
|
-
const originalHunks = parseHunks(patch);
|
|
856
|
-
const fixedHunks: Hunk[] = [];
|
|
857
|
-
|
|
858
|
-
console.log(`Attempting to fix ${originalHunks.length} hunks...`);
|
|
859
|
-
|
|
860
|
-
for (const hunk of originalHunks) {
|
|
861
|
-
console.log(`\nProcessing Hunk: ${hunk.header}`);
|
|
862
|
-
try {
|
|
863
|
-
const fixed = fixSingleHunk(hunk, originalContent);
|
|
864
|
-
if (fixed) {
|
|
865
|
-
console.log(`Successfully fixed. New header: ${fixed.header}`);
|
|
866
|
-
fixedHunks.push(fixed);
|
|
867
|
-
} else {
|
|
868
|
-
console.warn(`Could not fix hunk, discarding: ${hunk.header}`);
|
|
869
|
-
}
|
|
870
|
-
} catch (error) {
|
|
871
|
-
console.error(`Error fixing hunk ${hunk.header}:`, error);
|
|
872
|
-
// Optionally decide whether to keep the original hunk or discard
|
|
873
|
-
}
|
|
874
|
-
}
|
|
875
|
-
|
|
876
|
-
// Check if the result ends with a newline like the original content
|
|
877
|
-
const needsNoNewlineSuffix =
|
|
878
|
-
!originalContent.endsWith("\n") && fixedHunks.length > 0;
|
|
879
|
-
let finalPatch = hunksToPatch(fixedHunks);
|
|
880
|
-
|
|
881
|
-
// The hunkToPatch function might handle the \ No newline ... line based on content,
|
|
882
|
-
// but we might need to ensure it's added if the *intended* final state doesn't have a newline.
|
|
883
|
-
// This is tricky. Let's rely on applyPatch to handle it correctly if the content matches.
|
|
884
|
-
// Re-apply the check: Does the *last* fixed hunk *imply* no newline?
|
|
885
|
-
if (fixedHunks.length > 0) {
|
|
886
|
-
const lastHunk = fixedHunks[fixedHunks.length - 1];
|
|
887
|
-
const lastLine = lastHunk.lines[lastHunk.lines.length - 1];
|
|
888
|
-
// If the original patch had the indicator, try to preserve it if relevant
|
|
889
|
-
if (
|
|
890
|
-
patch.includes("\") &&
|
|
891
|
-
!lastLine?.endsWith("\n") &&
|
|
892
|
-
!finalPatch.endsWith("\")
|
|
893
|
-
) {
|
|
894
|
-
// This logic is imperfect. Let's assume for now hunkToPatch handles it ok.
|
|
895
|
-
}
|
|
896
|
-
}
|
|
897
|
-
|
|
898
|
-
// Add trailing newline if the original patch had one and the fixed one doesn't
|
|
899
|
-
if (
|
|
900
|
-
patch.endsWith("\n") &&
|
|
901
|
-
!finalPatch.endsWith("\n") &&
|
|
902
|
-
finalPatch.length > 0
|
|
903
|
-
) {
|
|
904
|
-
finalPatch += "\n";
|
|
905
|
-
}
|
|
906
|
-
|
|
907
|
-
return finalPatch;
|
|
908
|
-
}
|
|
909
|
-
|
|
910
|
-
/**
|
|
911
|
-
* Verify that auto-correction did not broaden or change the requested edit.
|
|
912
|
-
* Line locations and hunk headers may change, but the exact multiset of added
|
|
913
|
-
* and removed lines must remain the same.
|
|
914
|
-
*/
|
|
915
|
-
export function autoCorrectionPreservesChanges(
|
|
916
|
-
originalContent: string,
|
|
917
|
-
updatedContent: string,
|
|
918
|
-
requestedPatch: string
|
|
919
|
-
): boolean {
|
|
920
|
-
const changedLines = (patch: string, prefix: "+" | "-"): string[] =>
|
|
921
|
-
parseHunks(patch)
|
|
922
|
-
.flatMap((hunk) =>
|
|
923
|
-
hunk.lines
|
|
924
|
-
.filter((line) => line.startsWith(prefix))
|
|
925
|
-
.map((line) => line.slice(1))
|
|
926
|
-
)
|
|
927
|
-
.sort();
|
|
928
|
-
|
|
929
|
-
const actualPatch = createTwoFilesPatch(
|
|
930
|
-
"original",
|
|
931
|
-
"updated",
|
|
932
|
-
originalContent,
|
|
933
|
-
updatedContent,
|
|
934
|
-
"",
|
|
935
|
-
"",
|
|
936
|
-
{ context: 0 }
|
|
937
|
-
);
|
|
938
|
-
|
|
939
|
-
const requestedAdditions = changedLines(requestedPatch, "+");
|
|
940
|
-
const requestedRemovals = changedLines(requestedPatch, "-");
|
|
941
|
-
const actualAdditions = changedLines(actualPatch, "+");
|
|
942
|
-
const actualRemovals = changedLines(actualPatch, "-");
|
|
943
|
-
|
|
944
|
-
return (
|
|
945
|
-
JSON.stringify(actualAdditions) === JSON.stringify(requestedAdditions) &&
|
|
946
|
-
JSON.stringify(actualRemovals) === JSON.stringify(requestedRemovals)
|
|
947
|
-
);
|
|
948
|
-
}
|
|
949
|
-
|
|
950
|
-
// --- Existing Application/Utility Code (Keep as is, ensure imports/exports are correct) ---
|
|
951
|
-
|
|
952
|
-
export async function savePatchError(
|
|
953
|
-
originalPatch: string,
|
|
954
|
-
fixedPatch: string | null, // Can be null if fixing failed
|
|
955
|
-
fileContent: string,
|
|
956
|
-
errorMsg: string // Add error message for context
|
|
957
|
-
) {
|
|
958
|
-
const dirName = ".knowhow/tools/patchFile"; // Use path.join ideally
|
|
959
|
-
const fileName = "errors.json";
|
|
960
|
-
const filePath = `${dirName}/${fileName}`; // Use path.join ideally
|
|
961
|
-
try {
|
|
962
|
-
if (!(await fileExists(filePath))) {
|
|
963
|
-
await mkdir(dirName, { recursive: true });
|
|
964
|
-
await writeFile(filePath, "[]");
|
|
965
|
-
}
|
|
966
|
-
let errors = [];
|
|
967
|
-
try {
|
|
968
|
-
errors = JSON.parse(await readFile(filePath, "utf8"));
|
|
969
|
-
if (!Array.isArray(errors)) errors = []; // Ensure it's an array
|
|
970
|
-
} catch (readError) {
|
|
971
|
-
console.error(
|
|
972
|
-
"Error reading patch error log, starting fresh.",
|
|
973
|
-
readError
|
|
974
|
-
);
|
|
975
|
-
errors = [];
|
|
976
|
-
}
|
|
977
|
-
errors.push({
|
|
978
|
-
timestamp: new Date().toISOString(),
|
|
979
|
-
error: errorMsg,
|
|
980
|
-
originalPatch,
|
|
981
|
-
fixedPatch, // May be null or the attempted fix
|
|
982
|
-
fileContent,
|
|
983
|
-
});
|
|
984
|
-
// Limit log size maybe?
|
|
985
|
-
// errors = errors.slice(-50);
|
|
986
|
-
await writeFile(filePath, JSON.stringify(errors, null, 2));
|
|
987
|
-
} catch (logError) {
|
|
988
|
-
console.error("Failed to save patch error information:", logError);
|
|
989
|
-
}
|
|
990
|
-
}
|
|
991
|
-
|
|
992
|
-
// Tool to apply a patch file to a file
|
|
993
|
-
export async function patchFile(
|
|
994
|
-
filePath: string,
|
|
995
|
-
patch: string
|
|
996
|
-
): Promise<string> {
|
|
997
|
-
// Get context from bound ToolsService
|
|
998
|
-
const toolService = (
|
|
999
|
-
this instanceof ToolsService ? this : services().Tools
|
|
1000
|
-
) as ToolsService;
|
|
1001
|
-
|
|
1002
|
-
const context = toolService.getContext();
|
|
1003
|
-
|
|
1004
|
-
let originalContent = "";
|
|
1005
|
-
try {
|
|
1006
|
-
if (!fs.existsSync(filePath)) {
|
|
1007
|
-
// If file doesn't exist, the patch should ideally be creating it.
|
|
1008
|
-
// The patch should start with --- /dev/null
|
|
1009
|
-
console.log(
|
|
1010
|
-
`File ${filePath} does not exist. Attempting to apply patch as creation.`
|
|
1011
|
-
);
|
|
1012
|
-
originalContent = "";
|
|
1013
|
-
// Ensure fs operations use async/await if utils are async
|
|
1014
|
-
// fs.writeFileSync(filePath, ""); // Don't create it yet, let applyPatch handle it from /dev/null
|
|
1015
|
-
} else {
|
|
1016
|
-
originalContent = await readFile(filePath, "utf8"); // Use async read
|
|
1017
|
-
}
|
|
1018
|
-
|
|
1019
|
-
const patchHunks = parseHunks(patch);
|
|
1020
|
-
// `diff.applyPatch` can report success for malformed hunks whose declared
|
|
1021
|
-
// line counts disagree with their bodies. In that case it consumes the
|
|
1022
|
-
// wrong number of lines and can move additions across scope boundaries.
|
|
1023
|
-
// Send those hunks through our re-anchoring logic instead of trusting the
|
|
1024
|
-
// library's successful-but-corrupt result.
|
|
1025
|
-
const hasInvalidHunkCounts = patchHunks.some((hunk) => {
|
|
1026
|
-
const originalBodyCount = hunk.lines.filter(
|
|
1027
|
-
(line) =>
|
|
1028
|
-
!line.startsWith("+") &&
|
|
1029
|
-
line !== "\"
|
|
1030
|
-
).length;
|
|
1031
|
-
const newBodyCount = hunk.lines.filter(
|
|
1032
|
-
(line) =>
|
|
1033
|
-
!line.startsWith("-") &&
|
|
1034
|
-
line !== "\"
|
|
1035
|
-
).length;
|
|
1036
|
-
return (
|
|
1037
|
-
originalBodyCount !== hunk.originalLineCount ||
|
|
1038
|
-
newBodyCount !== hunk.newLineCount
|
|
1039
|
-
);
|
|
1040
|
-
});
|
|
1041
|
-
let updatedContent = hasInvalidHunkCounts
|
|
1042
|
-
? false
|
|
1043
|
-
: applyPatch(originalContent, patch);
|
|
1044
|
-
let appliedPatch = patch; // Keep track of which patch succeeded
|
|
1045
|
-
const patchHasAdditions = patchHunks.some((h) => h.additions.length > 0);
|
|
1046
|
-
const patchHasDeletions = patchHunks.some((h) => h.subtractions.length > 0);
|
|
1047
|
-
|
|
1048
|
-
/**
|
|
1049
|
-
* Build a human-readable summary of what changed between two content strings.
|
|
1050
|
-
*/
|
|
1051
|
-
function buildChangeSummary(original: string, updated: string): string {
|
|
1052
|
-
const origLines = original === "" ? [] : original.split("\n");
|
|
1053
|
-
const updLines = updated === "" ? [] : updated.split("\n");
|
|
1054
|
-
const netChange = updLines.length - origLines.length;
|
|
1055
|
-
|
|
1056
|
-
// Find lines unique to each side (approximate diff)
|
|
1057
|
-
const origSet = new Set(origLines);
|
|
1058
|
-
const updSet = new Set(updLines);
|
|
1059
|
-
const addedLines = updLines.filter((l) => !origSet.has(l));
|
|
1060
|
-
const removedLines = origLines.filter((l) => !updSet.has(l));
|
|
1061
|
-
|
|
1062
|
-
const linesAdded = netChange > 0 ? netChange : addedLines.length;
|
|
1063
|
-
const linesRemoved = netChange < 0 ? -netChange : removedLines.length;
|
|
1064
|
-
|
|
1065
|
-
const parts: string[] = [];
|
|
1066
|
-
parts.push(`+${linesAdded} lines, -${linesRemoved} lines (net: ${netChange > 0 ? "+" : ""}${netChange})`);
|
|
1067
|
-
|
|
1068
|
-
// Preview: show first 3 added lines
|
|
1069
|
-
const previewAdded = addedLines.slice(0, 3);
|
|
1070
|
-
if (previewAdded.length > 0) {
|
|
1071
|
-
parts.push("Preview of additions:\n" + previewAdded.map((l) => ` + ${l.trim().slice(0, 100)}`).join("\n"));
|
|
1072
|
-
}
|
|
1073
|
-
const previewRemoved = removedLines.slice(0, 3);
|
|
1074
|
-
if (previewRemoved.length > 0) {
|
|
1075
|
-
parts.push("Preview of removals:\n" + previewRemoved.map((l) => ` - ${l.trim().slice(0, 100)}`).join("\n"));
|
|
1076
|
-
}
|
|
1077
|
-
return parts.join("\n");
|
|
1078
|
-
}
|
|
1079
|
-
|
|
1080
|
-
// Detect silent no-op: patch "succeeded" but content unchanged despite having additions/deletions
|
|
1081
|
-
let wasNoOp = false;
|
|
1082
|
-
if (
|
|
1083
|
-
updatedContent !== false &&
|
|
1084
|
-
updatedContent === originalContent &&
|
|
1085
|
-
(patchHasAdditions || patchHasDeletions)
|
|
1086
|
-
) {
|
|
1087
|
-
console.warn(
|
|
1088
|
-
"Patch applied but resulted in NO CHANGES despite having additions/deletions. Treating as failure and attempting fix..."
|
|
1089
|
-
);
|
|
1090
|
-
wasNoOp = true;
|
|
1091
|
-
updatedContent = false; // Force fix path
|
|
1092
|
-
}
|
|
1093
|
-
|
|
1094
|
-
// If the patch doesn't apply (or was a silent no-op), try to fix it
|
|
1095
|
-
if (updatedContent === false) {
|
|
1096
|
-
// diff library often returns false on failure
|
|
1097
|
-
console.warn("Initial patch apply failed. Attempting to fix patch...");
|
|
1098
|
-
let fixedPatch: string | null = null; // Initialize as null
|
|
1099
|
-
try {
|
|
1100
|
-
fixedPatch = fixPatch(originalContent, patch);
|
|
1101
|
-
console.log("--- Attempted Fixed Patch ---");
|
|
1102
|
-
console.log(fixedPatch || "<Fixing resulted in empty patch>");
|
|
1103
|
-
console.log("---------------------------");
|
|
1104
|
-
} catch (fixError: any) {
|
|
1105
|
-
console.error("Error during fixPatch execution:", fixError);
|
|
1106
|
-
await savePatchError(
|
|
1107
|
-
patch,
|
|
1108
|
-
null,
|
|
1109
|
-
originalContent,
|
|
1110
|
-
`fixPatch function errored: ${fixError.message}`
|
|
1111
|
-
);
|
|
1112
|
-
return `An error occured while trying to fix the patch: ${fixError.message}`;
|
|
1113
|
-
}
|
|
1114
|
-
|
|
1115
|
-
if (!fixedPatch || fixedPatch.trim() === "") {
|
|
1116
|
-
// If fixing resulted in an empty patch, it means no valid changes could be salvaged.
|
|
1117
|
-
console.error(
|
|
1118
|
-
"Patch could not be fixed or resulted in an empty patch."
|
|
1119
|
-
);
|
|
1120
|
-
await savePatchError(
|
|
1121
|
-
patch,
|
|
1122
|
-
fixedPatch,
|
|
1123
|
-
originalContent,
|
|
1124
|
-
"Patch fix resulted in empty or null patch."
|
|
1125
|
-
);
|
|
1126
|
-
// It might be valid that the patch had no real changes, but applyPatch failed anyway?
|
|
1127
|
-
// Let's return an error indicating failure.
|
|
1128
|
-
const hunkSummary = patchHunks.map((h, i) =>
|
|
1129
|
-
` Hunk ${i + 1}: ${h.header} — ${h.additions.length} additions, ${h.subtractions.length} deletions`
|
|
1130
|
-
).join("\n");
|
|
1131
|
-
return [
|
|
1132
|
-
`❌ Patch failed: could not apply or fix the patch (${patchHunks.length} hunk(s) attempted, 0 applied).`,
|
|
1133
|
-
wasNoOp ? `⚠️ Note: The patch initially appeared to succeed but produced NO CHANGES (silent no-op). This often means context lines matched a different location than intended.` : null,
|
|
1134
|
-
`File: ${filePath} (${originalContent.split("\n").length} lines)`,
|
|
1135
|
-
`Hunks attempted:\n${hunkSummary}`,
|
|
1136
|
-
`Tip: Break your patch into smaller hunks. Ensure context lines exactly match the file. Use readFile to verify the current content before patching.`,
|
|
1137
|
-
].filter(Boolean).join("\n");
|
|
1138
|
-
}
|
|
1139
|
-
|
|
1140
|
-
updatedContent = applyPatch(originalContent, fixedPatch);
|
|
1141
|
-
appliedPatch = fixedPatch; // Use the fixed patch now
|
|
1142
|
-
|
|
1143
|
-
// Sometimes patches need a trailing newline
|
|
1144
|
-
if (updatedContent === false && !fixedPatch.endsWith("\n")) {
|
|
1145
|
-
console.log(
|
|
1146
|
-
"Applying fixed patch failed, trying with added newline..."
|
|
1147
|
-
);
|
|
1148
|
-
fixedPatch += "\n";
|
|
1149
|
-
updatedContent = applyPatch(originalContent, fixedPatch);
|
|
1150
|
-
appliedPatch = fixedPatch;
|
|
1151
|
-
}
|
|
1152
|
-
|
|
1153
|
-
if (updatedContent === false) {
|
|
1154
|
-
console.error("Applying the *fixed* patch also failed.");
|
|
1155
|
-
await savePatchError(
|
|
1156
|
-
patch,
|
|
1157
|
-
fixedPatch,
|
|
1158
|
-
originalContent,
|
|
1159
|
-
"Fixed patch also failed to apply."
|
|
1160
|
-
);
|
|
1161
|
-
// Try to provide more specific feedback from applyPatch if possible (library might not offer it)
|
|
1162
|
-
return [
|
|
1163
|
-
`❌ Patch failed: could not apply even after auto-correction (${patchHunks.length} hunk(s) attempted, 0 applied).`,
|
|
1164
|
-
wasNoOp ? `⚠️ Note: The patch initially appeared to succeed but produced NO CHANGES (silent no-op). Context lines may have matched the wrong location.` : null,
|
|
1165
|
-
`File: ${filePath} (${originalContent.split("\n").length} lines)`,
|
|
1166
|
-
`The auto-fix attempted to re-anchor your hunks to the file content but the resulting patch still failed.`,
|
|
1167
|
-
`Tip: Use readFile to get the current exact content, then rewrite your patch with precise context lines matching the file. Make smaller, more targeted hunks.`,
|
|
1168
|
-
].filter(Boolean).join("\n");
|
|
1169
|
-
} else {
|
|
1170
|
-
console.log("Successfully applied the *fixed* patch.");
|
|
1171
|
-
appliedPatch = fixedPatch;
|
|
1172
|
-
}
|
|
1173
|
-
} else {
|
|
1174
|
-
console.log("Successfully applied the original patch.");
|
|
1175
|
-
}
|
|
1176
|
-
|
|
1177
|
-
const wasFixed = appliedPatch !== patch;
|
|
1178
|
-
|
|
1179
|
-
// Auto-correction may re-anchor hunks, but it must never invent removals,
|
|
1180
|
-
// drop requested edits, or move lines by representing them as extra edits.
|
|
1181
|
-
// Reject before events or disk writes if its actual delta differs from the
|
|
1182
|
-
// submitted patch.
|
|
1183
|
-
if (
|
|
1184
|
-
wasFixed &&
|
|
1185
|
-
!autoCorrectionPreservesChanges(
|
|
1186
|
-
originalContent,
|
|
1187
|
-
updatedContent as string,
|
|
1188
|
-
patch
|
|
1189
|
-
)
|
|
1190
|
-
) {
|
|
1191
|
-
return [
|
|
1192
|
-
`❌ Patch failed: auto-correction changed the requested edit, so no changes were written.`,
|
|
1193
|
-
`File: ${filePath} (${originalContent.split("\n").length} lines)`,
|
|
1194
|
-
`Tip: Re-read the file and submit smaller hunks with unique surrounding context.`,
|
|
1195
|
-
].join("\n");
|
|
1196
|
-
}
|
|
1197
|
-
|
|
1198
|
-
const eventResults: any[] = [];
|
|
1199
|
-
// Emit pre-edit blocking event
|
|
1200
|
-
if (context.Events) {
|
|
1201
|
-
eventResults.push(
|
|
1202
|
-
...(await context.Events.emitBlocking("file:pre-edit", {
|
|
1203
|
-
filePath,
|
|
1204
|
-
operation: "patch",
|
|
1205
|
-
patch: appliedPatch,
|
|
1206
|
-
originalContent,
|
|
1207
|
-
updatedContent: updatedContent as string,
|
|
1208
|
-
}))
|
|
1209
|
-
);
|
|
1210
|
-
}
|
|
1211
|
-
|
|
1212
|
-
// Write the updated content
|
|
1213
|
-
await writeFile(filePath, updatedContent as string); // Type assertion needed as applyPatch might return boolean
|
|
1214
|
-
|
|
1215
|
-
// Emit post-edit blocking event to get event results
|
|
1216
|
-
if (context.Events) {
|
|
1217
|
-
eventResults.push(
|
|
1218
|
-
...(await context.Events.emitBlocking("file:post-edit", {
|
|
1219
|
-
filePath,
|
|
1220
|
-
operation: "patch",
|
|
1221
|
-
patch: appliedPatch,
|
|
1222
|
-
originalContent,
|
|
1223
|
-
updatedContent: updatedContent as string,
|
|
1224
|
-
}))
|
|
1225
|
-
);
|
|
1226
|
-
}
|
|
1227
|
-
|
|
1228
|
-
// Format event results
|
|
1229
|
-
let eventResultsText = "";
|
|
1230
|
-
if (eventResults && eventResults.length > 0) {
|
|
1231
|
-
if (eventResults.length > 0) {
|
|
1232
|
-
eventResultsText =
|
|
1233
|
-
"\n\nAdditional Information:\n" +
|
|
1234
|
-
JSON.stringify(eventResults, null, 2);
|
|
1235
|
-
}
|
|
1236
|
-
}
|
|
1237
|
-
|
|
1238
|
-
// Build rich summary of what actually changed
|
|
1239
|
-
const changeSummary = buildChangeSummary(originalContent, updatedContent as string);
|
|
1240
|
-
const appliedHunks = parseHunks(appliedPatch);
|
|
1241
|
-
const totalHunks = patchHunks.length;
|
|
1242
|
-
const appliedHunkCount = appliedHunks.length;
|
|
1243
|
-
const patchStatus = wasFixed
|
|
1244
|
-
? `⚠️ Original patch required auto-correction before applying.`
|
|
1245
|
-
: `✅ Original patch applied cleanly.`;
|
|
1246
|
-
const hunkStatus = appliedHunkCount < totalHunks
|
|
1247
|
-
? `⚠️ Only ${appliedHunkCount}/${totalHunks} hunks were applied.`
|
|
1248
|
-
: `${appliedHunkCount}/${totalHunks} hunks applied.`;
|
|
1249
|
-
|
|
1250
|
-
const summaryLines = [
|
|
1251
|
-
`Patch applied to ${filePath}.`,
|
|
1252
|
-
patchStatus,
|
|
1253
|
-
hunkStatus,
|
|
1254
|
-
changeSummary,
|
|
1255
|
-
];
|
|
1256
|
-
if (eventResultsText) summaryLines.push(eventResultsText);
|
|
1257
|
-
|
|
1258
|
-
return summaryLines.join("\n");
|
|
1259
|
-
} catch (e: any) {
|
|
1260
|
-
console.error(`Error in patchFile function for ${filePath}:`, e);
|
|
1261
|
-
// Save error only if it's not a controlled failure path that already saved
|
|
1262
|
-
if (!String(e.message).includes("Patch failed to apply")) {
|
|
1263
|
-
// Avoid double logging known failures
|
|
1264
|
-
await savePatchError(
|
|
1265
|
-
patch,
|
|
1266
|
-
null,
|
|
1267
|
-
originalContent,
|
|
1268
|
-
`Unexpected error in patchFile: ${e.message}`
|
|
1269
|
-
);
|
|
1270
|
-
}
|
|
1271
|
-
return `An error occured while applying the patch: ${e.message}`;
|
|
1272
|
-
}
|
|
1273
|
-
}
|
|
1274
|
-
|
|
1275
|
-
export function categorizeHunks(originalContent: string, patch: string) {
|
|
1276
|
-
const hunks = parseHunks(patch);
|
|
1277
|
-
|
|
1278
|
-
const validHunks = hunks.filter((hunk) =>
|
|
1279
|
-
applyPatch(originalContent, hunksToPatch([hunk]))
|
|
1280
|
-
);
|
|
1281
|
-
|
|
1282
|
-
const invalidHunks = hunks.filter(
|
|
1283
|
-
(hunk) => !applyPatch(originalContent, hunksToPatch([hunk]))
|
|
1284
|
-
);
|
|
1285
|
-
|
|
1286
|
-
return { validHunks, invalidHunks };
|
|
1287
|
-
}
|