repoburg 1.3.9 → 1.3.11
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/backend/dist/bin/grammar/tree-sitter-bash.wasm +0 -0
- package/backend/dist/bin/grammar/tree-sitter-css.wasm +0 -0
- package/backend/dist/bin/grammar/tree-sitter-html.wasm +0 -0
- package/backend/dist/bin/grammar/tree-sitter-javascript.wasm +0 -0
- package/backend/dist/bin/grammar/tree-sitter-json.wasm +0 -0
- package/backend/dist/bin/grammar/tree-sitter-python.wasm +0 -0
- package/backend/dist/bin/grammar/tree-sitter-rust.wasm +0 -0
- package/backend/dist/bin/grammar/tree-sitter-toml.wasm +0 -0
- package/backend/dist/bin/grammar/tree-sitter-tsx.wasm +0 -0
- package/backend/dist/bin/grammar/tree-sitter-typescript.wasm +0 -0
- package/backend/dist/bin/grammar/tree-sitter-yaml.wasm +0 -0
- package/backend/dist/packages/tokenpatch/index.d.ts +1 -0
- package/backend/dist/packages/tokenpatch/index.js +52 -0
- package/backend/dist/packages/tokenpatch/index.js.map +1 -0
- package/backend/dist/packages/tokenpatch/parser.d.ts +2 -0
- package/backend/dist/packages/tokenpatch/parser.js +17 -0
- package/backend/dist/packages/tokenpatch/parser.js.map +1 -0
- package/backend/dist/packages/tokenpatch/patcher.d.ts +11 -0
- package/backend/dist/packages/tokenpatch/patcher.js +189 -0
- package/backend/dist/packages/tokenpatch/patcher.js.map +1 -0
- package/backend/dist/packages/tokenpatch/tokens.d.ts +6 -0
- package/backend/dist/packages/tokenpatch/tokens.js +49 -0
- package/backend/dist/packages/tokenpatch/tokens.js.map +1 -0
- package/backend/dist/packages/tokenpatch/types.d.ts +8 -0
- package/backend/dist/packages/tokenpatch/types.js +3 -0
- package/backend/dist/packages/tokenpatch/types.js.map +1 -0
- package/backend/dist/src/ai-actions/ai-actions.service.d.ts +1 -0
- package/backend/dist/src/ai-actions/ai-actions.service.js +2 -0
- package/backend/dist/src/ai-actions/ai-actions.service.js.map +1 -1
- package/backend/dist/src/llm-orchestration/action-handlers/action-handler.interface.d.ts +1 -0
- package/backend/dist/src/llm-orchestration/action-handlers/apply-diff.handler.d.ts +1 -0
- package/backend/dist/src/llm-orchestration/action-handlers/apply-diff.handler.js +35 -0
- package/backend/dist/src/llm-orchestration/action-handlers/apply-diff.handler.js.map +1 -1
- package/backend/dist/src/llm-orchestration/action-handlers/create-file.handler.d.ts +1 -0
- package/backend/dist/src/llm-orchestration/action-handlers/create-file.handler.js +48 -0
- package/backend/dist/src/llm-orchestration/action-handlers/create-file.handler.js.map +1 -1
- package/backend/dist/src/llm-orchestration/action-handlers/delete-file.handler.d.ts +1 -0
- package/backend/dist/src/llm-orchestration/action-handlers/delete-file.handler.js +21 -0
- package/backend/dist/src/llm-orchestration/action-handlers/delete-file.handler.js.map +1 -1
- package/backend/dist/src/llm-orchestration/action-handlers/dto/howto.args.dto.d.ts +2 -0
- package/backend/dist/src/llm-orchestration/action-handlers/dto/howto.args.dto.js +7 -0
- package/backend/dist/src/llm-orchestration/action-handlers/dto/howto.args.dto.js.map +1 -0
- package/backend/dist/src/llm-orchestration/action-handlers/dto/patch.args.dto.d.ts +4 -0
- package/backend/dist/src/llm-orchestration/action-handlers/dto/patch.args.dto.js +29 -0
- package/backend/dist/src/llm-orchestration/action-handlers/dto/patch.args.dto.js.map +1 -0
- package/backend/dist/src/llm-orchestration/action-handlers/edit-file.handler.d.ts +1 -0
- package/backend/dist/src/llm-orchestration/action-handlers/edit-file.handler.js +55 -0
- package/backend/dist/src/llm-orchestration/action-handlers/edit-file.handler.js.map +1 -1
- package/backend/dist/src/llm-orchestration/action-handlers/final.handler.d.ts +1 -0
- package/backend/dist/src/llm-orchestration/action-handlers/final.handler.js +20 -0
- package/backend/dist/src/llm-orchestration/action-handlers/final.handler.js.map +1 -1
- package/backend/dist/src/llm-orchestration/action-handlers/howto.handler.d.ts +9 -0
- package/backend/dist/src/llm-orchestration/action-handlers/howto.handler.js +85 -0
- package/backend/dist/src/llm-orchestration/action-handlers/howto.handler.js.map +1 -0
- package/backend/dist/src/llm-orchestration/action-handlers/new-session.handler.d.ts +1 -0
- package/backend/dist/src/llm-orchestration/action-handlers/new-session.handler.js +21 -0
- package/backend/dist/src/llm-orchestration/action-handlers/new-session.handler.js.map +1 -1
- package/backend/dist/src/llm-orchestration/action-handlers/patch.handler.d.ts +13 -0
- package/backend/dist/src/llm-orchestration/action-handlers/patch.handler.js +247 -0
- package/backend/dist/src/llm-orchestration/action-handlers/patch.handler.js.map +1 -0
- package/backend/dist/src/llm-orchestration/action-handlers/quick-edit.handler.d.ts +1 -0
- package/backend/dist/src/llm-orchestration/action-handlers/quick-edit.handler.js +53 -0
- package/backend/dist/src/llm-orchestration/action-handlers/quick-edit.handler.js.map +1 -1
- package/backend/dist/src/llm-orchestration/action-handlers/request-context.handler.d.ts +1 -0
- package/backend/dist/src/llm-orchestration/action-handlers/request-context.handler.js +30 -0
- package/backend/dist/src/llm-orchestration/action-handlers/request-context.handler.js.map +1 -1
- package/backend/dist/src/llm-orchestration/action-handlers/run-command.handler.d.ts +1 -0
- package/backend/dist/src/llm-orchestration/action-handlers/run-command.handler.js +45 -0
- package/backend/dist/src/llm-orchestration/action-handlers/run-command.handler.js.map +1 -1
- package/backend/dist/src/llm-orchestration/action-handlers/use-mcp-tool.handler.d.ts +1 -0
- package/backend/dist/src/llm-orchestration/action-handlers/use-mcp-tool.handler.js +29 -0
- package/backend/dist/src/llm-orchestration/action-handlers/use-mcp-tool.handler.js.map +1 -1
- package/backend/dist/src/llm-orchestration/llm-orchestration.module.js +6 -2
- package/backend/dist/src/llm-orchestration/llm-orchestration.module.js.map +1 -1
- package/backend/dist/src/llm-orchestration/llm-turn-processor.service.js +1 -0
- package/backend/dist/src/llm-orchestration/llm-turn-processor.service.js.map +1 -1
- package/backend/dist/src/seeding/data/custom-snippets/eta-for.d.ts +4 -0
- package/backend/dist/src/seeding/data/custom-snippets/eta-for.js +8 -0
- package/backend/dist/src/seeding/data/custom-snippets/eta-for.js.map +1 -0
- package/backend/dist/src/seeding/data/custom-snippets/eta-if.d.ts +4 -0
- package/backend/dist/src/seeding/data/custom-snippets/eta-if.js +8 -0
- package/backend/dist/src/seeding/data/custom-snippets/eta-if.js.map +1 -0
- package/backend/dist/src/seeding/data/custom-snippets/eta-ifelse.d.ts +4 -0
- package/backend/dist/src/seeding/data/custom-snippets/eta-ifelse.js +8 -0
- package/backend/dist/src/seeding/data/custom-snippets/eta-ifelse.js.map +1 -0
- package/backend/dist/src/seeding/data/custom-snippets/it-mcp.d.ts +4 -0
- package/backend/dist/src/seeding/data/custom-snippets/it-mcp.js +8 -0
- package/backend/dist/src/seeding/data/custom-snippets/it-mcp.js.map +1 -0
- package/backend/dist/src/seeding/data/custom-snippets/it-tools.d.ts +4 -0
- package/backend/dist/src/seeding/data/custom-snippets/it-tools.js +8 -0
- package/backend/dist/src/seeding/data/custom-snippets/it-tools.js.map +1 -0
- package/backend/dist/src/seeding/data/system-prompts/default_master-agent.d.ts +1 -1
- package/backend/dist/src/seeding/data/system-prompts/default_master-agent.js +1 -1
- package/backend/dist/src/seeding/data/system-prompts/experimental_eta_master-agent.d.ts +2 -0
- package/backend/dist/src/seeding/data/system-prompts/experimental_eta_master-agent.js +62 -0
- package/backend/dist/src/seeding/data/system-prompts/experimental_eta_master-agent.js.map +1 -0
- package/backend/dist/src/seeding/data/system-prompts/experimental_patch_master-agent.d.ts +2 -0
- package/backend/dist/src/seeding/data/system-prompts/experimental_patch_master-agent.js +463 -0
- package/backend/dist/src/seeding/data/system-prompts/experimental_patch_master-agent.js.map +1 -0
- package/backend/dist/src/system-prompts/dto/system-prompt.dto.d.ts +6 -0
- package/backend/dist/src/system-prompts/dto/system-prompt.dto.js +12 -1
- package/backend/dist/src/system-prompts/dto/system-prompt.dto.js.map +1 -1
- package/backend/dist/src/system-prompts/system-prompts.controller.d.ts +3 -1
- package/backend/dist/src/system-prompts/system-prompts.controller.js +20 -0
- package/backend/dist/src/system-prompts/system-prompts.controller.js.map +1 -1
- package/backend/dist/src/system-prompts/system-prompts.module.js +11 -1
- package/backend/dist/src/system-prompts/system-prompts.module.js.map +1 -1
- package/backend/dist/src/system-prompts/system-prompts.service.d.ts +11 -3
- package/backend/dist/src/system-prompts/system-prompts.service.js +39 -12
- package/backend/dist/src/system-prompts/system-prompts.service.js.map +1 -1
- package/backend/dist/src/utils/ai-format-generator.d.ts +1 -0
- package/backend/dist/src/utils/ai-format-generator.js +23 -0
- package/backend/dist/src/utils/ai-format-generator.js.map +1 -0
- package/backend/dist/src/utils/index.d.ts +1 -0
- package/backend/dist/src/utils/index.js +1 -0
- package/backend/dist/src/utils/index.js.map +1 -1
- package/backend/dist/tsconfig.build.tsbuildinfo +1 -1
- package/backend/package.json +6 -3
- package/backend/packages/tokenpatch/grammar/tree-sitter-tsx.wasm +0 -0
- package/backend/packages/tokenpatch/grammar/tree-sitter-typescript.wasm +0 -0
- package/backend/packages/tokenpatch/index.spec.ts +579 -0
- package/backend/packages/tokenpatch/index.ts +80 -0
- package/backend/packages/tokenpatch/parser.ts +18 -0
- package/backend/packages/tokenpatch/patcher.spec.ts +194 -0
- package/backend/packages/tokenpatch/patcher.ts +300 -0
- package/backend/packages/tokenpatch/tokens.spec.ts +84 -0
- package/backend/packages/tokenpatch/tokens.ts +50 -0
- package/backend/packages/tokenpatch/types.ts +9 -0
- package/package.json +13 -12
- package/backend/coverage/clover.xml +0 -3434
- package/backend/coverage/coverage-final.json +0 -120
- package/backend/coverage/lcov-report/base.css +0 -224
- package/backend/coverage/lcov-report/block-navigation.js +0 -87
- package/backend/coverage/lcov-report/favicon.png +0 -0
- package/backend/coverage/lcov-report/index.html +0 -701
- package/backend/coverage/lcov-report/prettify.css +0 -1
- package/backend/coverage/lcov-report/prettify.js +0 -2
- package/backend/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/backend/coverage/lcov-report/sorter.js +0 -196
- package/backend/coverage/lcov-report/src/action-execution/action-execution.module.ts.html +0 -109
- package/backend/coverage/lcov-report/src/action-execution/action-execution.service.ts.html +0 -448
- package/backend/coverage/lcov-report/src/action-execution/index.html +0 -131
- package/backend/coverage/lcov-report/src/ai-actions/ai-action-batch.service.ts.html +0 -940
- package/backend/coverage/lcov-report/src/ai-actions/ai-action-creation.service.ts.html +0 -1243
- package/backend/coverage/lcov-report/src/ai-actions/ai-actions.controller.ts.html +0 -664
- package/backend/coverage/lcov-report/src/ai-actions/ai-actions.module.ts.html +0 -154
- package/backend/coverage/lcov-report/src/ai-actions/ai-actions.service.ts.html +0 -859
- package/backend/coverage/lcov-report/src/ai-actions/index.html +0 -176
- package/backend/coverage/lcov-report/src/app.controller.ts.html +0 -151
- package/backend/coverage/lcov-report/src/app.module.ts.html +0 -373
- package/backend/coverage/lcov-report/src/app.service.ts.html +0 -196
- package/backend/coverage/lcov-report/src/application-state/application-state.controller.ts.html +0 -319
- package/backend/coverage/lcov-report/src/application-state/application-state.module.ts.html +0 -124
- package/backend/coverage/lcov-report/src/application-state/application-state.service.ts.html +0 -439
- package/backend/coverage/lcov-report/src/application-state/dto/index.html +0 -161
- package/backend/coverage/lcov-report/src/application-state/dto/set-auto-context-fetch-enabled.dto.ts.html +0 -103
- package/backend/coverage/lcov-report/src/application-state/dto/set-orchestration-timeout.dto.ts.html +0 -103
- package/backend/coverage/lcov-report/src/application-state/dto/set-theme.dto.ts.html +0 -106
- package/backend/coverage/lcov-report/src/application-state/dto/set-websocket-enabled.dto.ts.html +0 -103
- package/backend/coverage/lcov-report/src/application-state/index.html +0 -146
- package/backend/coverage/lcov-report/src/context-generation/context-generation.module.ts.html +0 -118
- package/backend/coverage/lcov-report/src/context-generation/context-generation.service.ts.html +0 -1348
- package/backend/coverage/lcov-report/src/context-generation/index.html +0 -131
- package/backend/coverage/lcov-report/src/context-snippets/context-snippets.controller.ts.html +0 -289
- package/backend/coverage/lcov-report/src/context-snippets/context-snippets.module.ts.html +0 -136
- package/backend/coverage/lcov-report/src/context-snippets/context-snippets.service.ts.html +0 -400
- package/backend/coverage/lcov-report/src/context-snippets/dto/context-snippet.dto.ts.html +0 -211
- package/backend/coverage/lcov-report/src/context-snippets/dto/index.html +0 -116
- package/backend/coverage/lcov-report/src/context-snippets/index.html +0 -146
- package/backend/coverage/lcov-report/src/context-templates/context-templates.controller.ts.html +0 -397
- package/backend/coverage/lcov-report/src/context-templates/context-templates.module.ts.html +0 -136
- package/backend/coverage/lcov-report/src/context-templates/context-templates.service.ts.html +0 -835
- package/backend/coverage/lcov-report/src/context-templates/dto/context-template.dto.ts.html +0 -358
- package/backend/coverage/lcov-report/src/context-templates/dto/index.html +0 -116
- package/backend/coverage/lcov-report/src/context-templates/index.html +0 -146
- package/backend/coverage/lcov-report/src/core-entities/ai-action.entity.ts.html +0 -241
- package/backend/coverage/lcov-report/src/core-entities/application-state.entity.ts.html +0 -115
- package/backend/coverage/lcov-report/src/core-entities/base.entity.ts.html +0 -145
- package/backend/coverage/lcov-report/src/core-entities/context-snippet.entity.ts.html +0 -130
- package/backend/coverage/lcov-report/src/core-entities/context-template.entity.ts.html +0 -223
- package/backend/coverage/lcov-report/src/core-entities/custom-snippet.entity.ts.html +0 -136
- package/backend/coverage/lcov-report/src/core-entities/execution-log.entity.ts.html +0 -157
- package/backend/coverage/lcov-report/src/core-entities/index.html +0 -281
- package/backend/coverage/lcov-report/src/core-entities/index.ts.html +0 -118
- package/backend/coverage/lcov-report/src/core-entities/project.entity.ts.html +0 -130
- package/backend/coverage/lcov-report/src/core-entities/session-input.entity.ts.html +0 -289
- package/backend/coverage/lcov-report/src/core-entities/session.entity.ts.html +0 -280
- package/backend/coverage/lcov-report/src/core-entities/system-prompt.entity.ts.html +0 -148
- package/backend/coverage/lcov-report/src/custom-snippets/custom-snippets.controller.ts.html +0 -277
- package/backend/coverage/lcov-report/src/custom-snippets/custom-snippets.module.ts.html +0 -124
- package/backend/coverage/lcov-report/src/custom-snippets/custom-snippets.service.ts.html +0 -304
- package/backend/coverage/lcov-report/src/custom-snippets/dto/custom-snippet.dto.ts.html +0 -205
- package/backend/coverage/lcov-report/src/custom-snippets/dto/index.html +0 -116
- package/backend/coverage/lcov-report/src/custom-snippets/index.html +0 -146
- package/backend/coverage/lcov-report/src/events/events.gateway.ts.html +0 -292
- package/backend/coverage/lcov-report/src/events/events.module.ts.html +0 -109
- package/backend/coverage/lcov-report/src/events/index.html +0 -131
- package/backend/coverage/lcov-report/src/execution-logs/dto/execution-log.dto.ts.html +0 -130
- package/backend/coverage/lcov-report/src/execution-logs/dto/index.html +0 -116
- package/backend/coverage/lcov-report/src/execution-logs/execution-logs.controller.ts.html +0 -130
- package/backend/coverage/lcov-report/src/execution-logs/execution-logs.module.ts.html +0 -124
- package/backend/coverage/lcov-report/src/execution-logs/execution-logs.service.ts.html +0 -238
- package/backend/coverage/lcov-report/src/execution-logs/index.html +0 -146
- package/backend/coverage/lcov-report/src/http-exception.filter.ts.html +0 -340
- package/backend/coverage/lcov-report/src/index.html +0 -191
- package/backend/coverage/lcov-report/src/llm-response-parser/dto/ai-action.dto.ts.html +0 -400
- package/backend/coverage/lcov-report/src/llm-response-parser/dto/index.html +0 -116
- package/backend/coverage/lcov-report/src/llm-response-parser/errors/index.html +0 -116
- package/backend/coverage/lcov-report/src/llm-response-parser/errors/parsing.error.ts.html +0 -118
- package/backend/coverage/lcov-report/src/llm-response-parser/index.html +0 -146
- package/backend/coverage/lcov-report/src/llm-response-parser/llm-response-parser.module.ts.html +0 -109
- package/backend/coverage/lcov-report/src/llm-response-parser/llm-response-parser.service.ts.html +0 -808
- package/backend/coverage/lcov-report/src/llm-response-parser/parsing.constants.ts.html +0 -139
- package/backend/coverage/lcov-report/src/llm-responses/dto/index.html +0 -116
- package/backend/coverage/lcov-report/src/llm-responses/dto/submit-llm-response.dto.ts.html +0 -172
- package/backend/coverage/lcov-report/src/llm-responses/index.html +0 -146
- package/backend/coverage/lcov-report/src/llm-responses/llm-responses.controller.ts.html +0 -154
- package/backend/coverage/lcov-report/src/llm-responses/llm-responses.module.ts.html +0 -166
- package/backend/coverage/lcov-report/src/llm-responses/llm-responses.service.ts.html +0 -787
- package/backend/coverage/lcov-report/src/main.ts.html +0 -382
- package/backend/coverage/lcov-report/src/orchestration/dto/index.html +0 -116
- package/backend/coverage/lcov-report/src/orchestration/dto/orchestration.dto.ts.html +0 -169
- package/backend/coverage/lcov-report/src/orchestration/index.html +0 -191
- package/backend/coverage/lcov-report/src/orchestration/orchestration-fs.service.ts.html +0 -595
- package/backend/coverage/lcov-report/src/orchestration/orchestration-parser.service.ts.html +0 -142
- package/backend/coverage/lcov-report/src/orchestration/orchestration.controller.ts.html +0 -406
- package/backend/coverage/lcov-report/src/orchestration/orchestration.module.ts.html +0 -169
- package/backend/coverage/lcov-report/src/orchestration/orchestration.service.ts.html +0 -1093
- package/backend/coverage/lcov-report/src/orchestration/orchestration.types.ts.html +0 -175
- package/backend/coverage/lcov-report/src/projects/dto/index.html +0 -116
- package/backend/coverage/lcov-report/src/projects/dto/project.dto.ts.html +0 -154
- package/backend/coverage/lcov-report/src/projects/index.html +0 -146
- package/backend/coverage/lcov-report/src/projects/projects.controller.ts.html +0 -232
- package/backend/coverage/lcov-report/src/projects/projects.module.ts.html +0 -124
- package/backend/coverage/lcov-report/src/projects/projects.service.ts.html +0 -223
- package/backend/coverage/lcov-report/src/seeding/context-template-seeding.service.ts.html +0 -355
- package/backend/coverage/lcov-report/src/seeding/custom-snippet-seeding.service.ts.html +0 -271
- package/backend/coverage/lcov-report/src/seeding/data/context-templates/default-followup_ad-hoc-focused-context.ts.html +0 -136
- package/backend/coverage/lcov-report/src/seeding/data/context-templates/default-initial_condensed-project-context.ts.html +0 -148
- package/backend/coverage/lcov-report/src/seeding/data/context-templates/default-initial_full-project-context.ts.html +0 -247
- package/backend/coverage/lcov-report/src/seeding/data/context-templates/index.html +0 -190
- package/backend/coverage/lcov-report/src/seeding/data/context-templates/pm-context.ts.html +0 -250
- package/backend/coverage/lcov-report/src/seeding/data/context-templates/pr-description.ts.html +0 -186
- package/backend/coverage/lcov-report/src/seeding/data/context-templates/sample_focused-tree.ts.html +0 -124
- package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/default_rglob.ts.html +0 -94
- package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/git-diff.ts.html +0 -94
- package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/index.html +0 -236
- package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/rg-exclude.ts.html +0 -94
- package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/rg-search-glob.ts.html +0 -94
- package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/rg-search.ts.html +0 -94
- package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/run-command.ts.html +0 -94
- package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/tree.ts.html +0 -94
- package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/usr-adhoc-incl.ts.html +0 -100
- package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/usr-input-incl.ts.html +0 -94
- package/backend/coverage/lcov-report/src/seeding/data/system-prompts/codebase-explorer.ts.html +0 -331
- package/backend/coverage/lcov-report/src/seeding/data/system-prompts/default_multi-file-action-generator-with-requester.ts.html +0 -675
- package/backend/coverage/lcov-report/src/seeding/data/system-prompts/index.html +0 -160
- package/backend/coverage/lcov-report/src/seeding/data/system-prompts/multi-file-action-generator.ts.html +0 -550
- package/backend/coverage/lcov-report/src/seeding/data/system-prompts/packup.ts.html +0 -184
- package/backend/coverage/lcov-report/src/seeding/data/system-prompts/refactor-split.ts.html +0 -244
- package/backend/coverage/lcov-report/src/seeding/index.html +0 -176
- package/backend/coverage/lcov-report/src/seeding/seeding.module.ts.html +0 -145
- package/backend/coverage/lcov-report/src/seeding/seeding.service.ts.html +0 -151
- package/backend/coverage/lcov-report/src/seeding/system-prompt-seeding.service.ts.html +0 -289
- package/backend/coverage/lcov-report/src/session-followup/index.html +0 -131
- package/backend/coverage/lcov-report/src/session-followup/session-followup.module.ts.html +0 -130
- package/backend/coverage/lcov-report/src/session-followup/session-followup.service.ts.html +0 -670
- package/backend/coverage/lcov-report/src/session-inputs/dto/index.html +0 -116
- package/backend/coverage/lcov-report/src/session-inputs/dto/session-input.dto.ts.html +0 -247
- package/backend/coverage/lcov-report/src/session-inputs/index.html +0 -161
- package/backend/coverage/lcov-report/src/session-inputs/session-input-context.service.ts.html +0 -763
- package/backend/coverage/lcov-report/src/session-inputs/session-inputs.controller.ts.html +0 -337
- package/backend/coverage/lcov-report/src/session-inputs/session-inputs.module.ts.html +0 -205
- package/backend/coverage/lcov-report/src/session-inputs/session-inputs.service.ts.html +0 -1621
- package/backend/coverage/lcov-report/src/session-transfer/index.html +0 -131
- package/backend/coverage/lcov-report/src/session-transfer/session-transfer.module.ts.html +0 -172
- package/backend/coverage/lcov-report/src/session-transfer/session-transfer.service.ts.html +0 -574
- package/backend/coverage/lcov-report/src/sessions/dto/index.html +0 -116
- package/backend/coverage/lcov-report/src/sessions/dto/session.dto.ts.html +0 -340
- package/backend/coverage/lcov-report/src/sessions/index.html +0 -146
- package/backend/coverage/lcov-report/src/sessions/sessions.controller.ts.html +0 -457
- package/backend/coverage/lcov-report/src/sessions/sessions.module.ts.html +0 -214
- package/backend/coverage/lcov-report/src/sessions/sessions.service.ts.html +0 -844
- package/backend/coverage/lcov-report/src/system-prompts/dto/index.html +0 -116
- package/backend/coverage/lcov-report/src/system-prompts/dto/system-prompt.dto.ts.html +0 -217
- package/backend/coverage/lcov-report/src/system-prompts/index.html +0 -146
- package/backend/coverage/lcov-report/src/system-prompts/system-prompts.controller.ts.html +0 -298
- package/backend/coverage/lcov-report/src/system-prompts/system-prompts.module.ts.html +0 -127
- package/backend/coverage/lcov-report/src/system-prompts/system-prompts.service.ts.html +0 -352
- package/backend/coverage/lcov-report/src/timeout.interceptor.ts.html +0 -178
- package/backend/coverage/lcov-report/src/utils/fuzzy-search.ts.html +0 -310
- package/backend/coverage/lcov-report/src/utils/index.html +0 -131
- package/backend/coverage/lcov-report/src/utils/index.ts.html +0 -88
- package/backend/coverage/lcov-report/src/workspace/dto/index.html +0 -116
- package/backend/coverage/lcov-report/src/workspace/dto/search-workspace.dto.ts.html +0 -193
- package/backend/coverage/lcov-report/src/workspace/index.html +0 -146
- package/backend/coverage/lcov-report/src/workspace/workspace.controller.ts.html +0 -247
- package/backend/coverage/lcov-report/src/workspace/workspace.module.ts.html +0 -121
- package/backend/coverage/lcov-report/src/workspace/workspace.service.ts.html +0 -745
- package/backend/coverage/lcov.info +0 -5590
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import {
|
|
2
|
+
handleBeginOfFilePatch,
|
|
3
|
+
handleEndOfFilePatch,
|
|
4
|
+
handleStandardPatch,
|
|
5
|
+
} from './patcher';
|
|
6
|
+
import type { Token } from './types';
|
|
7
|
+
|
|
8
|
+
// Helper to create mock tokens for testing.
|
|
9
|
+
// Simplified: we only care about text, startIndex, and endIndex for these tests.
|
|
10
|
+
const makeTokens = (texts: string[]): Token[] => {
|
|
11
|
+
let offset = 0;
|
|
12
|
+
return texts.map((text) => {
|
|
13
|
+
const start = offset;
|
|
14
|
+
const end = start + text.length;
|
|
15
|
+
offset = end + 1; // Simulate space
|
|
16
|
+
return {
|
|
17
|
+
text,
|
|
18
|
+
type: 'test',
|
|
19
|
+
startIndex: start,
|
|
20
|
+
endIndex: end,
|
|
21
|
+
startPosition: { row: 0, column: start },
|
|
22
|
+
};
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
describe('patcher', () => {
|
|
27
|
+
describe('handleStandardPatch', () => {
|
|
28
|
+
it('should find a unique prefix and suffix', () => {
|
|
29
|
+
const sourceTokens = makeTokens(['prefix', '(', 'old', ')', 'suffix']);
|
|
30
|
+
const patchTokens = makeTokens(['prefix', '(', 'new', ')', 'suffix']);
|
|
31
|
+
const result = handleStandardPatch(sourceTokens, patchTokens);
|
|
32
|
+
expect(result).toEqual({
|
|
33
|
+
patchInsertEnd: 21,
|
|
34
|
+
patchInsertStart: 0,
|
|
35
|
+
replaceStart: 0, // 'prefix' startIndex
|
|
36
|
+
replaceEnd: 21, // 'suffix' endIndex
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('should trim non-matching tokens from both ends to find a match', () => {
|
|
41
|
+
const sourceTokens = makeTokens(['prefix', 'content', 'suffix']);
|
|
42
|
+
// The patch has extra tokens at the start and end that aren't in the source.
|
|
43
|
+
const patchTokens = makeTokens([
|
|
44
|
+
'bad', // 0-3
|
|
45
|
+
'prefix', // 4-10
|
|
46
|
+
'new-content', // 11-22
|
|
47
|
+
'suffix', // 23-29
|
|
48
|
+
'good', // 30-34
|
|
49
|
+
]);
|
|
50
|
+
const result = handleStandardPatch(sourceTokens, patchTokens);
|
|
51
|
+
// It should fail with 'bad'/'good', then trim them, then succeed on ['prefix', 'new-content', 'suffix']
|
|
52
|
+
expect(result).toEqual({
|
|
53
|
+
replaceStart: 0, // start of 'prefix' in source
|
|
54
|
+
replaceEnd: 21, // end of 'suffix' in source
|
|
55
|
+
patchInsertStart: 4, // start of 'prefix' in patch
|
|
56
|
+
patchInsertEnd: 29, // end of 'suffix' in patch
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('should throw for persistently ambiguous prefix', () => {
|
|
61
|
+
const sourceTokens = makeTokens(['a', 'b', 'c', 'a', 'b', 'd']);
|
|
62
|
+
const patchTokens = makeTokens(['a', 'b', 'e']); // a b is ambiguous
|
|
63
|
+
expect(() => handleStandardPatch(sourceTokens, patchTokens)).toThrow(
|
|
64
|
+
/Ambiguous prefix anchor/,
|
|
65
|
+
);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('should throw for persistently ambiguous suffix', () => {
|
|
69
|
+
const sourceTokens = makeTokens(['prefix', 'x', 'suffix', 'y', 'suffix']);
|
|
70
|
+
const patchTokens = makeTokens(['prefix', 'z', 'suffix']);
|
|
71
|
+
expect(() => handleStandardPatch(sourceTokens, patchTokens)).toThrow(
|
|
72
|
+
/Ambiguous suffix anchor/,
|
|
73
|
+
);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('should throw if patch has fewer than two tokens', () => {
|
|
77
|
+
const sourceTokens = makeTokens(['a', 'b', 'c']);
|
|
78
|
+
const patchTokens = makeTokens(['a']);
|
|
79
|
+
expect(() => handleStandardPatch(sourceTokens, patchTokens)).toThrow(
|
|
80
|
+
'Patch must contain at least two tokens to form a prefix and a suffix.',
|
|
81
|
+
);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
describe('handleBeginOfFilePatch', () => {
|
|
86
|
+
it('should find a unique suffix anchor', () => {
|
|
87
|
+
const sourceTokens = makeTokens(['a', 'b', 'c', 'd']);
|
|
88
|
+
const patchTokens = makeTokens(['x', 'y', 'c', 'd']); // Suffix is 'c', 'd'
|
|
89
|
+
const result = handleBeginOfFilePatch(sourceTokens, patchTokens);
|
|
90
|
+
expect(result).toEqual({
|
|
91
|
+
patchInsertEnd: 7,
|
|
92
|
+
patchInsertStart: 0,
|
|
93
|
+
replaceStart: 0,
|
|
94
|
+
replaceEnd: 7, // endIndex of 'd'
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it('should trim from the start to find a unique suffix', () => {
|
|
99
|
+
// The "good" part of the patch, ['a', 'b'], is unique in the source.
|
|
100
|
+
const sourceTokens = makeTokens(['x', 'y', 'a', 'b']);
|
|
101
|
+
// The initial patch will fail because the suffix ['y', 'a', 'b'] is not in the source.
|
|
102
|
+
const patchTokens = makeTokens([
|
|
103
|
+
'bad', // 0-3
|
|
104
|
+
'token', // 4-9
|
|
105
|
+
'a', // 10-11
|
|
106
|
+
'b', // 12-13
|
|
107
|
+
]);
|
|
108
|
+
const result = handleBeginOfFilePatch(sourceTokens, patchTokens);
|
|
109
|
+
// Should fail, trim 'bad', fail, trim 'token', then succeed with suffix ['a', 'b'].
|
|
110
|
+
expect(result).toEqual({
|
|
111
|
+
replaceStart: 0,
|
|
112
|
+
replaceEnd: 7, // end of 'b' in source
|
|
113
|
+
patchInsertStart: 0, // start of 'a' in patch
|
|
114
|
+
patchInsertEnd: 13, // end of 'b' in patch
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it('should throw for a persistently ambiguous suffix', () => {
|
|
119
|
+
const sourceTokens = makeTokens(['a', 'b', 'a', 'b']);
|
|
120
|
+
const patchTokens = makeTokens(['x', 'y', 'a', 'b']);
|
|
121
|
+
expect(() => handleBeginOfFilePatch(sourceTokens, patchTokens)).toThrow(
|
|
122
|
+
/Ambiguous suffix anchor/,
|
|
123
|
+
);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('should throw if anchor not found even after trimming', () => {
|
|
127
|
+
const sourceTokens = makeTokens(['a', 'b', 'c']);
|
|
128
|
+
const patchTokens = makeTokens(['x', 'y', 'z']);
|
|
129
|
+
expect(() => handleBeginOfFilePatch(sourceTokens, patchTokens)).toThrow(
|
|
130
|
+
/Suffix anchor not found/,
|
|
131
|
+
);
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
describe('handleEndOfFilePatch', () => {
|
|
136
|
+
const sourceCode = 'a b c d'; // length 7
|
|
137
|
+
const sourceTokens = makeTokens(['a', 'b', 'c', 'd']);
|
|
138
|
+
|
|
139
|
+
it('should find a unique prefix anchor', () => {
|
|
140
|
+
const patchTokens = makeTokens(['a', 'b', 'x', 'y']); // Prefix is 'a', 'b'
|
|
141
|
+
const result = handleEndOfFilePatch(
|
|
142
|
+
sourceTokens,
|
|
143
|
+
patchTokens,
|
|
144
|
+
sourceCode,
|
|
145
|
+
);
|
|
146
|
+
expect(result).toEqual({
|
|
147
|
+
patchInsertEnd: 7,
|
|
148
|
+
patchInsertStart: 0,
|
|
149
|
+
replaceStart: 0, // startIndex of 'a'
|
|
150
|
+
replaceEnd: 7, // sourceCode.length
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('should trim from the end to find a unique prefix', () => {
|
|
155
|
+
// The "good" part of the patch, ['c', 'd'], is unique in the source.
|
|
156
|
+
const sourceTokens = makeTokens(['c', 'd', 'x', 'y']);
|
|
157
|
+
const sourceCode = 'c d x y'; // length 7
|
|
158
|
+
// The initial patch will fail because the prefix ['c', 'd', 'bad'] is not in the source.
|
|
159
|
+
const patchTokens = makeTokens([
|
|
160
|
+
'c', // 0-1
|
|
161
|
+
'd', // 2-3
|
|
162
|
+
'bad', // 4-7
|
|
163
|
+
'token', // 8-13
|
|
164
|
+
]);
|
|
165
|
+
const result = handleEndOfFilePatch(
|
|
166
|
+
sourceTokens,
|
|
167
|
+
patchTokens,
|
|
168
|
+
sourceCode,
|
|
169
|
+
);
|
|
170
|
+
// Should fail, trim 'token', fail, trim 'bad', then succeed with prefix ['c', 'd'].
|
|
171
|
+
expect(result).toEqual({
|
|
172
|
+
replaceStart: 0, // start of 'c' in source
|
|
173
|
+
replaceEnd: 7, // sourceCode.length
|
|
174
|
+
patchInsertStart: 0, // start of 'c' in patch
|
|
175
|
+
patchInsertEnd: 13, // end of 'd' in patch
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it('should throw for a persistently ambiguous prefix', () => {
|
|
180
|
+
const ambiguousSourceTokens = makeTokens(['a', 'b', 'a', 'b']);
|
|
181
|
+
const patchTokens = makeTokens(['a', 'b', 'x', 'y']);
|
|
182
|
+
expect(() =>
|
|
183
|
+
handleEndOfFilePatch(ambiguousSourceTokens, patchTokens, 'a b a b'),
|
|
184
|
+
).toThrow(/Ambiguous prefix anchor/);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it('should throw if anchor not found even after trimming', () => {
|
|
188
|
+
const patchTokens = makeTokens(['x', 'y', 'z']);
|
|
189
|
+
expect(() =>
|
|
190
|
+
handleEndOfFilePatch(sourceTokens, patchTokens, sourceCode),
|
|
191
|
+
).toThrow(/Prefix anchor not found/);
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
});
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
import type { Token } from './types';
|
|
2
|
+
import { findAllSequences, formatAnchor } from './tokens';
|
|
3
|
+
|
|
4
|
+
interface PatchResult {
|
|
5
|
+
replaceStart: number;
|
|
6
|
+
replaceEnd: number;
|
|
7
|
+
patchInsertStart: number;
|
|
8
|
+
patchInsertEnd: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface SimplePatchResult {
|
|
12
|
+
replaceStart: number;
|
|
13
|
+
replaceEnd: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Internal helper for the original matching logic
|
|
17
|
+
function _findBeginOfFilePatchLocation(
|
|
18
|
+
sourceTokens: Token[],
|
|
19
|
+
patchTokens: Token[],
|
|
20
|
+
): SimplePatchResult {
|
|
21
|
+
let replaceStart: number | null = null;
|
|
22
|
+
let replaceEnd: number | null = null;
|
|
23
|
+
let lastError = '';
|
|
24
|
+
|
|
25
|
+
for (let anchorSize = 1; anchorSize <= patchTokens.length; anchorSize++) {
|
|
26
|
+
const suffixAnchor = patchTokens.slice(patchTokens.length - anchorSize);
|
|
27
|
+
const indices = findAllSequences(sourceTokens, suffixAnchor);
|
|
28
|
+
|
|
29
|
+
if (indices.length === 1) {
|
|
30
|
+
replaceStart = 0;
|
|
31
|
+
const suffixIndex = indices[0];
|
|
32
|
+
replaceEnd = sourceTokens[suffixIndex + anchorSize - 1].endIndex;
|
|
33
|
+
break; // Found unique anchor
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (indices.length > 1) {
|
|
37
|
+
const formattedAnchor = formatAnchor(suffixAnchor);
|
|
38
|
+
const locations = indices
|
|
39
|
+
.map((i) => `line ${sourceTokens[i].startPosition.row + 1}`)
|
|
40
|
+
.join(', ');
|
|
41
|
+
lastError = `Ambiguous suffix anchor. The sequence "${formattedAnchor}" was found at ${indices.length} locations: ${locations}.`;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (replaceStart === null || replaceEnd === null) {
|
|
46
|
+
const smallestAnchor = patchTokens.slice(patchTokens.length - 1);
|
|
47
|
+
throw new Error(
|
|
48
|
+
lastError ||
|
|
49
|
+
`Suffix anchor not found. The sequence "${formatAnchor(
|
|
50
|
+
smallestAnchor,
|
|
51
|
+
)}" could not be located.`,
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return { replaceStart, replaceEnd };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function handleBeginOfFilePatch(
|
|
59
|
+
sourceTokens: Token[],
|
|
60
|
+
originalPatchTokens: Token[],
|
|
61
|
+
): PatchResult {
|
|
62
|
+
if (originalPatchTokens.length === 0) {
|
|
63
|
+
throw new Error('Patch is empty after removing @begin-of-file marker.');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
let patchAttempt = [...originalPatchTokens];
|
|
67
|
+
let lastError: Error | null = null;
|
|
68
|
+
|
|
69
|
+
// Outer loop for trimming tokens from the start
|
|
70
|
+
while (patchAttempt.length >= 1) {
|
|
71
|
+
try {
|
|
72
|
+
const { replaceStart, replaceEnd } = _findBeginOfFilePatchLocation(
|
|
73
|
+
sourceTokens,
|
|
74
|
+
patchAttempt,
|
|
75
|
+
);
|
|
76
|
+
const patchInsertStart = patchAttempt[0].startIndex;
|
|
77
|
+
const patchInsertEnd = patchAttempt[patchAttempt.length - 1].endIndex;
|
|
78
|
+
return { replaceStart, replaceEnd, patchInsertStart, patchInsertEnd };
|
|
79
|
+
} catch (e) {
|
|
80
|
+
lastError = e as Error;
|
|
81
|
+
patchAttempt = patchAttempt.slice(1); // Trim one token from the beginning
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
throw new Error(
|
|
86
|
+
`Failed to apply @begin-of-file patch. Could not find a unique anchor, even after trimming tokens. Last known error: ${lastError?.message}`,
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Internal helper for the original matching logic
|
|
91
|
+
function _findEndOfFilePatchLocation(
|
|
92
|
+
sourceTokens: Token[],
|
|
93
|
+
patchTokens: Token[],
|
|
94
|
+
sourceCode: string,
|
|
95
|
+
): SimplePatchResult {
|
|
96
|
+
let replaceStart: number | null = null;
|
|
97
|
+
let replaceEnd: number | null = null;
|
|
98
|
+
let lastError = '';
|
|
99
|
+
|
|
100
|
+
for (let anchorSize = 1; anchorSize <= patchTokens.length; anchorSize++) {
|
|
101
|
+
const prefixAnchor = patchTokens.slice(0, anchorSize);
|
|
102
|
+
const indices = findAllSequences(sourceTokens, prefixAnchor);
|
|
103
|
+
|
|
104
|
+
if (indices.length === 1) {
|
|
105
|
+
replaceStart = sourceTokens[indices[0]].startIndex;
|
|
106
|
+
replaceEnd = sourceCode.length;
|
|
107
|
+
break; // Found unique anchor
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (indices.length > 1) {
|
|
111
|
+
const formattedAnchor = formatAnchor(prefixAnchor);
|
|
112
|
+
const locations = indices
|
|
113
|
+
.map((i) => `line ${sourceTokens[i].startPosition.row + 1}`)
|
|
114
|
+
.join(', ');
|
|
115
|
+
lastError = `Ambiguous prefix anchor. The sequence "${formattedAnchor}" was found at ${indices.length} locations: ${locations}.`;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (replaceStart === null || replaceEnd === null) {
|
|
120
|
+
const smallestAnchor = patchTokens.slice(0, 1);
|
|
121
|
+
throw new Error(
|
|
122
|
+
lastError ||
|
|
123
|
+
`Prefix anchor not found. The sequence "${formatAnchor(
|
|
124
|
+
smallestAnchor,
|
|
125
|
+
)}" could not be located.`,
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
return { replaceStart, replaceEnd };
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function handleEndOfFilePatch(
|
|
132
|
+
sourceTokens: Token[],
|
|
133
|
+
originalPatchTokens: Token[],
|
|
134
|
+
sourceCode: string,
|
|
135
|
+
): PatchResult {
|
|
136
|
+
if (originalPatchTokens.length === 0) {
|
|
137
|
+
throw new Error('Patch is empty after removing @end-of-file marker.');
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
let patchAttempt = [...originalPatchTokens];
|
|
141
|
+
let lastError: Error | null = null;
|
|
142
|
+
|
|
143
|
+
// Outer loop for trimming tokens from the end
|
|
144
|
+
while (patchAttempt.length >= 1) {
|
|
145
|
+
try {
|
|
146
|
+
const { replaceStart, replaceEnd } = _findEndOfFilePatchLocation(
|
|
147
|
+
sourceTokens,
|
|
148
|
+
patchAttempt,
|
|
149
|
+
sourceCode,
|
|
150
|
+
);
|
|
151
|
+
const patchInsertStart = patchAttempt[0].startIndex;
|
|
152
|
+
const patchInsertEnd = patchAttempt[patchAttempt.length - 1].endIndex;
|
|
153
|
+
return { replaceStart, replaceEnd, patchInsertStart, patchInsertEnd };
|
|
154
|
+
} catch (e) {
|
|
155
|
+
lastError = e as Error;
|
|
156
|
+
patchAttempt = patchAttempt.slice(0, -1); // Trim one token from the end
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
throw new Error(
|
|
161
|
+
`Failed to apply @end-of-file patch. Could not find a unique anchor, even after trimming tokens. Last known error: ${lastError?.message}`,
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Internal helper for the original matching logic
|
|
166
|
+
function _findStandardPatchLocation(
|
|
167
|
+
sourceTokens: Token[],
|
|
168
|
+
patchTokens: Token[],
|
|
169
|
+
): SimplePatchResult {
|
|
170
|
+
// 1. Find smallest unique prefix
|
|
171
|
+
let prefixAnchor: Token[] | null = null;
|
|
172
|
+
let prefixIndex: number | null = null;
|
|
173
|
+
let bestPrefixError: string | null = null;
|
|
174
|
+
|
|
175
|
+
for (let prefixSize = 1; prefixSize < patchTokens.length; prefixSize++) {
|
|
176
|
+
const currentPrefix = patchTokens.slice(0, prefixSize);
|
|
177
|
+
const prefixIndices = findAllSequences(sourceTokens, currentPrefix);
|
|
178
|
+
|
|
179
|
+
if (prefixIndices.length === 1) {
|
|
180
|
+
prefixAnchor = currentPrefix;
|
|
181
|
+
prefixIndex = prefixIndices[0];
|
|
182
|
+
bestPrefixError = null; // Found it
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
if (prefixIndices.length > 1) {
|
|
186
|
+
const formatted = formatAnchor(currentPrefix);
|
|
187
|
+
const locations = prefixIndices
|
|
188
|
+
.map((i) => `line ${sourceTokens[i].startPosition.row + 1}`)
|
|
189
|
+
.join(', ');
|
|
190
|
+
bestPrefixError = `Ambiguous prefix anchor. The sequence "${formatted}" was found at ${prefixIndices.length} locations: ${locations}.`;
|
|
191
|
+
}
|
|
192
|
+
if (prefixIndices.length === 0) {
|
|
193
|
+
if (!bestPrefixError) {
|
|
194
|
+
const formatted = formatAnchor(currentPrefix);
|
|
195
|
+
bestPrefixError = `Prefix anchor not found: "${formatted}"`;
|
|
196
|
+
}
|
|
197
|
+
break; // A larger prefix will also not be found
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (!prefixAnchor || prefixIndex === null) {
|
|
202
|
+
throw new Error(
|
|
203
|
+
bestPrefixError || 'Could not find a unique prefix anchor.',
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// 2. Find smallest unique suffix after prefix
|
|
208
|
+
let suffixAnchor: Token[] | null = null;
|
|
209
|
+
let suffixIndex: number | null = null;
|
|
210
|
+
let bestSuffixError: string | null = null;
|
|
211
|
+
const searchStartIndex = prefixIndex + prefixAnchor.length;
|
|
212
|
+
const sourceAfterPrefix = sourceTokens.slice(searchStartIndex);
|
|
213
|
+
|
|
214
|
+
for (
|
|
215
|
+
let suffixSize = 1;
|
|
216
|
+
suffixSize <= patchTokens.length - prefixAnchor.length;
|
|
217
|
+
suffixSize++
|
|
218
|
+
) {
|
|
219
|
+
const currentSuffix = patchTokens.slice(patchTokens.length - suffixSize);
|
|
220
|
+
const suffixIndices = findAllSequences(sourceAfterPrefix, currentSuffix);
|
|
221
|
+
|
|
222
|
+
if (suffixIndices.length === 1) {
|
|
223
|
+
suffixAnchor = currentSuffix;
|
|
224
|
+
suffixIndex = searchStartIndex + suffixIndices[0];
|
|
225
|
+
bestSuffixError = null; // Found it
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
if (suffixIndices.length > 1) {
|
|
229
|
+
const formatted = formatAnchor(currentSuffix);
|
|
230
|
+
const locations = suffixIndices
|
|
231
|
+
.map(
|
|
232
|
+
(i) =>
|
|
233
|
+
`line ${
|
|
234
|
+
sourceTokens[searchStartIndex + i].startPosition.row + 1
|
|
235
|
+
}`,
|
|
236
|
+
)
|
|
237
|
+
.join(', ');
|
|
238
|
+
bestSuffixError = `Ambiguous suffix anchor. The sequence "${formatted}" was found ${suffixIndices.length} times after the prefix: ${locations}.`;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
if (!suffixAnchor || suffixIndex === null) {
|
|
242
|
+
if (bestSuffixError) {
|
|
243
|
+
throw new Error(bestSuffixError);
|
|
244
|
+
}
|
|
245
|
+
const prefixLocation = `line ${
|
|
246
|
+
sourceTokens[prefixIndex].startPosition.row + 1
|
|
247
|
+
}`;
|
|
248
|
+
const formattedPrefix = formatAnchor(prefixAnchor);
|
|
249
|
+
const smallestSuffix = formatAnchor(
|
|
250
|
+
patchTokens.slice(patchTokens.length - 1),
|
|
251
|
+
);
|
|
252
|
+
|
|
253
|
+
throw new Error(
|
|
254
|
+
`Could not find a unique suffix anchor after the prefix anchor "${formattedPrefix}" (found at ${prefixLocation}). ` +
|
|
255
|
+
`The smallest suffix searched for ("${smallestSuffix}") was not found after it.`,
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// 3. Apply patch
|
|
260
|
+
const replaceStart = sourceTokens[prefixIndex].startIndex;
|
|
261
|
+
const replaceEnd =
|
|
262
|
+
sourceTokens[suffixIndex + suffixAnchor.length - 1].endIndex;
|
|
263
|
+
|
|
264
|
+
return { replaceStart, replaceEnd };
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
export function handleStandardPatch(
|
|
268
|
+
sourceTokens: Token[],
|
|
269
|
+
originalPatchTokens: Token[],
|
|
270
|
+
): PatchResult {
|
|
271
|
+
if (originalPatchTokens.length < 2) {
|
|
272
|
+
throw new Error(
|
|
273
|
+
'Patch must contain at least two tokens to form a prefix and a suffix.',
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
let patchAttempt = [...originalPatchTokens];
|
|
278
|
+
let lastError: Error | null = null;
|
|
279
|
+
|
|
280
|
+
// Outer loop for trimming tokens from both ends
|
|
281
|
+
while (patchAttempt.length >= 2) {
|
|
282
|
+
try {
|
|
283
|
+
const { replaceStart, replaceEnd } = _findStandardPatchLocation(
|
|
284
|
+
sourceTokens,
|
|
285
|
+
patchAttempt,
|
|
286
|
+
);
|
|
287
|
+
const patchInsertStart = patchAttempt[0].startIndex;
|
|
288
|
+
const patchInsertEnd = patchAttempt[patchAttempt.length - 1].endIndex;
|
|
289
|
+
return { replaceStart, replaceEnd, patchInsertStart, patchInsertEnd };
|
|
290
|
+
} catch (e) {
|
|
291
|
+
lastError = e as Error;
|
|
292
|
+
// Trim one token from the start and one from the end for the next attempt
|
|
293
|
+
patchAttempt = patchAttempt.slice(1, -1);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
throw new Error(
|
|
298
|
+
`Failed to apply patch. Could not find a unique anchor in the source file, even after trimming ambiguous tokens. Last known error: ${lastError?.message}`,
|
|
299
|
+
);
|
|
300
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { findAllSequences, tokensEqual, formatAnchor } from './tokens';
|
|
2
|
+
import type { Token } from './types';
|
|
3
|
+
|
|
4
|
+
// A helper to create mock tokens for testing
|
|
5
|
+
const makeTokens = (texts: string[]): Token[] => {
|
|
6
|
+
let startIndex = 0;
|
|
7
|
+
return texts.map((text) => {
|
|
8
|
+
const token: Token = {
|
|
9
|
+
text,
|
|
10
|
+
type: 'identifier', // type and positions are not important for these tests
|
|
11
|
+
startIndex: startIndex,
|
|
12
|
+
endIndex: startIndex + text.length,
|
|
13
|
+
startPosition: { row: 0, column: startIndex },
|
|
14
|
+
};
|
|
15
|
+
startIndex += text.length + 1; // +1 for space
|
|
16
|
+
return token;
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
describe('token-utils', () => {
|
|
21
|
+
describe('findAllSequences', () => {
|
|
22
|
+
it('should find a single unique sequence', () => {
|
|
23
|
+
const haystack = makeTokens(['a', 'b', 'c', 'd', 'e']);
|
|
24
|
+
const needle = makeTokens(['b', 'c']);
|
|
25
|
+
const indices = findAllSequences(haystack, needle);
|
|
26
|
+
expect(indices).toEqual([1]);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('should find multiple occurrences of a sequence', () => {
|
|
30
|
+
const haystack = makeTokens(['a', 'b', 'c', 'a', 'b', 'c']);
|
|
31
|
+
const needle = makeTokens(['a', 'b', 'c']);
|
|
32
|
+
const indices = findAllSequences(haystack, needle);
|
|
33
|
+
expect(indices).toEqual([0, 3]);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('should return an empty array if sequence is not found', () => {
|
|
37
|
+
const haystack = makeTokens(['a', 'b', 'c']);
|
|
38
|
+
const needle = makeTokens(['d', 'e']);
|
|
39
|
+
const indices = findAllSequences(haystack, needle);
|
|
40
|
+
expect(indices).toEqual([]);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('should return an empty array for an empty needle', () => {
|
|
44
|
+
const haystack = makeTokens(['a', 'b', 'c']);
|
|
45
|
+
const needle = makeTokens([]);
|
|
46
|
+
const indices = findAllSequences(haystack, needle);
|
|
47
|
+
expect(indices).toEqual([]);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('should handle sequences at the beginning and end of haystack', () => {
|
|
51
|
+
const haystack = makeTokens(['a', 'b', 'c', 'd', 'a', 'b']);
|
|
52
|
+
const needleAtStart = makeTokens(['a', 'b']);
|
|
53
|
+
const needleAtEnd = makeTokens(['a', 'b']);
|
|
54
|
+
expect(findAllSequences(haystack, needleAtStart)).toEqual([0, 4]);
|
|
55
|
+
expect(findAllSequences(haystack, needleAtEnd)).toEqual([0, 4]);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
describe('tokensEqual', () => {
|
|
60
|
+
it('should return true for tokens with same text', () => {
|
|
61
|
+
const tokenA = makeTokens(['hello'])[0];
|
|
62
|
+
const tokenB = makeTokens(['hello'])[0];
|
|
63
|
+
expect(tokensEqual(tokenA, tokenB)).toBe(true);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('should return false for tokens with different text', () => {
|
|
67
|
+
const tokenA = makeTokens(['hello'])[0];
|
|
68
|
+
const tokenB = makeTokens(['world'])[0];
|
|
69
|
+
expect(tokensEqual(tokenA, tokenB)).toBe(false);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
describe('formatAnchor', () => {
|
|
74
|
+
it('should format an anchor to a space-separated string', () => {
|
|
75
|
+
const anchor = makeTokens(['const', 'x', '=', '1', ';']);
|
|
76
|
+
expect(formatAnchor(anchor)).toBe('const x = 1 ;');
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('should return an empty string for an empty anchor', () => {
|
|
80
|
+
const anchor = makeTokens([]);
|
|
81
|
+
expect(formatAnchor(anchor)).toBe('');
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
});
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { Tree, Node } from 'web-tree-sitter';
|
|
2
|
+
import type { Token } from './types';
|
|
3
|
+
|
|
4
|
+
export function collectTokens(tree: Tree, code: string): Token[] {
|
|
5
|
+
const tokens: Token[] = [];
|
|
6
|
+
|
|
7
|
+
function visit(node: Node) {
|
|
8
|
+
if (node.childCount === 0) {
|
|
9
|
+
tokens.push({
|
|
10
|
+
text: code.slice(node.startIndex, node.endIndex),
|
|
11
|
+
type: node.type,
|
|
12
|
+
startIndex: node.startIndex,
|
|
13
|
+
endIndex: node.endIndex,
|
|
14
|
+
startPosition: node.startPosition,
|
|
15
|
+
});
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
// By iterating over all children (not just named), we include punctuation
|
|
19
|
+
// which is critical for anchor-based matching.
|
|
20
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
21
|
+
const child = node.child(i);
|
|
22
|
+
if (child) visit(child);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
visit(tree.rootNode);
|
|
27
|
+
return tokens;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function tokensEqual(a: Token, b: Token): boolean {
|
|
31
|
+
return a.text === b.text;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function formatAnchor(anchor: Token[]): string {
|
|
35
|
+
return anchor.map((t) => t.text).join(' ');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function findAllSequences(haystack: Token[], needle: Token[]): number[] {
|
|
39
|
+
if (needle.length === 0) return [];
|
|
40
|
+
const indices: number[] = [];
|
|
41
|
+
outer: for (let i = 0; i <= haystack.length - needle.length; i++) {
|
|
42
|
+
for (let j = 0; j < needle.length; j++) {
|
|
43
|
+
if (!tokensEqual(haystack[i + j], needle[j])) {
|
|
44
|
+
continue outer;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
indices.push(i);
|
|
48
|
+
}
|
|
49
|
+
return indices;
|
|
50
|
+
}
|