repoburg 1.3.8 → 1.3.10

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.
Files changed (230) hide show
  1. package/backend/dist/bin/grammar/tree-sitter-bash.wasm +0 -0
  2. package/backend/dist/bin/grammar/tree-sitter-css.wasm +0 -0
  3. package/backend/dist/bin/grammar/tree-sitter-html.wasm +0 -0
  4. package/backend/dist/bin/grammar/tree-sitter-javascript.wasm +0 -0
  5. package/backend/dist/bin/grammar/tree-sitter-json.wasm +0 -0
  6. package/backend/dist/bin/grammar/tree-sitter-python.wasm +0 -0
  7. package/backend/dist/bin/grammar/tree-sitter-rust.wasm +0 -0
  8. package/backend/dist/bin/grammar/tree-sitter-toml.wasm +0 -0
  9. package/backend/dist/bin/grammar/tree-sitter-tsx.wasm +0 -0
  10. package/backend/dist/bin/grammar/tree-sitter-typescript.wasm +0 -0
  11. package/backend/dist/bin/grammar/tree-sitter-yaml.wasm +0 -0
  12. package/backend/dist/packages/tokenpatch/index.d.ts +1 -0
  13. package/backend/dist/packages/tokenpatch/index.js +52 -0
  14. package/backend/dist/packages/tokenpatch/index.js.map +1 -0
  15. package/backend/dist/packages/tokenpatch/parser.d.ts +2 -0
  16. package/backend/dist/packages/tokenpatch/parser.js +17 -0
  17. package/backend/dist/packages/tokenpatch/parser.js.map +1 -0
  18. package/backend/dist/packages/tokenpatch/patcher.d.ts +11 -0
  19. package/backend/dist/packages/tokenpatch/patcher.js +189 -0
  20. package/backend/dist/packages/tokenpatch/patcher.js.map +1 -0
  21. package/backend/dist/packages/tokenpatch/tokens.d.ts +6 -0
  22. package/backend/dist/packages/tokenpatch/tokens.js +49 -0
  23. package/backend/dist/packages/tokenpatch/tokens.js.map +1 -0
  24. package/backend/dist/packages/tokenpatch/types.d.ts +8 -0
  25. package/backend/dist/packages/tokenpatch/types.js +3 -0
  26. package/backend/dist/packages/tokenpatch/types.js.map +1 -0
  27. package/backend/dist/src/ai-actions/ai-actions.service.d.ts +1 -0
  28. package/backend/dist/src/ai-actions/ai-actions.service.js +2 -0
  29. package/backend/dist/src/ai-actions/ai-actions.service.js.map +1 -1
  30. package/backend/dist/src/llm-orchestration/action-handlers/apply-diff.handler.js +6 -3
  31. package/backend/dist/src/llm-orchestration/action-handlers/apply-diff.handler.js.map +1 -1
  32. package/backend/dist/src/llm-orchestration/action-handlers/dto/patch.args.dto.d.ts +4 -0
  33. package/backend/dist/src/llm-orchestration/action-handlers/dto/patch.args.dto.js +29 -0
  34. package/backend/dist/src/llm-orchestration/action-handlers/dto/patch.args.dto.js.map +1 -0
  35. package/backend/dist/src/llm-orchestration/action-handlers/patch.handler.d.ts +12 -0
  36. package/backend/dist/src/llm-orchestration/action-handlers/patch.handler.js +142 -0
  37. package/backend/dist/src/llm-orchestration/action-handlers/patch.handler.js.map +1 -0
  38. package/backend/dist/src/llm-orchestration/llm-orchestration.module.js +2 -0
  39. package/backend/dist/src/llm-orchestration/llm-orchestration.module.js.map +1 -1
  40. package/backend/dist/src/llm-orchestration/llm-turn-processor.service.js +1 -0
  41. package/backend/dist/src/llm-orchestration/llm-turn-processor.service.js.map +1 -1
  42. package/backend/dist/src/seeding/data/system-prompts/experimental_master-agent.d.ts +1 -1
  43. package/backend/dist/src/seeding/data/system-prompts/experimental_master-agent.js +13 -13
  44. package/backend/dist/src/seeding/data/system-prompts/experimental_patch_master-agent.d.ts +2 -0
  45. package/backend/dist/src/seeding/data/system-prompts/experimental_patch_master-agent.js +463 -0
  46. package/backend/dist/src/seeding/data/system-prompts/experimental_patch_master-agent.js.map +1 -0
  47. package/backend/dist/tsconfig.build.tsbuildinfo +1 -1
  48. package/backend/package.json +6 -3
  49. package/backend/packages/tokenpatch/grammar/tree-sitter-tsx.wasm +0 -0
  50. package/backend/packages/tokenpatch/grammar/tree-sitter-typescript.wasm +0 -0
  51. package/backend/packages/tokenpatch/index.spec.ts +579 -0
  52. package/backend/packages/tokenpatch/index.ts +80 -0
  53. package/backend/packages/tokenpatch/parser.ts +18 -0
  54. package/backend/packages/tokenpatch/patcher.spec.ts +194 -0
  55. package/backend/packages/tokenpatch/patcher.ts +300 -0
  56. package/backend/packages/tokenpatch/tokens.spec.ts +84 -0
  57. package/backend/packages/tokenpatch/tokens.ts +50 -0
  58. package/backend/packages/tokenpatch/types.ts +9 -0
  59. package/package.json +13 -12
  60. package/backend/coverage/clover.xml +0 -3434
  61. package/backend/coverage/coverage-final.json +0 -120
  62. package/backend/coverage/lcov-report/base.css +0 -224
  63. package/backend/coverage/lcov-report/block-navigation.js +0 -87
  64. package/backend/coverage/lcov-report/favicon.png +0 -0
  65. package/backend/coverage/lcov-report/index.html +0 -701
  66. package/backend/coverage/lcov-report/prettify.css +0 -1
  67. package/backend/coverage/lcov-report/prettify.js +0 -2
  68. package/backend/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  69. package/backend/coverage/lcov-report/sorter.js +0 -196
  70. package/backend/coverage/lcov-report/src/action-execution/action-execution.module.ts.html +0 -109
  71. package/backend/coverage/lcov-report/src/action-execution/action-execution.service.ts.html +0 -448
  72. package/backend/coverage/lcov-report/src/action-execution/index.html +0 -131
  73. package/backend/coverage/lcov-report/src/ai-actions/ai-action-batch.service.ts.html +0 -940
  74. package/backend/coverage/lcov-report/src/ai-actions/ai-action-creation.service.ts.html +0 -1243
  75. package/backend/coverage/lcov-report/src/ai-actions/ai-actions.controller.ts.html +0 -664
  76. package/backend/coverage/lcov-report/src/ai-actions/ai-actions.module.ts.html +0 -154
  77. package/backend/coverage/lcov-report/src/ai-actions/ai-actions.service.ts.html +0 -859
  78. package/backend/coverage/lcov-report/src/ai-actions/index.html +0 -176
  79. package/backend/coverage/lcov-report/src/app.controller.ts.html +0 -151
  80. package/backend/coverage/lcov-report/src/app.module.ts.html +0 -373
  81. package/backend/coverage/lcov-report/src/app.service.ts.html +0 -196
  82. package/backend/coverage/lcov-report/src/application-state/application-state.controller.ts.html +0 -319
  83. package/backend/coverage/lcov-report/src/application-state/application-state.module.ts.html +0 -124
  84. package/backend/coverage/lcov-report/src/application-state/application-state.service.ts.html +0 -439
  85. package/backend/coverage/lcov-report/src/application-state/dto/index.html +0 -161
  86. package/backend/coverage/lcov-report/src/application-state/dto/set-auto-context-fetch-enabled.dto.ts.html +0 -103
  87. package/backend/coverage/lcov-report/src/application-state/dto/set-orchestration-timeout.dto.ts.html +0 -103
  88. package/backend/coverage/lcov-report/src/application-state/dto/set-theme.dto.ts.html +0 -106
  89. package/backend/coverage/lcov-report/src/application-state/dto/set-websocket-enabled.dto.ts.html +0 -103
  90. package/backend/coverage/lcov-report/src/application-state/index.html +0 -146
  91. package/backend/coverage/lcov-report/src/context-generation/context-generation.module.ts.html +0 -118
  92. package/backend/coverage/lcov-report/src/context-generation/context-generation.service.ts.html +0 -1348
  93. package/backend/coverage/lcov-report/src/context-generation/index.html +0 -131
  94. package/backend/coverage/lcov-report/src/context-snippets/context-snippets.controller.ts.html +0 -289
  95. package/backend/coverage/lcov-report/src/context-snippets/context-snippets.module.ts.html +0 -136
  96. package/backend/coverage/lcov-report/src/context-snippets/context-snippets.service.ts.html +0 -400
  97. package/backend/coverage/lcov-report/src/context-snippets/dto/context-snippet.dto.ts.html +0 -211
  98. package/backend/coverage/lcov-report/src/context-snippets/dto/index.html +0 -116
  99. package/backend/coverage/lcov-report/src/context-snippets/index.html +0 -146
  100. package/backend/coverage/lcov-report/src/context-templates/context-templates.controller.ts.html +0 -397
  101. package/backend/coverage/lcov-report/src/context-templates/context-templates.module.ts.html +0 -136
  102. package/backend/coverage/lcov-report/src/context-templates/context-templates.service.ts.html +0 -835
  103. package/backend/coverage/lcov-report/src/context-templates/dto/context-template.dto.ts.html +0 -358
  104. package/backend/coverage/lcov-report/src/context-templates/dto/index.html +0 -116
  105. package/backend/coverage/lcov-report/src/context-templates/index.html +0 -146
  106. package/backend/coverage/lcov-report/src/core-entities/ai-action.entity.ts.html +0 -241
  107. package/backend/coverage/lcov-report/src/core-entities/application-state.entity.ts.html +0 -115
  108. package/backend/coverage/lcov-report/src/core-entities/base.entity.ts.html +0 -145
  109. package/backend/coverage/lcov-report/src/core-entities/context-snippet.entity.ts.html +0 -130
  110. package/backend/coverage/lcov-report/src/core-entities/context-template.entity.ts.html +0 -223
  111. package/backend/coverage/lcov-report/src/core-entities/custom-snippet.entity.ts.html +0 -136
  112. package/backend/coverage/lcov-report/src/core-entities/execution-log.entity.ts.html +0 -157
  113. package/backend/coverage/lcov-report/src/core-entities/index.html +0 -281
  114. package/backend/coverage/lcov-report/src/core-entities/index.ts.html +0 -118
  115. package/backend/coverage/lcov-report/src/core-entities/project.entity.ts.html +0 -130
  116. package/backend/coverage/lcov-report/src/core-entities/session-input.entity.ts.html +0 -289
  117. package/backend/coverage/lcov-report/src/core-entities/session.entity.ts.html +0 -280
  118. package/backend/coverage/lcov-report/src/core-entities/system-prompt.entity.ts.html +0 -148
  119. package/backend/coverage/lcov-report/src/custom-snippets/custom-snippets.controller.ts.html +0 -277
  120. package/backend/coverage/lcov-report/src/custom-snippets/custom-snippets.module.ts.html +0 -124
  121. package/backend/coverage/lcov-report/src/custom-snippets/custom-snippets.service.ts.html +0 -304
  122. package/backend/coverage/lcov-report/src/custom-snippets/dto/custom-snippet.dto.ts.html +0 -205
  123. package/backend/coverage/lcov-report/src/custom-snippets/dto/index.html +0 -116
  124. package/backend/coverage/lcov-report/src/custom-snippets/index.html +0 -146
  125. package/backend/coverage/lcov-report/src/events/events.gateway.ts.html +0 -292
  126. package/backend/coverage/lcov-report/src/events/events.module.ts.html +0 -109
  127. package/backend/coverage/lcov-report/src/events/index.html +0 -131
  128. package/backend/coverage/lcov-report/src/execution-logs/dto/execution-log.dto.ts.html +0 -130
  129. package/backend/coverage/lcov-report/src/execution-logs/dto/index.html +0 -116
  130. package/backend/coverage/lcov-report/src/execution-logs/execution-logs.controller.ts.html +0 -130
  131. package/backend/coverage/lcov-report/src/execution-logs/execution-logs.module.ts.html +0 -124
  132. package/backend/coverage/lcov-report/src/execution-logs/execution-logs.service.ts.html +0 -238
  133. package/backend/coverage/lcov-report/src/execution-logs/index.html +0 -146
  134. package/backend/coverage/lcov-report/src/http-exception.filter.ts.html +0 -340
  135. package/backend/coverage/lcov-report/src/index.html +0 -191
  136. package/backend/coverage/lcov-report/src/llm-response-parser/dto/ai-action.dto.ts.html +0 -400
  137. package/backend/coverage/lcov-report/src/llm-response-parser/dto/index.html +0 -116
  138. package/backend/coverage/lcov-report/src/llm-response-parser/errors/index.html +0 -116
  139. package/backend/coverage/lcov-report/src/llm-response-parser/errors/parsing.error.ts.html +0 -118
  140. package/backend/coverage/lcov-report/src/llm-response-parser/index.html +0 -146
  141. package/backend/coverage/lcov-report/src/llm-response-parser/llm-response-parser.module.ts.html +0 -109
  142. package/backend/coverage/lcov-report/src/llm-response-parser/llm-response-parser.service.ts.html +0 -808
  143. package/backend/coverage/lcov-report/src/llm-response-parser/parsing.constants.ts.html +0 -139
  144. package/backend/coverage/lcov-report/src/llm-responses/dto/index.html +0 -116
  145. package/backend/coverage/lcov-report/src/llm-responses/dto/submit-llm-response.dto.ts.html +0 -172
  146. package/backend/coverage/lcov-report/src/llm-responses/index.html +0 -146
  147. package/backend/coverage/lcov-report/src/llm-responses/llm-responses.controller.ts.html +0 -154
  148. package/backend/coverage/lcov-report/src/llm-responses/llm-responses.module.ts.html +0 -166
  149. package/backend/coverage/lcov-report/src/llm-responses/llm-responses.service.ts.html +0 -787
  150. package/backend/coverage/lcov-report/src/main.ts.html +0 -382
  151. package/backend/coverage/lcov-report/src/orchestration/dto/index.html +0 -116
  152. package/backend/coverage/lcov-report/src/orchestration/dto/orchestration.dto.ts.html +0 -169
  153. package/backend/coverage/lcov-report/src/orchestration/index.html +0 -191
  154. package/backend/coverage/lcov-report/src/orchestration/orchestration-fs.service.ts.html +0 -595
  155. package/backend/coverage/lcov-report/src/orchestration/orchestration-parser.service.ts.html +0 -142
  156. package/backend/coverage/lcov-report/src/orchestration/orchestration.controller.ts.html +0 -406
  157. package/backend/coverage/lcov-report/src/orchestration/orchestration.module.ts.html +0 -169
  158. package/backend/coverage/lcov-report/src/orchestration/orchestration.service.ts.html +0 -1093
  159. package/backend/coverage/lcov-report/src/orchestration/orchestration.types.ts.html +0 -175
  160. package/backend/coverage/lcov-report/src/projects/dto/index.html +0 -116
  161. package/backend/coverage/lcov-report/src/projects/dto/project.dto.ts.html +0 -154
  162. package/backend/coverage/lcov-report/src/projects/index.html +0 -146
  163. package/backend/coverage/lcov-report/src/projects/projects.controller.ts.html +0 -232
  164. package/backend/coverage/lcov-report/src/projects/projects.module.ts.html +0 -124
  165. package/backend/coverage/lcov-report/src/projects/projects.service.ts.html +0 -223
  166. package/backend/coverage/lcov-report/src/seeding/context-template-seeding.service.ts.html +0 -355
  167. package/backend/coverage/lcov-report/src/seeding/custom-snippet-seeding.service.ts.html +0 -271
  168. package/backend/coverage/lcov-report/src/seeding/data/context-templates/default-followup_ad-hoc-focused-context.ts.html +0 -136
  169. package/backend/coverage/lcov-report/src/seeding/data/context-templates/default-initial_condensed-project-context.ts.html +0 -148
  170. package/backend/coverage/lcov-report/src/seeding/data/context-templates/default-initial_full-project-context.ts.html +0 -247
  171. package/backend/coverage/lcov-report/src/seeding/data/context-templates/index.html +0 -190
  172. package/backend/coverage/lcov-report/src/seeding/data/context-templates/pm-context.ts.html +0 -250
  173. package/backend/coverage/lcov-report/src/seeding/data/context-templates/pr-description.ts.html +0 -186
  174. package/backend/coverage/lcov-report/src/seeding/data/context-templates/sample_focused-tree.ts.html +0 -124
  175. package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/default_rglob.ts.html +0 -94
  176. package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/git-diff.ts.html +0 -94
  177. package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/index.html +0 -236
  178. package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/rg-exclude.ts.html +0 -94
  179. package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/rg-search-glob.ts.html +0 -94
  180. package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/rg-search.ts.html +0 -94
  181. package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/run-command.ts.html +0 -94
  182. package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/tree.ts.html +0 -94
  183. package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/usr-adhoc-incl.ts.html +0 -100
  184. package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/usr-input-incl.ts.html +0 -94
  185. package/backend/coverage/lcov-report/src/seeding/data/system-prompts/codebase-explorer.ts.html +0 -331
  186. package/backend/coverage/lcov-report/src/seeding/data/system-prompts/default_multi-file-action-generator-with-requester.ts.html +0 -675
  187. package/backend/coverage/lcov-report/src/seeding/data/system-prompts/index.html +0 -160
  188. package/backend/coverage/lcov-report/src/seeding/data/system-prompts/multi-file-action-generator.ts.html +0 -550
  189. package/backend/coverage/lcov-report/src/seeding/data/system-prompts/packup.ts.html +0 -184
  190. package/backend/coverage/lcov-report/src/seeding/data/system-prompts/refactor-split.ts.html +0 -244
  191. package/backend/coverage/lcov-report/src/seeding/index.html +0 -176
  192. package/backend/coverage/lcov-report/src/seeding/seeding.module.ts.html +0 -145
  193. package/backend/coverage/lcov-report/src/seeding/seeding.service.ts.html +0 -151
  194. package/backend/coverage/lcov-report/src/seeding/system-prompt-seeding.service.ts.html +0 -289
  195. package/backend/coverage/lcov-report/src/session-followup/index.html +0 -131
  196. package/backend/coverage/lcov-report/src/session-followup/session-followup.module.ts.html +0 -130
  197. package/backend/coverage/lcov-report/src/session-followup/session-followup.service.ts.html +0 -670
  198. package/backend/coverage/lcov-report/src/session-inputs/dto/index.html +0 -116
  199. package/backend/coverage/lcov-report/src/session-inputs/dto/session-input.dto.ts.html +0 -247
  200. package/backend/coverage/lcov-report/src/session-inputs/index.html +0 -161
  201. package/backend/coverage/lcov-report/src/session-inputs/session-input-context.service.ts.html +0 -763
  202. package/backend/coverage/lcov-report/src/session-inputs/session-inputs.controller.ts.html +0 -337
  203. package/backend/coverage/lcov-report/src/session-inputs/session-inputs.module.ts.html +0 -205
  204. package/backend/coverage/lcov-report/src/session-inputs/session-inputs.service.ts.html +0 -1621
  205. package/backend/coverage/lcov-report/src/session-transfer/index.html +0 -131
  206. package/backend/coverage/lcov-report/src/session-transfer/session-transfer.module.ts.html +0 -172
  207. package/backend/coverage/lcov-report/src/session-transfer/session-transfer.service.ts.html +0 -574
  208. package/backend/coverage/lcov-report/src/sessions/dto/index.html +0 -116
  209. package/backend/coverage/lcov-report/src/sessions/dto/session.dto.ts.html +0 -340
  210. package/backend/coverage/lcov-report/src/sessions/index.html +0 -146
  211. package/backend/coverage/lcov-report/src/sessions/sessions.controller.ts.html +0 -457
  212. package/backend/coverage/lcov-report/src/sessions/sessions.module.ts.html +0 -214
  213. package/backend/coverage/lcov-report/src/sessions/sessions.service.ts.html +0 -844
  214. package/backend/coverage/lcov-report/src/system-prompts/dto/index.html +0 -116
  215. package/backend/coverage/lcov-report/src/system-prompts/dto/system-prompt.dto.ts.html +0 -217
  216. package/backend/coverage/lcov-report/src/system-prompts/index.html +0 -146
  217. package/backend/coverage/lcov-report/src/system-prompts/system-prompts.controller.ts.html +0 -298
  218. package/backend/coverage/lcov-report/src/system-prompts/system-prompts.module.ts.html +0 -127
  219. package/backend/coverage/lcov-report/src/system-prompts/system-prompts.service.ts.html +0 -352
  220. package/backend/coverage/lcov-report/src/timeout.interceptor.ts.html +0 -178
  221. package/backend/coverage/lcov-report/src/utils/fuzzy-search.ts.html +0 -310
  222. package/backend/coverage/lcov-report/src/utils/index.html +0 -131
  223. package/backend/coverage/lcov-report/src/utils/index.ts.html +0 -88
  224. package/backend/coverage/lcov-report/src/workspace/dto/index.html +0 -116
  225. package/backend/coverage/lcov-report/src/workspace/dto/search-workspace.dto.ts.html +0 -193
  226. package/backend/coverage/lcov-report/src/workspace/index.html +0 -146
  227. package/backend/coverage/lcov-report/src/workspace/workspace.controller.ts.html +0 -247
  228. package/backend/coverage/lcov-report/src/workspace/workspace.module.ts.html +0 -121
  229. package/backend/coverage/lcov-report/src/workspace/workspace.service.ts.html +0 -745
  230. package/backend/coverage/lcov.info +0 -5590
@@ -13,7 +13,7 @@
13
13
  "start:debug": "nest start --debug --watch",
14
14
  "start:prod": "NODE_ENV=production node dist/main",
15
15
  "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
16
- "test": "jest --bail",
16
+ "test": "NODE_OPTIONS=--experimental-vm-modules jest --bail",
17
17
  "test:watch": "jest --watch",
18
18
  "test:cov": "jest --coverage",
19
19
  "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
@@ -57,7 +57,10 @@
57
57
  "json",
58
58
  "ts"
59
59
  ],
60
- "rootDir": "src",
60
+ "roots": [
61
+ "<rootDir>/src",
62
+ "<rootDir>/packages"
63
+ ],
61
64
  "testRegex": ".*\\.spec\\.ts$",
62
65
  "transform": {
63
66
  "^.+\\.(t|j)s$": "ts-jest"
@@ -65,7 +68,7 @@
65
68
  "collectCoverageFrom": [
66
69
  "**/*.(t|j)s"
67
70
  ],
68
- "coverageDirectory": "../coverage",
71
+ "coverageDirectory": "coverage",
69
72
  "testEnvironment": "node"
70
73
  }
71
74
  }
@@ -0,0 +1,579 @@
1
+ import { applySnippetPatch } from './index';
2
+ import * as path from 'path';
3
+
4
+ const TS_WASM_PATH = path.join(
5
+ __dirname,
6
+ './grammar/tree-sitter-typescript.wasm',
7
+ );
8
+
9
+ const TSX_WASM_PATH = path.join(__dirname, './grammar/tree-sitter-tsx.wasm');
10
+
11
+ // Helper to normalize whitespace for robust comparison
12
+ const normalize = (str: string) => str.replace(/\s+/g, ' ').trim();
13
+
14
+ describe('applySnippetPatch', () => {
15
+ it('should replace a method body in a class by automatically finding anchor size', async () => {
16
+ const sourceCode = `
17
+ class Greeter {
18
+ greet() {
19
+ return "Hello, world";
20
+ }
21
+
22
+ fc(){ return 42; }
23
+ }
24
+ `;
25
+ const patchCode = `
26
+ greet() {
27
+ // A new implementation
28
+ return "Hello, TypeScript!";
29
+ }
30
+ fc(){
31
+ `;
32
+ const expectedResult = `
33
+ class Greeter {
34
+ greet() {
35
+ // A new implementation
36
+ return "Hello, TypeScript!";
37
+ }
38
+ fc(){ return 42; }
39
+
40
+ }
41
+ `;
42
+ const result = await applySnippetPatch(sourceCode, patchCode, TS_WASM_PATH);
43
+ expect(normalize(result)).toEqual(normalize(expectedResult));
44
+ });
45
+
46
+ it('should replace a data structure definition', async () => {
47
+ const sourceCode = `
48
+ interface MyData {
49
+ field1: string;
50
+ }
51
+ console.log("hello");
52
+ `;
53
+ const patchCode = `
54
+ interface MyData {
55
+ field1: number;
56
+ field2: boolean;
57
+ }
58
+ `;
59
+ const expectedResult = `
60
+ interface MyData {
61
+ field1: number;
62
+ field2: boolean;
63
+ }
64
+ console.log("hello");
65
+ `;
66
+ const result = await applySnippetPatch(sourceCode, patchCode, TS_WASM_PATH);
67
+ expect(normalize(result)).toEqual(normalize(expectedResult));
68
+ });
69
+
70
+ it('should replace a full function definition', async () => {
71
+ const sourceCode = `
72
+ import fs from 'fs';
73
+
74
+ function calculate() {
75
+ return 1 + 1;
76
+ }
77
+
78
+ export { calculate };
79
+ `;
80
+ const patchCode = `
81
+ function calculate() {
82
+ // A more complex calculation
83
+ const result = 2 * 2;
84
+ return result;
85
+ }
86
+ `;
87
+ const expectedResult = `
88
+ import fs from 'fs';
89
+
90
+ function calculate() {
91
+ // A more complex calculation
92
+ const result = 2 * 2;
93
+ return result;
94
+ }
95
+
96
+ export { calculate };
97
+ `;
98
+ const result = await applySnippetPatch(sourceCode, patchCode, TS_WASM_PATH);
99
+ expect(normalize(result)).toEqual(normalize(expectedResult));
100
+ });
101
+
102
+ it('should replace a beginning of the file @begin-of-file', async () => {
103
+ const sourceCode = `
104
+ import { ModuleA } from './moduleA';
105
+ import { ModuleB } from './moduleB';
106
+
107
+ console.log('starting up');
108
+ `;
109
+ const patchCode = `
110
+ // @begin-of-file
111
+ import groupBy from 'lodash';
112
+ import { ModuleA } from './moduleA';
113
+ `;
114
+ const expectedResult = `
115
+ import groupBy from 'lodash';
116
+ import { ModuleA } from './moduleA';
117
+ import { ModuleB } from './moduleB';
118
+
119
+ console.log('starting up');
120
+ `;
121
+ const result = await applySnippetPatch(sourceCode, patchCode, TS_WASM_PATH);
122
+ expect(normalize(result)).toEqual(normalize(expectedResult));
123
+ });
124
+
125
+ it('should handle @begin-of-file marker with variations', async () => {
126
+ const sourceCode = `
127
+ import { ModuleA } from './moduleA';
128
+ import { ModuleB } from './moduleB';
129
+
130
+ console.log('starting up');
131
+ `;
132
+ const patchCode = `
133
+ //@begin-of-file extra text
134
+ import groupBy from 'lodash';
135
+ import { ModuleA } from './moduleA';
136
+ `;
137
+ const expectedResult = `
138
+ import groupBy from 'lodash';
139
+ import { ModuleA } from './moduleA';
140
+ import { ModuleB } from './moduleB';
141
+
142
+ console.log('starting up');
143
+ `;
144
+ const result = await applySnippetPatch(sourceCode, patchCode, TS_WASM_PATH);
145
+ expect(normalize(result)).toEqual(normalize(expectedResult));
146
+ });
147
+
148
+ it('should replace a end of the file @end-of-file', async () => {
149
+ const sourceCode = `
150
+ import fs from 'fs';
151
+
152
+ function calculate() {
153
+ return 1 + 1;
154
+ }
155
+
156
+ export { calculate };
157
+ `;
158
+ const patchCode = `
159
+ export { calculate };
160
+ export { sum };
161
+ // @end-of-file
162
+ `;
163
+ const expectedResult = `
164
+ import fs from 'fs';
165
+
166
+ function calculate() {
167
+ return 1 + 1;
168
+ }
169
+
170
+ export { calculate };
171
+ export { sum };
172
+ `;
173
+ const result = await applySnippetPatch(sourceCode, patchCode, TS_WASM_PATH);
174
+ expect(normalize(result)).toEqual(normalize(expectedResult));
175
+ });
176
+
177
+ it('should handle @end-of-file marker with variations', async () => {
178
+ const sourceCode = `
179
+ import fs from 'fs';
180
+
181
+ function calculate() {
182
+ return 1 + 1;
183
+ }
184
+
185
+ export { calculate };
186
+ `;
187
+ const patchCode = `
188
+ export { calculate };
189
+ export { sum };
190
+ //@end-of-file some extra text
191
+ `;
192
+ const expectedResult = `
193
+ import fs from 'fs';
194
+
195
+ function calculate() {
196
+ return 1 + 1;
197
+ }
198
+
199
+ export { calculate };
200
+ export { sum };
201
+ `;
202
+ const result = await applySnippetPatch(sourceCode, patchCode, TS_WASM_PATH);
203
+ expect(normalize(result)).toEqual(normalize(expectedResult));
204
+ });
205
+ it('should succeed with dynamic anchor sizing when initial anchors are ambiguous', async () => {
206
+ const sourceCode = `
207
+ const config = {
208
+ port: 8080,
209
+ host: 'localhost',
210
+ };
211
+
212
+ function connect() {
213
+ // uses config
214
+ }
215
+
216
+ const config2 = {
217
+ port: 3000,
218
+ host: 'remote',
219
+ };
220
+ `;
221
+ const patchCode = `
222
+ const config = {
223
+ port: 9000,
224
+ host: 'localhost',
225
+ protocol: 'https'
226
+ };
227
+
228
+ function connect() {
229
+ `;
230
+ const expectedResult = `
231
+ const config = {
232
+ port: 9000,
233
+ host: 'localhost',
234
+ protocol: 'https'
235
+ };
236
+
237
+ function connect() {
238
+ // uses config
239
+ }
240
+
241
+ const config2 = {
242
+ port: 3000,
243
+ host: 'remote',
244
+ };
245
+ `;
246
+ const result = await applySnippetPatch(sourceCode, patchCode, TS_WASM_PATH);
247
+ expect(normalize(result)).toEqual(normalize(expectedResult));
248
+ });
249
+
250
+ it('should handle partial type definitions by trimming ambiguous tokens', async () => {
251
+ const sourceCode = `
252
+ /**
253
+ * Bill date of the vendor bill
254
+ */
255
+ billDate: everest_appserver_primitive_PlainDate;
256
+ billNumber: everest_appserver_primitive_Text;
257
+ businessPartnerId: everest_appserver_primitive_ID;
258
+ /**
259
+ * Conditionally return status or paymentStatus
260
+ */
261
+ combinedStatus?: everest_appserver_primitive_Text | null;
262
+ /**
263
+ * Contains Billable Expense line
264
+ */
265
+ containsBillableItem?: everest_appserver_primitive_TrueFalse | null;
266
+ /**
267
+ * Denotes whether bill type is prepaid or not
268
+ */
269
+ containsPrepaidItem?: everest_appserver_primitive_TrueFalse | null;
270
+ `;
271
+ const patchCode = `
272
+ businessPartnerId: everest_appserver_primitive_ID;
273
+ /**
274
+ * Conditionally return status or paymentStatus
275
+ */
276
+ combinedStatusNew2?: everest_appserver_primitive_Text | null;
277
+ /**
278
+ `;
279
+ const expectedResult = `
280
+ /**
281
+ * Bill date of the vendor bill
282
+ */
283
+ billDate: everest_appserver_primitive_PlainDate;
284
+ billNumber: everest_appserver_primitive_Text;
285
+ businessPartnerId: everest_appserver_primitive_ID;
286
+ /**
287
+ * Conditionally return status or paymentStatus
288
+ */
289
+ combinedStatusNew2?: everest_appserver_primitive_Text | null;
290
+ /**
291
+ * Contains Billable Expense line
292
+ */
293
+ containsBillableItem?: everest_appserver_primitive_TrueFalse | null;
294
+ /**
295
+ * Denotes whether bill type is prepaid or not
296
+ */
297
+ containsPrepaidItem?: everest_appserver_primitive_TrueFalse | null;
298
+ `;
299
+ const result = await applySnippetPatch(sourceCode, patchCode, TS_WASM_PATH);
300
+ expect(normalize(result)).toEqual(normalize(expectedResult));
301
+ });
302
+
303
+ it('should patch TSX correctly by trimming tokens from invalid partial snippets', async () => {
304
+ const sourceCode = `
305
+ import { useEffect, useMemo } from "react"
306
+ import { trpc } from "@/lib/trpc"
307
+
308
+ import { Button } from "@/components/ui/button"
309
+ import { DataTable } from "@/components/ui/data-table"
310
+ import { useReconciliationStore } from "@/store/reconciliation"
311
+
312
+ import {
313
+ getBillColumns,
314
+ getInvoiceColumns,
315
+ getMatchedColumns,
316
+ getTransactionColumns,
317
+ } from "./transactions-columns"
318
+
319
+ export function TransactionsPage() {
320
+ const {
321
+ transactions,
322
+ invoices,
323
+ matchedItems,
324
+ selectedTransactionId,
325
+ selectedMatchableId,
326
+ loadInitialData,
327
+ selectTransaction,
328
+ selectMatchable,
329
+ matchItems,
330
+ unmatchItems,
331
+ } = useReconciliationStore()
332
+ const { data: bills = [] } = trpc.bills.getBills.useQuery()
333
+
334
+ // Load mock data when component mounts
335
+ useEffect(() => {
336
+ loadInitialData()
337
+ }, [loadInitialData])
338
+
339
+ const selectedTransaction =
340
+ transactions.find((t) => t.id === selectedTransactionId) || null
341
+
342
+ const transactionColumns = useMemo(() => getTransactionColumns(), [])
343
+
344
+ const invoiceColumns = useMemo(() => getInvoiceColumns(), [])
345
+
346
+ const billColumns = useMemo(() => getBillColumns(), [])
347
+
348
+ const matchedColumns = useMemo(
349
+ () =>
350
+ getMatchedColumns({
351
+ onUnmatch: unmatchItems,
352
+ }),
353
+ [unmatchItems]
354
+ )
355
+
356
+ const canMatch = selectedTransactionId && selectedMatchableId
357
+
358
+ return (
359
+ <div>
360
+ <div className="flex justify-between items-center mb-4">
361
+ <h2 className="text-2xl font-bold">Transaction Matching</h2>
362
+ <Button onClick={matchItems} disabled={!canMatch}>
363
+ Match Items
364
+ </Button>
365
+ </div>
366
+
367
+ <div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
368
+ {/* Left Panel: Bank Transactions */}
369
+ <div>
370
+ <h3 className="text-lg font-semibold mb-2">Bank Transactions</h3>
371
+ <p className="text-sm text-muted-foreground mb-4">
372
+ Select a transaction to begin matching.
373
+ </p>
374
+ <DataTable
375
+ columns={transactionColumns}
376
+ data={transactions}
377
+ onRowClick={(row) => selectTransaction(row.id)}
378
+ selectedId={selectedTransactionId}
379
+ />
380
+ </div>
381
+
382
+ {/* Right Panel: Matching Items */}
383
+ <div>
384
+ <h3 className="text-lg font-semibold mb-2">Potential Matches</h3>
385
+ {!selectedTransaction ? (
386
+ <div className="h-full flex items-center justify-center rounded-lg border-2 border-dashed border-muted-foreground/30 p-8">
387
+ <p className="text-muted-foreground">
388
+ Select a transaction to see potential matches.
389
+ </p>
390
+ </div>
391
+ ) : selectedTransaction.amount > 0 ? (
392
+ <div>
393
+ <h4 className="text-md font-semibold mb-2 text-muted-foreground">
394
+ Unpaid Invoices
395
+ </h4>
396
+ <DataTable
397
+ columns={invoiceColumns}
398
+ data={invoices}
399
+ onRowClick={(row) => selectMatchable(row.id)}
400
+ selectedId={selectedMatchableId}
401
+ />
402
+ </div>
403
+ ) : (
404
+ <div>
405
+ <h4 className="text-md font-semibold mb-2 text-muted-foreground">
406
+ Unpaid Bills
407
+ </h4>
408
+ <DataTable
409
+ columns={billColumns}
410
+ data={bills}
411
+ onRowClick={(row) => selectMatchable(row.id)}
412
+ selectedId={selectedMatchableId}
413
+ />
414
+ </div>
415
+ )}
416
+ </div>
417
+ </div>
418
+
419
+ {matchedItems.length > 0 && (
420
+ <div className="mt-12">
421
+ <h3 className="text-lg font-semibold mb-2">Matched Transactions</h3>
422
+ <DataTable columns={matchedColumns} data={matchedItems} />
423
+ </div>
424
+ )}
425
+ </div>
426
+ )
427
+ }
428
+ `;
429
+ const patchCode = `
430
+ Unpaid Bills
431
+ </h4>
432
+ <DataTable
433
+ columns={billColumns}
434
+ data={bills}
435
+ onRowClick={(row) => {
436
+ console.log(\`[UI] Selected matchable bill ID\`)
437
+ selectMatchable(row.id)
438
+ }}
439
+ selectedId={selectedMatchableId}
440
+ />
441
+ </div>
442
+ )}
443
+ `;
444
+ const expectedResult = `
445
+ import { useEffect, useMemo } from "react"
446
+ import { trpc } from "@/lib/trpc"
447
+
448
+ import { Button } from "@/components/ui/button"
449
+ import { DataTable } from "@/components/ui/data-table"
450
+ import { useReconciliationStore } from "@/store/reconciliation"
451
+
452
+ import {
453
+ getBillColumns,
454
+ getInvoiceColumns,
455
+ getMatchedColumns,
456
+ getTransactionColumns,
457
+ } from "./transactions-columns"
458
+
459
+ export function TransactionsPage() {
460
+ const {
461
+ transactions,
462
+ invoices,
463
+ matchedItems,
464
+ selectedTransactionId,
465
+ selectedMatchableId,
466
+ loadInitialData,
467
+ selectTransaction,
468
+ selectMatchable,
469
+ matchItems,
470
+ unmatchItems,
471
+ } = useReconciliationStore()
472
+ const { data: bills = [] } = trpc.bills.getBills.useQuery()
473
+
474
+ // Load mock data when component mounts
475
+ useEffect(() => {
476
+ loadInitialData()
477
+ }, [loadInitialData])
478
+
479
+ const selectedTransaction =
480
+ transactions.find((t) => t.id === selectedTransactionId) || null
481
+
482
+ const transactionColumns = useMemo(() => getTransactionColumns(), [])
483
+
484
+ const invoiceColumns = useMemo(() => getInvoiceColumns(), [])
485
+
486
+ const billColumns = useMemo(() => getBillColumns(), [])
487
+
488
+ const matchedColumns = useMemo(
489
+ () =>
490
+ getMatchedColumns({
491
+ onUnmatch: unmatchItems,
492
+ }),
493
+ [unmatchItems]
494
+ )
495
+
496
+ const canMatch = selectedTransactionId && selectedMatchableId
497
+
498
+ return (
499
+ <div>
500
+ <div className="flex justify-between items-center mb-4">
501
+ <h2 className="text-2xl font-bold">Transaction Matching</h2>
502
+ <Button onClick={matchItems} disabled={!canMatch}>
503
+ Match Items
504
+ </Button>
505
+ </div>
506
+
507
+ <div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
508
+ {/* Left Panel: Bank Transactions */}
509
+ <div>
510
+ <h3 className="text-lg font-semibold mb-2">Bank Transactions</h3>
511
+ <p className="text-sm text-muted-foreground mb-4">
512
+ Select a transaction to begin matching.
513
+ </p>
514
+ <DataTable
515
+ columns={transactionColumns}
516
+ data={transactions}
517
+ onRowClick={(row) => selectTransaction(row.id)}
518
+ selectedId={selectedTransactionId}
519
+ />
520
+ </div>
521
+
522
+ {/* Right Panel: Matching Items */}
523
+ <div>
524
+ <h3 className="text-lg font-semibold mb-2">Potential Matches</h3>
525
+ {!selectedTransaction ? (
526
+ <div className="h-full flex items-center justify-center rounded-lg border-2 border-dashed border-muted-foreground/30 p-8">
527
+ <p className="text-muted-foreground">
528
+ Select a transaction to see potential matches.
529
+ </p>
530
+ </div>
531
+ ) : selectedTransaction.amount > 0 ? (
532
+ <div>
533
+ <h4 className="text-md font-semibold mb-2 text-muted-foreground">
534
+ Unpaid Invoices
535
+ </h4>
536
+ <DataTable
537
+ columns={invoiceColumns}
538
+ data={invoices}
539
+ onRowClick={(row) => selectMatchable(row.id)}
540
+ selectedId={selectedMatchableId}
541
+ />
542
+ </div>
543
+ ) : (
544
+ <div>
545
+ <h4 className="text-md font-semibold mb-2 text-muted-foreground">
546
+ Unpaid Bills
547
+ </h4>
548
+ <DataTable
549
+ columns={billColumns}
550
+ data={bills}
551
+ onRowClick={(row) => {
552
+ console.log(\`[UI] Selected matchable bill ID\`)
553
+ selectMatchable(row.id)
554
+ }}
555
+ selectedId={selectedMatchableId}
556
+ />
557
+ </div>
558
+ )}
559
+ </div>
560
+ </div>
561
+
562
+ {matchedItems.length > 0 && (
563
+ <div className="mt-12">
564
+ <h3 className="text-lg font-semibold mb-2">Matched Transactions</h3>
565
+ <DataTable columns={matchedColumns} data={matchedItems} />
566
+ </div>
567
+ )}
568
+ </div>
569
+ )
570
+ }
571
+ `;
572
+ const result = await applySnippetPatch(
573
+ sourceCode,
574
+ patchCode,
575
+ TSX_WASM_PATH,
576
+ );
577
+ expect(normalize(result)).toEqual(normalize(expectedResult));
578
+ });
579
+ });
@@ -0,0 +1,80 @@
1
+ import { initializeParser } from './parser';
2
+ import { collectTokens } from './tokens';
3
+ import {
4
+ handleBeginOfFilePatch,
5
+ handleEndOfFilePatch,
6
+ handleStandardPatch,
7
+ } from './patcher';
8
+
9
+ export async function applySnippetPatch(
10
+ sourceCode: string,
11
+ patchCode: string,
12
+ grammarPath: string,
13
+ ): Promise<string> {
14
+ const parser = await initializeParser(grammarPath);
15
+
16
+ const sourceTree = parser.parse(sourceCode);
17
+ if (!sourceTree) {
18
+ throw new Error('Failed to parse source code.');
19
+ }
20
+ const sourceTokens = collectTokens(sourceTree, sourceCode);
21
+
22
+ let patchResult: {
23
+ replaceStart: number;
24
+ replaceEnd: number;
25
+ patchInsertStart: number;
26
+ patchInsertEnd: number;
27
+ };
28
+ let processedPatchCode = patchCode;
29
+
30
+ const beginOfFileRegex = /\/\/\s*@begin-of-file.*/;
31
+ const endOfFileRegex = /\/\/\s*@end-of-file.*/;
32
+
33
+ const hasBeginOfFile = beginOfFileRegex.test(patchCode);
34
+ const hasEndOfFile = endOfFileRegex.test(patchCode);
35
+
36
+ if (hasBeginOfFile) {
37
+ processedPatchCode = patchCode.replace(beginOfFileRegex, '');
38
+ const patchTree = parser.parse(processedPatchCode);
39
+ if (!patchTree) {
40
+ throw new Error('Failed to parse patch code.');
41
+ }
42
+ const patchTokens = collectTokens(patchTree, processedPatchCode).filter(
43
+ (t) => t.text !== '',
44
+ );
45
+ patchResult = handleBeginOfFilePatch(sourceTokens, patchTokens);
46
+ } else if (hasEndOfFile) {
47
+ processedPatchCode = patchCode.replace(endOfFileRegex, '');
48
+ const patchTree = parser.parse(processedPatchCode);
49
+ if (!patchTree) {
50
+ throw new Error('Failed to parse patch code.');
51
+ }
52
+ const patchTokens = collectTokens(patchTree, processedPatchCode).filter(
53
+ (t) => t.text !== '',
54
+ );
55
+ patchResult = handleEndOfFilePatch(sourceTokens, patchTokens, sourceCode);
56
+ } else {
57
+ processedPatchCode = patchCode.trim();
58
+ const patchTree = parser.parse(processedPatchCode);
59
+ if (!patchTree) {
60
+ throw new Error('Failed to parse patch code.');
61
+ }
62
+ const patchTokens = collectTokens(patchTree, processedPatchCode).filter(
63
+ (t) => t.text !== '',
64
+ );
65
+ patchResult = handleStandardPatch(sourceTokens, patchTokens);
66
+ }
67
+
68
+ // NOTE: replaceStart/End are byte offsets.
69
+ // If your code can contain non-ASCII characters, you need to
70
+ // map byte offsets to JS string indices. For pure ASCII, this
71
+ // works as-is.
72
+ const prefix = sourceCode.slice(0, patchResult.replaceStart);
73
+ const suffix = sourceCode.slice(patchResult.replaceEnd);
74
+ const finalPatchContent = processedPatchCode.slice(
75
+ patchResult.patchInsertStart,
76
+ patchResult.patchInsertEnd,
77
+ );
78
+
79
+ return prefix + finalPatchContent + suffix;
80
+ }
@@ -0,0 +1,18 @@
1
+ // import Parser from 'web-tree-sitter';
2
+
3
+ // Cache parsers by grammar path to avoid re-initialization.
4
+ import { Language, Parser } from 'web-tree-sitter';
5
+
6
+ const parsers = new Map<string, Parser>();
7
+
8
+ export async function initializeParser(grammarPath: string): Promise<Parser> {
9
+ if (parsers.has(grammarPath)) {
10
+ return parsers.get(grammarPath)!;
11
+ }
12
+ await Parser.init();
13
+ const newParser = new Parser();
14
+ const language = await Language.load(grammarPath);
15
+ newParser.setLanguage(language);
16
+ parsers.set(grammarPath, newParser);
17
+ return newParser;
18
+ }