xcoder-dna 0.0.0-stage → 1.3.1

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 (390) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +87 -2
  3. package/dist/agents/ai-chat-debate.d.ts +36 -0
  4. package/dist/agents/ai-chat-debate.js +300 -0
  5. package/dist/agents/ai-chat-report-writer.d.ts +7 -0
  6. package/dist/agents/ai-chat-report-writer.js +100 -0
  7. package/dist/agents/duplicate-detector.d.ts +41 -0
  8. package/dist/agents/duplicate-detector.js +65 -0
  9. package/dist/agents/genesis-agent.d.ts +61 -0
  10. package/dist/agents/genesis-agent.js +340 -0
  11. package/dist/agents/samurai-agent.d.ts +53 -0
  12. package/dist/agents/samurai-agent.js +279 -0
  13. package/dist/agents/sub-agent.d.ts +56 -0
  14. package/dist/agents/sub-agent.js +353 -0
  15. package/dist/backlog/backlog-requirement-validator.d.ts +10 -0
  16. package/dist/backlog/backlog-requirement-validator.js +60 -0
  17. package/dist/backlog/backlog-store.d.ts +29 -0
  18. package/dist/backlog/backlog-store.js +148 -0
  19. package/dist/backlog/po-agent.d.ts +16 -0
  20. package/dist/backlog/po-agent.js +121 -0
  21. package/dist/backlog/types.d.ts +25 -0
  22. package/dist/backlog/types.js +4 -0
  23. package/dist/bench/run.d.ts +11 -0
  24. package/dist/bench/run.js +185 -0
  25. package/dist/bench/types.d.ts +50 -0
  26. package/dist/bench/types.js +1 -0
  27. package/dist/cli/swarm.d.ts +10 -0
  28. package/dist/cli/swarm.js +100 -0
  29. package/dist/cli/task.d.ts +14 -0
  30. package/dist/cli/task.js +121 -0
  31. package/dist/cli/wbc-arg.d.ts +6 -0
  32. package/dist/cli/wbc-arg.js +40 -0
  33. package/dist/cli/wbc.d.ts +45 -0
  34. package/dist/cli/wbc.js +98 -0
  35. package/dist/commands/license.d.ts +9 -0
  36. package/dist/commands/license.js +140 -0
  37. package/dist/commands/release.d.ts +44 -0
  38. package/dist/commands/release.js +180 -0
  39. package/dist/commands/test.d.ts +50 -0
  40. package/dist/commands/test.js +385 -0
  41. package/dist/config/loadConfig.d.ts +82 -0
  42. package/dist/config/loadConfig.js +240 -0
  43. package/dist/config/secure-mode.d.ts +29 -0
  44. package/dist/config/secure-mode.js +63 -0
  45. package/dist/config/user-config.d.ts +39 -0
  46. package/dist/config/user-config.js +202 -0
  47. package/dist/engine/reasoning-engine.d.ts +21 -0
  48. package/dist/engine/reasoning-engine.js +59 -0
  49. package/dist/events/bus.d.ts +22 -0
  50. package/dist/events/bus.js +18 -0
  51. package/dist/index.d.ts +79 -0
  52. package/dist/index.js +77 -0
  53. package/dist/indexing/ignoreRules.d.ts +1 -0
  54. package/dist/indexing/ignoreRules.js +53 -0
  55. package/dist/instance-swarm/instance-swarm-orchestrator.d.ts +57 -0
  56. package/dist/instance-swarm/instance-swarm-orchestrator.js +204 -0
  57. package/dist/instance-swarm/protocol-name-resolver.d.ts +23 -0
  58. package/dist/instance-swarm/protocol-name-resolver.js +64 -0
  59. package/dist/license/gate.d.ts +31 -0
  60. package/dist/license/gate.js +188 -0
  61. package/dist/license/http-client.d.ts +43 -0
  62. package/dist/license/http-client.js +195 -0
  63. package/dist/license/manager.d.ts +39 -0
  64. package/dist/license/manager.js +175 -0
  65. package/dist/license/receipt.d.ts +27 -0
  66. package/dist/license/receipt.js +108 -0
  67. package/dist/license/state-codec.d.ts +72 -0
  68. package/dist/license/state-codec.js +218 -0
  69. package/dist/license/state-paths.d.ts +17 -0
  70. package/dist/license/state-paths.js +64 -0
  71. package/dist/license/store.d.ts +44 -0
  72. package/dist/license/store.js +223 -0
  73. package/dist/license/trust-anchor.d.ts +24 -0
  74. package/dist/license/trust-anchor.js +74 -0
  75. package/dist/license/types.d.ts +34 -0
  76. package/dist/license/types.js +19 -0
  77. package/dist/llm/budget.d.ts +23 -0
  78. package/dist/llm/budget.js +58 -0
  79. package/dist/llm/client.d.ts +53 -0
  80. package/dist/llm/client.js +122 -0
  81. package/dist/llm/factory.d.ts +14 -0
  82. package/dist/llm/factory.js +32 -0
  83. package/dist/orchestrator/defect-logger.d.ts +31 -0
  84. package/dist/orchestrator/defect-logger.js +101 -0
  85. package/dist/orchestrator/defect-manager.d.ts +118 -0
  86. package/dist/orchestrator/defect-manager.js +338 -0
  87. package/dist/orchestrator/defect-migration.d.ts +14 -0
  88. package/dist/orchestrator/defect-migration.js +174 -0
  89. package/dist/orchestrator/defect-store.d.ts +48 -0
  90. package/dist/orchestrator/defect-store.js +76 -0
  91. package/dist/orchestrator/healing.d.ts +14 -0
  92. package/dist/orchestrator/healing.js +11 -0
  93. package/dist/orchestrator/interactive-steering.d.ts +64 -0
  94. package/dist/orchestrator/interactive-steering.js +107 -0
  95. package/dist/orchestrator/interrupt-handler.d.ts +30 -0
  96. package/dist/orchestrator/interrupt-handler.js +70 -0
  97. package/dist/orchestrator/lesson-manager.d.ts +25 -0
  98. package/dist/orchestrator/lesson-manager.js +122 -0
  99. package/dist/orchestrator/progress-summary.d.ts +15 -0
  100. package/dist/orchestrator/progress-summary.js +106 -0
  101. package/dist/orchestrator/reasoning-score.d.ts +49 -0
  102. package/dist/orchestrator/reasoning-score.js +117 -0
  103. package/dist/orchestrator/swarm.d.ts +36 -0
  104. package/dist/orchestrator/swarm.js +77 -0
  105. package/dist/orchestrator/task-factory.d.ts +15 -0
  106. package/dist/orchestrator/task-factory.js +176 -0
  107. package/dist/orchestrator/validation-gate.d.ts +23 -0
  108. package/dist/orchestrator/validation-gate.js +155 -0
  109. package/dist/protocol/react-contract.d.ts +136 -0
  110. package/dist/protocol/react-contract.js +698 -0
  111. package/dist/protocol/wks-protocol-manager.d.ts +22 -0
  112. package/dist/protocol/wks-protocol-manager.js +72 -0
  113. package/dist/sdlc-runtime/conversation-runner.d.ts +8 -0
  114. package/dist/sdlc-runtime/conversation-runner.js +64 -0
  115. package/dist/sdlc-runtime/dag-utils.d.ts +15 -0
  116. package/dist/sdlc-runtime/dag-utils.js +67 -0
  117. package/dist/sdlc-runtime/defect-integration.d.ts +7 -0
  118. package/dist/sdlc-runtime/defect-integration.js +99 -0
  119. package/dist/sdlc-runtime/execution-loop.d.ts +38 -0
  120. package/dist/sdlc-runtime/execution-loop.js +274 -0
  121. package/dist/sdlc-runtime/lesson-recorder.d.ts +9 -0
  122. package/dist/sdlc-runtime/lesson-recorder.js +27 -0
  123. package/dist/sdlc-runtime/plan-initializer.d.ts +47 -0
  124. package/dist/sdlc-runtime/plan-initializer.js +135 -0
  125. package/dist/sdlc-runtime/progress-persister.d.ts +10 -0
  126. package/dist/sdlc-runtime/progress-persister.js +34 -0
  127. package/dist/sdlc-runtime/protocol-loader.d.ts +10 -0
  128. package/dist/sdlc-runtime/protocol-loader.js +21 -0
  129. package/dist/sdlc-runtime/reporting.d.ts +24 -0
  130. package/dist/sdlc-runtime/reporting.js +68 -0
  131. package/dist/sdlc-runtime/sdlc-orchestrator.d.ts +59 -0
  132. package/dist/sdlc-runtime/sdlc-orchestrator.js +170 -0
  133. package/dist/sdlc-runtime/sdlc-skill.d.ts +44 -0
  134. package/dist/sdlc-runtime/sdlc-skill.js +148 -0
  135. package/dist/sdlc-runtime/steering-handler.d.ts +14 -0
  136. package/dist/sdlc-runtime/steering-handler.js +51 -0
  137. package/dist/sdlc-runtime/trace-recorder.d.ts +10 -0
  138. package/dist/sdlc-runtime/trace-recorder.js +7 -0
  139. package/dist/security/index.d.ts +16 -0
  140. package/dist/security/index.js +12 -0
  141. package/dist/security/input-screen.d.ts +30 -0
  142. package/dist/security/input-screen.js +75 -0
  143. package/dist/security/tool-call-guard.d.ts +16 -0
  144. package/dist/security/tool-call-guard.js +163 -0
  145. package/dist/security/untrusted-content.d.ts +34 -0
  146. package/dist/security/untrusted-content.js +63 -0
  147. package/dist/skills/advanced-dfir/SKILL.md +85 -0
  148. package/dist/skills/advanced-pentest-lab/SKILL.md +88 -0
  149. package/dist/skills/analyst/SKILL.md +55 -0
  150. package/dist/skills/architect/SKILL.md +54 -0
  151. package/dist/skills/aws/SKILL.md +92 -0
  152. package/dist/skills/azure/SKILL.md +90 -0
  153. package/dist/skills/bylaw-context.d.ts +45 -0
  154. package/dist/skills/bylaw-context.js +61 -0
  155. package/dist/skills/bylaw-review.d.ts +20 -0
  156. package/dist/skills/bylaw-review.js +101 -0
  157. package/dist/skills/conversation/SKILL.md +29 -0
  158. package/dist/skills/design-patterns/SKILL.md +190 -0
  159. package/dist/skills/devops/SKILL.md +55 -0
  160. package/dist/skills/directives.d.ts +20 -0
  161. package/dist/skills/directives.js +313 -0
  162. package/dist/skills/docker/SKILL.md +76 -0
  163. package/dist/skills/docker-expert/SKILL.md +56 -0
  164. package/dist/skills/enterprise-systems-analyst/SKILL.md +83 -0
  165. package/dist/skills/enterprise-systems-analyst/references/crm.md +41 -0
  166. package/dist/skills/enterprise-systems-analyst/references/erp.md +40 -0
  167. package/dist/skills/enterprise-systems-analyst/references/financial-systems.md +35 -0
  168. package/dist/skills/enterprise-systems-analyst/references/hcm.md +38 -0
  169. package/dist/skills/enterprise-systems-analyst/references/mrp.md +37 -0
  170. package/dist/skills/enterprise-systems-analyst/references/scm.md +32 -0
  171. package/dist/skills/ethical-hacking-methodology/SKILL.md +119 -0
  172. package/dist/skills/externalSkillLoader.d.ts +25 -0
  173. package/dist/skills/externalSkillLoader.js +65 -0
  174. package/dist/skills/externalSkillRegistry.d.ts +33 -0
  175. package/dist/skills/externalSkillRegistry.js +94 -0
  176. package/dist/skills/filesystem-management/SKILL.md +61 -0
  177. package/dist/skills/first-run-seed.d.ts +26 -0
  178. package/dist/skills/first-run-seed.js +75 -0
  179. package/dist/skills/git-vcs/SKILL.md +84 -0
  180. package/dist/skills/kafka/SKILL.md +89 -0
  181. package/dist/skills/kubernetes/SKILL.md +93 -0
  182. package/dist/skills/kubernetes-expert/SKILL.md +54 -0
  183. package/dist/skills/openshift/SKILL.md +93 -0
  184. package/dist/skills/pentester/SKILL.md +59 -0
  185. package/dist/skills/performance-tester/SKILL.md +57 -0
  186. package/dist/skills/playwright-ui-tester/SKILL.md +67 -0
  187. package/dist/skills/programmer/SKILL.md +58 -0
  188. package/dist/skills/project-scaffolding/SKILL.md +133 -0
  189. package/dist/skills/qa-engineer/SKILL.md +91 -0
  190. package/dist/skills/rca/SKILL.md +58 -0
  191. package/dist/skills/redhat/SKILL.md +92 -0
  192. package/dist/skills/rosa/SKILL.md +80 -0
  193. package/dist/skills/scrum-framework/SKILL.md +74 -0
  194. package/dist/skills/scrum-framework/references/artifacts_and_quality.md +79 -0
  195. package/dist/skills/scrum-framework/references/roles_and_events.md +105 -0
  196. package/dist/skills/scrum-master-agent/SKILL.md +74 -0
  197. package/dist/skills/scrum-master-agent/references/behaviors.md +56 -0
  198. package/dist/skills/sdlc-skill.d.ts +1 -0
  199. package/dist/skills/sdlc-skill.js +4 -0
  200. package/dist/skills/secops/SKILL.md +52 -0
  201. package/dist/skills/secure-architect.bylaws.d.ts +68 -0
  202. package/dist/skills/secure-architect.bylaws.js +525 -0
  203. package/dist/skills/seed-skills.d.ts +48 -0
  204. package/dist/skills/seed-skills.js +213 -0
  205. package/dist/skills/skill-authoring/SKILL.md +123 -0
  206. package/dist/skills/skill-header.d.ts +51 -0
  207. package/dist/skills/skill-header.js +163 -0
  208. package/dist/skills/skill-path-guard.d.ts +41 -0
  209. package/dist/skills/skill-path-guard.js +95 -0
  210. package/dist/skills/skillRouter.d.ts +51 -0
  211. package/dist/skills/skillRouter.js +90 -0
  212. package/dist/skills/skills-root.d.ts +64 -0
  213. package/dist/skills/skills-root.js +168 -0
  214. package/dist/skills/software-architect/SKILL.md +77 -0
  215. package/dist/skills/software-engineer/SKILL.md +74 -0
  216. package/dist/skills/solid-principles/SKILL.md +94 -0
  217. package/dist/skills/task-planning/SKILL.md +115 -0
  218. package/dist/skills/tester/SKILL.md +54 -0
  219. package/dist/skills/ubuntu/SKILL.md +87 -0
  220. package/dist/skills/ui-ux-design/SKILL.md +114 -0
  221. package/dist/skills/workspace-context/SKILL.md +103 -0
  222. package/dist/sprint/controller.d.ts +37 -0
  223. package/dist/sprint/controller.js +220 -0
  224. package/dist/sprint/dag-builder.d.ts +14 -0
  225. package/dist/sprint/dag-builder.js +105 -0
  226. package/dist/sprint/reporter.d.ts +11 -0
  227. package/dist/sprint/reporter.js +97 -0
  228. package/dist/sprint/state-store.d.ts +10 -0
  229. package/dist/sprint/state-store.js +71 -0
  230. package/dist/sprint/types.d.ts +24 -0
  231. package/dist/sprint/types.js +4 -0
  232. package/dist/store/file-version-store.d.ts +24 -0
  233. package/dist/store/file-version-store.js +73 -0
  234. package/dist/store/task-store.d.ts +90 -0
  235. package/dist/store/task-store.js +166 -0
  236. package/dist/task-ingest/architect-detailer.d.ts +43 -0
  237. package/dist/task-ingest/architect-detailer.js +141 -0
  238. package/dist/task-ingest/detail-schema.d.ts +9 -0
  239. package/dist/task-ingest/detail-schema.js +195 -0
  240. package/dist/task-ingest/detailed-run.d.ts +36 -0
  241. package/dist/task-ingest/detailed-run.js +108 -0
  242. package/dist/task-ingest/extract-id.d.ts +9 -0
  243. package/dist/task-ingest/extract-id.js +24 -0
  244. package/dist/task-ingest/index.d.ts +23 -0
  245. package/dist/task-ingest/index.js +14 -0
  246. package/dist/task-ingest/ingest.d.ts +45 -0
  247. package/dist/task-ingest/ingest.js +163 -0
  248. package/dist/task-ingest/list-ingested.d.ts +13 -0
  249. package/dist/task-ingest/list-ingested.js +30 -0
  250. package/dist/task-ingest/pending-filter.d.ts +30 -0
  251. package/dist/task-ingest/pending-filter.js +59 -0
  252. package/dist/task-ingest/scanner.d.ts +56 -0
  253. package/dist/task-ingest/scanner.js +216 -0
  254. package/dist/task-ingest/source-reader.d.ts +25 -0
  255. package/dist/task-ingest/source-reader.js +93 -0
  256. package/dist/task-ingest/spec-builder.d.ts +34 -0
  257. package/dist/task-ingest/spec-builder.js +89 -0
  258. package/dist/task-ingest/wbs-extract.d.ts +50 -0
  259. package/dist/task-ingest/wbs-extract.js +226 -0
  260. package/dist/task-ingest/wbs-parser.d.ts +36 -0
  261. package/dist/task-ingest/wbs-parser.js +170 -0
  262. package/dist/tools/apiTestTool.d.ts +37 -0
  263. package/dist/tools/apiTestTool.js +128 -0
  264. package/dist/tools/ast-tools.d.ts +183 -0
  265. package/dist/tools/ast-tools.js +853 -0
  266. package/dist/tools/browse-tool.d.ts +105 -0
  267. package/dist/tools/browse-tool.js +394 -0
  268. package/dist/tools/credential.d.ts +17 -0
  269. package/dist/tools/credential.js +32 -0
  270. package/dist/tools/dependency-graph.d.ts +23 -0
  271. package/dist/tools/dependency-graph.js +164 -0
  272. package/dist/tools/edit-tool.d.ts +34 -0
  273. package/dist/tools/edit-tool.js +95 -0
  274. package/dist/tools/file-header-manager.d.ts +27 -0
  275. package/dist/tools/file-header-manager.js +153 -0
  276. package/dist/tools/fs-tools.d.ts +154 -0
  277. package/dist/tools/fs-tools.js +337 -0
  278. package/dist/tools/git-tools.d.ts +79 -0
  279. package/dist/tools/git-tools.js +348 -0
  280. package/dist/tools/github-tool.d.ts +48 -0
  281. package/dist/tools/github-tool.js +147 -0
  282. package/dist/tools/globTool.d.ts +20 -0
  283. package/dist/tools/globTool.js +34 -0
  284. package/dist/tools/grepTool.d.ts +19 -0
  285. package/dist/tools/grepTool.js +44 -0
  286. package/dist/tools/index-freshness.d.ts +58 -0
  287. package/dist/tools/index-freshness.js +190 -0
  288. package/dist/tools/index-glob.d.ts +48 -0
  289. package/dist/tools/index-glob.js +175 -0
  290. package/dist/tools/load-skill-tool.d.ts +15 -0
  291. package/dist/tools/load-skill-tool.js +114 -0
  292. package/dist/tools/patch-tools.d.ts +58 -0
  293. package/dist/tools/patch-tools.js +153 -0
  294. package/dist/tools/playwright-tool.d.ts +66 -0
  295. package/dist/tools/playwright-tool.js +121 -0
  296. package/dist/tools/project-detect.d.ts +20 -0
  297. package/dist/tools/project-detect.js +87 -0
  298. package/dist/tools/prompt-guidance.d.ts +22 -0
  299. package/dist/tools/prompt-guidance.js +23 -0
  300. package/dist/tools/scheduleTool.d.ts +19 -0
  301. package/dist/tools/scheduleTool.js +181 -0
  302. package/dist/tools/search-tools.d.ts +27 -0
  303. package/dist/tools/search-tools.js +78 -0
  304. package/dist/tools/sed-tool.d.ts +66 -0
  305. package/dist/tools/sed-tool.js +402 -0
  306. package/dist/tools/shell-result.d.ts +11 -0
  307. package/dist/tools/shell-result.js +1 -0
  308. package/dist/tools/shell-tool.d.ts +45 -0
  309. package/dist/tools/shell-tool.js +141 -0
  310. package/dist/tools/siteCrawlerTool.d.ts +32 -0
  311. package/dist/tools/siteCrawlerTool.js +205 -0
  312. package/dist/tools/tool-registry.d.ts +67 -0
  313. package/dist/tools/tool-registry.js +596 -0
  314. package/dist/tools/validate-tool.d.ts +23 -0
  315. package/dist/tools/validate-tool.js +201 -0
  316. package/dist/tools/workspace-index.d.ts +46 -0
  317. package/dist/tools/workspace-index.js +173 -0
  318. package/dist/types.d.ts +222 -0
  319. package/dist/types.js +7 -0
  320. package/dist/updater/index.d.ts +14 -0
  321. package/dist/updater/index.js +120 -0
  322. package/dist/util/banner.d.ts +25 -0
  323. package/dist/util/banner.js +140 -0
  324. package/dist/util/command-suggester.d.ts +6 -0
  325. package/dist/util/command-suggester.js +25 -0
  326. package/dist/util/confirm-interrupt.d.ts +10 -0
  327. package/dist/util/confirm-interrupt.js +31 -0
  328. package/dist/util/continue-trigger.d.ts +11 -0
  329. package/dist/util/continue-trigger.js +20 -0
  330. package/dist/util/env-info.d.ts +18 -0
  331. package/dist/util/env-info.js +37 -0
  332. package/dist/util/file-access-log.d.ts +35 -0
  333. package/dist/util/file-access-log.js +140 -0
  334. package/dist/util/footer-manager.d.ts +124 -0
  335. package/dist/util/footer-manager.js +195 -0
  336. package/dist/util/footer-renderer.d.ts +67 -0
  337. package/dist/util/footer-renderer.js +319 -0
  338. package/dist/util/footer-state.d.ts +34 -0
  339. package/dist/util/footer-state.js +18 -0
  340. package/dist/util/footer-text.d.ts +51 -0
  341. package/dist/util/footer-text.js +74 -0
  342. package/dist/util/ids.d.ts +1 -0
  343. package/dist/util/ids.js +4 -0
  344. package/dist/util/levenshtein.d.ts +6 -0
  345. package/dist/util/levenshtein.js +34 -0
  346. package/dist/util/logger.d.ts +10 -0
  347. package/dist/util/logger.js +41 -0
  348. package/dist/util/logs.d.ts +26 -0
  349. package/dist/util/logs.js +88 -0
  350. package/dist/util/output-handler.d.ts +89 -0
  351. package/dist/util/output-handler.js +193 -0
  352. package/dist/util/output-interceptor.d.ts +18 -0
  353. package/dist/util/output-interceptor.js +49 -0
  354. package/dist/util/output-paths.d.ts +43 -0
  355. package/dist/util/output-paths.js +121 -0
  356. package/dist/util/package-json.d.ts +6 -0
  357. package/dist/util/package-json.js +36 -0
  358. package/dist/util/process-kill.d.ts +27 -0
  359. package/dist/util/process-kill.js +148 -0
  360. package/dist/util/protocol-error-logger.d.ts +33 -0
  361. package/dist/util/protocol-error-logger.js +73 -0
  362. package/dist/util/redact.d.ts +25 -0
  363. package/dist/util/redact.js +103 -0
  364. package/dist/util/scroll-region-guard.d.ts +33 -0
  365. package/dist/util/scroll-region-guard.js +63 -0
  366. package/dist/util/spinner.d.ts +15 -0
  367. package/dist/util/spinner.js +49 -0
  368. package/dist/util/terminal-output.d.ts +34 -0
  369. package/dist/util/terminal-output.js +1 -0
  370. package/dist/util/terminal-silent.d.ts +6 -0
  371. package/dist/util/terminal-silent.js +20 -0
  372. package/dist/util/terminal.d.ts +56 -0
  373. package/dist/util/terminal.js +124 -0
  374. package/dist/util/text-sanitize.d.ts +8 -0
  375. package/dist/util/text-sanitize.js +45 -0
  376. package/dist/util/thinking-spinner.d.ts +27 -0
  377. package/dist/util/thinking-spinner.js +189 -0
  378. package/dist/util/tool-error-logger.d.ts +33 -0
  379. package/dist/util/tool-error-logger.js +77 -0
  380. package/dist/util/tty.d.ts +13 -0
  381. package/dist/util/tty.js +16 -0
  382. package/dist/util/xcoder-paths.d.ts +56 -0
  383. package/dist/util/xcoder-paths.js +63 -0
  384. package/dist/version.d.ts +2 -0
  385. package/dist/version.js +4 -0
  386. package/dist/worker-agent/to-subtask-node.d.ts +35 -0
  387. package/dist/worker-agent/to-subtask-node.js +41 -0
  388. package/dist/worker-agent/worker-orchestrator.d.ts +104 -0
  389. package/dist/worker-agent/worker-orchestrator.js +201 -0
  390. package/package.json +38 -3
@@ -0,0 +1,853 @@
1
+ // xcoder:version 17 | xcoder:task task-e6370a | xcoder:updated 2026-08-12T16:39:47.708Z | xcoder:subtask code-st-cd4444
2
+ import { promises as fs } from "node:fs";
3
+ import path from "node:path";
4
+ import { upsertEntry } from "./workspace-index.js";
5
+ import { resolveInWorkspace, hashFile } from "./patch-tools.js";
6
+ import { getCommentSyntax, injectVersionHeader, } from "./file-header-manager.js";
7
+ import { incrementFileVersion } from "../store/file-version-store.js";
8
+ /**
9
+ * A small, dependency-free tokenizer + scope tracker for TypeScript and
10
+ * JavaScript, powering `read_outline`, `search_ast`, `update_function`,
11
+ * `rename_symbol`, and the TS/JS import extraction used by
12
+ * `get_dependency_graph`.
13
+ *
14
+ * Deliberately NOT a full parser and NOT type-aware (tradeoff T1): it
15
+ * tokenizes identifiers / strings / templates / comments / punctuation,
16
+ * tracks brace nesting to delimit scopes and function bodies, and records
17
+ * declarations and identifier references. Exotic edge cases (destructuring
18
+ * with shadowing, hoisting, complex generics) may mis-scope, but every
19
+ * failure path returns a typed `parse_error`, never silent corruption.
20
+ */
21
+ export const MAX_SCAN_BYTES = 2 * 1024 * 1024;
22
+ // ---------------------------------------------------------------------------
23
+ // Tokenizer
24
+ // ---------------------------------------------------------------------------
25
+ const KEYWORDS = new Set([
26
+ "function", "class", "const", "let", "var", "interface", "type", "import",
27
+ "export", "from", "return", "if", "else", "for", "while", "do", "switch",
28
+ "case", "default", "new", "typeof", "instanceof", "in", "of", "async",
29
+ "await", "yield", "extends", "implements", "enum", "namespace", "declare",
30
+ "abstract", "public", "private", "protected", "static", "readonly", "get",
31
+ "set", "void", "null", "undefined", "true", "false", "this", "super",
32
+ "break", "continue", "throw", "try", "catch", "finally", "delete", "with",
33
+ "debugger", "as", "satisfies", "keyof", "infer", "is", "any", "unknown",
34
+ "never", "string", "number", "boolean", "symbol", "bigint", "object",
35
+ "module", "require", "global", "NaN", "Infinity", "constructor",
36
+ ]);
37
+ /**
38
+ * Tokenizes into a small vocabulary. Handles line/block comments, quoted
39
+ * strings with escapes, template literals (incl. nested ${}), numbers,
40
+ * identifiers, and single-char punctuation. Returns `{ error }` on
41
+ * unterminated constructs instead of throwing.
42
+ */
43
+ export function tokenize(content) {
44
+ const tokens = [];
45
+ const n = content.length;
46
+ let i = 0;
47
+ let line = 1;
48
+ let col = 0;
49
+ const advance = (by) => {
50
+ for (let k = 0; k < by && i < n; k++) {
51
+ if (content[i] === "\n") {
52
+ line++;
53
+ col = 0;
54
+ }
55
+ else {
56
+ col++;
57
+ }
58
+ i++;
59
+ }
60
+ };
61
+ const push = (type, value, startLine, startCol, startOffset) => {
62
+ tokens.push({ type, value, line: startLine, startCol, endCol: col, offset: startOffset });
63
+ };
64
+ while (i < n) {
65
+ const ch = content[i];
66
+ const startLine = line;
67
+ const startCol = col;
68
+ const startOffset = i;
69
+ if (/\s/.test(ch)) {
70
+ advance(1);
71
+ continue;
72
+ }
73
+ if (ch === "/" && content[i + 1] === "/") {
74
+ let end = i + 2;
75
+ while (end < n && content[end] !== "\n")
76
+ end++;
77
+ advance(end - i);
78
+ push("comment", content.slice(startOffset, end), startLine, startCol, startOffset);
79
+ continue;
80
+ }
81
+ if (ch === "/" && content[i + 1] === "*") {
82
+ const close = content.indexOf("*/", i + 2);
83
+ if (close === -1)
84
+ return { error: "unterminated block comment" };
85
+ const end = close + 2;
86
+ advance(end - i);
87
+ push("comment", content.slice(startOffset, end), startLine, startCol, startOffset);
88
+ continue;
89
+ }
90
+ if (ch === "'" || ch === '"') {
91
+ let end = i + 1;
92
+ let closed = false;
93
+ while (end < n) {
94
+ if (content[end] === "\\") {
95
+ end += 2;
96
+ continue;
97
+ }
98
+ if (content[end] === ch) {
99
+ end++;
100
+ closed = true;
101
+ break;
102
+ }
103
+ if (content[end] === "\n")
104
+ break;
105
+ end++;
106
+ }
107
+ if (!closed)
108
+ return { error: "unterminated string literal" };
109
+ advance(end - i);
110
+ push("string", content.slice(startOffset, end), startLine, startCol, startOffset);
111
+ continue;
112
+ }
113
+ if (ch === "`") {
114
+ let end = i + 1;
115
+ let depth = 0;
116
+ let closed = false;
117
+ while (end < n) {
118
+ if (content[end] === "\\") {
119
+ end += 2;
120
+ continue;
121
+ }
122
+ if (content[end] === "$" && content[end + 1] === "{") {
123
+ depth++;
124
+ end += 2;
125
+ continue;
126
+ }
127
+ if (content[end] === "}" && depth > 0) {
128
+ depth--;
129
+ end++;
130
+ continue;
131
+ }
132
+ if (content[end] === "`") {
133
+ end++;
134
+ closed = true;
135
+ break;
136
+ }
137
+ if (content[end] === "\n" && depth === 0)
138
+ break;
139
+ end++;
140
+ }
141
+ if (!closed)
142
+ return { error: "unterminated template literal" };
143
+ advance(end - i);
144
+ push("template", content.slice(startOffset, end), startLine, startCol, startOffset);
145
+ continue;
146
+ }
147
+ if (/[0-9]/.test(ch) || (ch === "." && /[0-9]/.test(content[i + 1] ?? ""))) {
148
+ let end = i + 1;
149
+ while (end < n && /[0-9a-zA-Z_.]/.test(content[end]))
150
+ end++;
151
+ advance(end - i);
152
+ push("number", content.slice(startOffset, end), startLine, startCol, startOffset);
153
+ continue;
154
+ }
155
+ if (/[A-Za-z_$]/.test(ch)) {
156
+ let end = i + 1;
157
+ while (end < n && /[A-Za-z0-9_$]/.test(content[end]))
158
+ end++;
159
+ advance(end - i);
160
+ push("identifier", content.slice(startOffset, end), startLine, startCol, startOffset);
161
+ continue;
162
+ }
163
+ advance(1);
164
+ push("punct", ch, startLine, startCol, startOffset);
165
+ }
166
+ return { tokens };
167
+ }
168
+ /**
169
+ * Tokenizes + scans TS/JS source for imports, declarations, and identifier
170
+ * references. Single pass with an explicit brace-depth scope stack. Never
171
+ * throws: all failure modes fold into a typed `{ ok: false, error }` or a
172
+ * `parseError` on the result.
173
+ */
174
+ export function scanFile(content, language) {
175
+ const tok = tokenize(content);
176
+ if ("error" in tok)
177
+ return { ok: false, error: tok.error };
178
+ const { tokens } = tok;
179
+ const imports = [];
180
+ const declarations = [];
181
+ const references = [];
182
+ const referenceOffsets = [];
183
+ let parseError;
184
+ // Offsets that must NOT be treated as references (decl names, bindings, params).
185
+ const nonRefOffsets = new Set();
186
+ let braceDepth = 0;
187
+ const scopeStack = [{ depth: 0, decls: [] }];
188
+ const currentScope = () => scopeStack[scopeStack.length - 1];
189
+ let pendingBodyDecl = null;
190
+ /** Finds the index of the `)` that closes the parameter list starting after `openParenIdx`. */
191
+ const findParamClose = (openParenIdx) => {
192
+ let depth = 0;
193
+ for (let j = openParenIdx; j < tokens.length; j++) {
194
+ if (tokens[j].type !== "punct")
195
+ continue;
196
+ if (tokens[j].value === "(")
197
+ depth++;
198
+ else if (tokens[j].value === ")") {
199
+ depth--;
200
+ if (depth === 0)
201
+ return j;
202
+ }
203
+ }
204
+ return openParenIdx; // unbalanced — degrade to no restriction
205
+ };
206
+ let prevSignificant = null;
207
+ // Import-statement state.
208
+ let inImportStatement = false;
209
+ let importNeedsSpecifier = false;
210
+ let importBracesDepth = 0;
211
+ let pendingImportFrom = false;
212
+ const registerDecl = (name, kind, startLine, startCol, endLine) => {
213
+ if (!name || KEYWORDS.has(name))
214
+ return;
215
+ const decl = { name, kind, startLine, startCol, endLine, depth: braceDepth };
216
+ declarations.push(decl);
217
+ currentScope().decls.push(decl);
218
+ };
219
+ const pushRef = (t) => {
220
+ references.push({ name: t.value, startLine: t.line, startCol: t.startCol, endCol: t.endCol });
221
+ referenceOffsets.push(t.offset);
222
+ };
223
+ for (let idx = 0; idx < tokens.length; idx++) {
224
+ const t = tokens[idx];
225
+ const next = tokens[idx + 1] ?? null;
226
+ const prev = prevSignificant;
227
+ // ── Braces / scopes ──
228
+ if (t.type === "punct" && t.value === "{") {
229
+ braceDepth++;
230
+ scopeStack.push({ depth: braceDepth, decls: [] });
231
+ // A declaration body's `{` must come after the param list's `)` and must
232
+ // NOT be a type-annotation object (`: { ... }`, `Promise<{ ... }>`) —
233
+ // those are preceded by `:` or `<` and are never a function body.
234
+ const prevIsAnnotationStart = prev?.type === "punct" && (prev.value === ":" || prev.value === "<");
235
+ if (pendingBodyDecl &&
236
+ !pendingBodyDecl.seenOpenBrace &&
237
+ idx > pendingBodyDecl.paramCloseIdx &&
238
+ !prevIsAnnotationStart) {
239
+ pendingBodyDecl.seenOpenBrace = true;
240
+ pendingBodyDecl.openDepth = braceDepth;
241
+ }
242
+ prevSignificant = t;
243
+ continue;
244
+ }
245
+ if (t.type === "punct" && t.value === "}") {
246
+ if (pendingBodyDecl &&
247
+ pendingBodyDecl.seenOpenBrace &&
248
+ pendingBodyDecl.openDepth === braceDepth) {
249
+ pendingBodyDecl.decl.endLine = t.line;
250
+ pendingBodyDecl = null;
251
+ }
252
+ if (braceDepth === 0) {
253
+ parseError = parseError ?? "unbalanced closing brace";
254
+ }
255
+ else {
256
+ braceDepth--;
257
+ scopeStack.pop();
258
+ }
259
+ prevSignificant = t;
260
+ continue;
261
+ }
262
+ if (t.type === "punct" && t.value === ";") {
263
+ importNeedsSpecifier = false;
264
+ pendingImportFrom = false;
265
+ prevSignificant = t;
266
+ continue;
267
+ }
268
+ // ── arrow-function params: `a =>` and `(a, b) =>` ──
269
+ if (t.type === "punct" && t.value === "=" && next && next.type === "punct" && next.value === ">") {
270
+ const prevTok = tokens[idx - 1];
271
+ if (prevTok && prevTok.type === "identifier" && !KEYWORDS.has(prevTok.value)) {
272
+ nonRefOffsets.add(prevTok.offset);
273
+ registerDecl(prevTok.value, "param", prevTok.line, prevTok.startCol, braceDepth);
274
+ }
275
+ else if (prevTok && prevTok.type === "punct" && prevTok.value === ")") {
276
+ for (let j = idx - 2; j >= 0 && tokens[j].value !== "("; j--) {
277
+ const tk = tokens[j];
278
+ if (tk.type === "identifier" && !KEYWORDS.has(tk.value)) {
279
+ const before = tokens[j - 1];
280
+ if (!(before?.type === "punct" && before.value === ":")) {
281
+ nonRefOffsets.add(tk.offset);
282
+ registerDecl(tk.value, "param", tk.line, tk.startCol, braceDepth);
283
+ }
284
+ }
285
+ }
286
+ }
287
+ prevSignificant = next;
288
+ idx++; // consume the '>' token
289
+ continue;
290
+ }
291
+ // ── Strings ──
292
+ if (t.type === "string") {
293
+ const inner = t.value.length >= 2 ? t.value.slice(1, -1) : t.value;
294
+ if (inImportStatement && (pendingImportFrom || importBracesDepth === 0)) {
295
+ imports.push(inner);
296
+ inImportStatement = false;
297
+ pendingImportFrom = false;
298
+ importNeedsSpecifier = false;
299
+ importBracesDepth = 0;
300
+ prevSignificant = null;
301
+ continue;
302
+ }
303
+ if (prev && prev.type === "punct" && prev.value === "(" &&
304
+ tokens[idx - 2] && tokens[idx - 2].type === "identifier" &&
305
+ (tokens[idx - 2].value === "require" || tokens[idx - 2].value === "import")) {
306
+ imports.push(inner);
307
+ }
308
+ prevSignificant = t;
309
+ continue;
310
+ }
311
+ // ── import statements ──
312
+ if (t.type === "identifier" && t.value === "import" && !inImportStatement) {
313
+ inImportStatement = true;
314
+ importNeedsSpecifier = false;
315
+ importBracesDepth = 0;
316
+ pendingImportFrom = false;
317
+ prevSignificant = t;
318
+ continue;
319
+ }
320
+ if (inImportStatement && t.type === "identifier") {
321
+ if (t.value === "from") {
322
+ pendingImportFrom = true;
323
+ importNeedsSpecifier = false;
324
+ }
325
+ else if (t.value === "as" || t.value === "*") {
326
+ // skip — handled naturally by the binding branch below
327
+ }
328
+ else {
329
+ // Any other identifier inside an import clause is a local binding.
330
+ nonRefOffsets.add(t.offset);
331
+ registerDecl(t.value, "const", t.line, t.startCol, t.line);
332
+ }
333
+ prevSignificant = t;
334
+ continue;
335
+ }
336
+ if (inImportStatement && t.type === "punct") {
337
+ if (t.value === "{") {
338
+ importBracesDepth = 1;
339
+ importNeedsSpecifier = true;
340
+ }
341
+ else if (t.value === "}") {
342
+ importBracesDepth = 0;
343
+ importNeedsSpecifier = true;
344
+ }
345
+ else if (t.value === ",") {
346
+ importNeedsSpecifier = true;
347
+ }
348
+ prevSignificant = t;
349
+ continue;
350
+ }
351
+ // ── declarations ──
352
+ if (t.type === "identifier") {
353
+ const v = t.value;
354
+ if (v === "function") {
355
+ let nameTok = next;
356
+ if (nameTok && nameTok.type === "punct" && nameTok.value === "*") {
357
+ nameTok = tokens[idx + 2] ?? null;
358
+ }
359
+ if (nameTok && nameTok.type === "identifier" && !KEYWORDS.has(nameTok.value)) {
360
+ nonRefOffsets.add(nameTok.offset);
361
+ const decl = {
362
+ name: nameTok.value, kind: "function",
363
+ startLine: nameTok.line, startCol: nameTok.startCol,
364
+ endLine: t.line, depth: braceDepth,
365
+ };
366
+ declarations.push(decl);
367
+ currentScope().decls.push(decl);
368
+ pendingBodyDecl = { decl, seenOpenBrace: false, openDepth: 0, paramCloseIdx: idx };
369
+ prevSignificant = t;
370
+ continue;
371
+ }
372
+ }
373
+ if (v === "class") {
374
+ const nameTok = next;
375
+ if (nameTok && nameTok.type === "identifier" && !KEYWORDS.has(nameTok.value)) {
376
+ nonRefOffsets.add(nameTok.offset);
377
+ const decl = {
378
+ name: nameTok.value, kind: "class",
379
+ startLine: nameTok.line, startCol: nameTok.startCol,
380
+ endLine: t.line, depth: braceDepth,
381
+ };
382
+ declarations.push(decl);
383
+ currentScope().decls.push(decl);
384
+ pendingBodyDecl = { decl, seenOpenBrace: false, openDepth: 0, paramCloseIdx: idx };
385
+ prevSignificant = t;
386
+ continue;
387
+ }
388
+ }
389
+ if (v === "interface") {
390
+ const nameTok = next;
391
+ if (nameTok && nameTok.type === "identifier") {
392
+ nonRefOffsets.add(nameTok.offset);
393
+ const decl = {
394
+ name: nameTok.value, kind: "interface",
395
+ startLine: nameTok.line, startCol: nameTok.startCol,
396
+ endLine: t.line, depth: braceDepth,
397
+ };
398
+ declarations.push(decl);
399
+ currentScope().decls.push(decl);
400
+ pendingBodyDecl = { decl, seenOpenBrace: false, openDepth: 0, paramCloseIdx: idx };
401
+ prevSignificant = t;
402
+ continue;
403
+ }
404
+ }
405
+ if (v === "type") {
406
+ const nameTok = next;
407
+ if (nameTok && nameTok.type === "identifier") {
408
+ nonRefOffsets.add(nameTok.offset);
409
+ const decl = {
410
+ name: nameTok.value, kind: "type",
411
+ startLine: nameTok.line, startCol: nameTok.startCol,
412
+ endLine: t.line, depth: braceDepth,
413
+ };
414
+ declarations.push(decl);
415
+ currentScope().decls.push(decl);
416
+ prevSignificant = t;
417
+ continue;
418
+ }
419
+ }
420
+ if (v === "const" || v === "let" || v === "var") {
421
+ const kind = v;
422
+ const first = next;
423
+ if (first && first.type === "identifier" && !KEYWORDS.has(first.value)) {
424
+ nonRefOffsets.add(first.offset);
425
+ registerDecl(first.value, kind, first.line, first.startCol, t.line);
426
+ }
427
+ else if (first && first.type === "punct" && (first.value === "{" || first.value === "[")) {
428
+ const open = first.value;
429
+ const close = open === "{" ? "}" : "]";
430
+ let depth = 0;
431
+ let k = idx + 1;
432
+ for (; k < tokens.length; k++) {
433
+ const tk = tokens[k];
434
+ if (tk.type === "punct") {
435
+ if (tk.value === open)
436
+ depth++;
437
+ else if (tk.value === close && depth > 0) {
438
+ depth--;
439
+ if (depth === 0)
440
+ break;
441
+ }
442
+ }
443
+ else if (tk.type === "identifier" && !KEYWORDS.has(tk.value)) {
444
+ const before = tokens[k - 1];
445
+ if (!(before?.type === "punct" && before.value === ":")) {
446
+ nonRefOffsets.add(tk.offset);
447
+ registerDecl(tk.value, kind, tk.line, tk.startCol, t.line);
448
+ }
449
+ }
450
+ }
451
+ }
452
+ prevSignificant = t;
453
+ continue;
454
+ }
455
+ // ── function parameters: `function name(a, b)` ──
456
+ if (prev && prev.type === "punct" && prev.value === "(") {
457
+ const beforeParen = tokens[idx - 2];
458
+ const isFunctionParens = beforeParen?.type === "identifier" &&
459
+ (beforeParen.value === "function" ||
460
+ (tokens[idx - 3]?.type === "identifier" && tokens[idx - 3].value === "function"));
461
+ if (isFunctionParens) {
462
+ nonRefOffsets.add(t.offset);
463
+ registerDecl(v, "param", t.line, t.startCol, braceDepth);
464
+ prevSignificant = t;
465
+ continue;
466
+ }
467
+ }
468
+ // ── plain identifier: reference or declaration-handling above ──
469
+ if (!KEYWORDS.has(v) && !nonRefOffsets.has(t.offset) && !inImportStatement) {
470
+ const isPropAccess = prev?.type === "punct" && prev.value === ".";
471
+ const isObjectKey = prev?.type === "punct" && (prev.value === "{" || prev.value === ",") &&
472
+ next?.type === "punct" && (next.value === ":" || next.value === "?");
473
+ if (!isPropAccess && !isObjectKey) {
474
+ pushRef(t);
475
+ }
476
+ }
477
+ prevSignificant = t;
478
+ continue;
479
+ }
480
+ // Arrow detection lives inside the identifier branch above (t.value === "=").
481
+ // Non-identifier tokens: track but otherwise ignore.
482
+ prevSignificant = t;
483
+ }
484
+ // A declaration whose body never closed still carries a usable start.
485
+ if (pendingBodyDecl) {
486
+ pendingBodyDecl.decl.endLine = tokens.length ? tokens[tokens.length - 1].line : pendingBodyDecl.decl.endLine;
487
+ }
488
+ // Drop any reference that ended up being a param/declaration after all
489
+ // (e.g. arrow params collected on `=>` after the identifier was pushed).
490
+ const kept = [];
491
+ for (let i = 0; i < referenceOffsets.length; i++) {
492
+ if (!nonRefOffsets.has(referenceOffsets[i]))
493
+ kept.push(references[i]);
494
+ }
495
+ return { language, imports, declarations, references: kept, parseError };
496
+ }
497
+ /**
498
+ * Resolves a reference to the innermost visible declaration with the same
499
+ * name. Shadowing-aware: a declaration at a deeper brace depth wins over an
500
+ * outer one; among declarations at the same depth, the most recent one seen
501
+ * before the reference wins. Returns null when nothing is visible.
502
+ */
503
+ export function resolveReference(ref, decls) {
504
+ const sameName = decls.filter((d) => d.name === ref.name && d.startLine <= ref.startLine);
505
+ if (sameName.length === 0)
506
+ return null;
507
+ sameName.sort((a, b) => {
508
+ const dA = a.depth ?? 0;
509
+ const dB = b.depth ?? 0;
510
+ if (dA !== dB)
511
+ return dB - dA;
512
+ return b.startLine - a.startLine;
513
+ });
514
+ return sameName[0];
515
+ }
516
+ /**
517
+ * Returns the unique declaration for `name` or a typed failure. Used by
518
+ * update_function / rename_symbol to enforce the no-match / not-unique
519
+ * contract before any write happens.
520
+ */
521
+ export function findUniqueDeclaration(name, decls, kinds) {
522
+ const matches = decls.filter((d) => d.name === name && (!kinds || kinds.has(d.kind)));
523
+ if (matches.length === 0) {
524
+ return {
525
+ ok: false,
526
+ code: "no_match",
527
+ error: `no declaration named "${name}" found${kinds ? ` (kind: ${[...kinds].join("/")})` : ""}. ` +
528
+ `Search the file with search_ast or grep to confirm the exact name, then retry.`,
529
+ };
530
+ }
531
+ if (matches.length > 1) {
532
+ return {
533
+ ok: false,
534
+ code: "not_unique",
535
+ error: `"${name}" is declared ${matches.length} times in this file — update_function/rename_symbol require a unique declaration. Candidate lines: ${matches.map((m) => m.startLine).join(", ")}. Use a more specific path or rename the shadowing declarations first.`,
536
+ candidates: matches.map((m) => m.startLine),
537
+ };
538
+ }
539
+ return { ok: true, decl: matches[0] };
540
+ }
541
+ const SEARCH_QUERY_RE = /^(function|class|call)\s+([A-Za-z_$][A-Za-z0-9_$]*)$/;
542
+ function guessJsLanguage(relPath) {
543
+ const lower = relPath.toLowerCase();
544
+ if (lower.endsWith(".ts") || lower.endsWith(".tsx") || lower.endsWith(".mts") || lower.endsWith(".cts"))
545
+ return "typescript";
546
+ if (lower.endsWith(".js") || lower.endsWith(".jsx") || lower.endsWith(".mjs") || lower.endsWith(".cjs"))
547
+ return "javascript";
548
+ return null;
549
+ }
550
+ function signatureForLine(content, line) {
551
+ const lines = content.split("\n");
552
+ return (lines[line - 1] ?? "").trim().slice(0, 200);
553
+ }
554
+ /**
555
+ * Structural TS/JS search over the workspace. Supported queries:
556
+ * - "function Name" → function declarations named Name
557
+ * - "class Name" → class declarations named Name
558
+ * - "call Name" → identifier references to Name (call sites), shadowing-aware
559
+ * Uses the scanner — no regex false positives inside strings/comments.
560
+ */
561
+ export async function searchAstTool(root, input) {
562
+ const m = SEARCH_QUERY_RE.exec(input.query.trim());
563
+ if (!m) {
564
+ return {
565
+ ok: false,
566
+ code: "invalid_query",
567
+ error: `search_ast query must be one of: "function <Name>", "class <Name>", "call <Name>" — got "${input.query}". Use grep for arbitrary regex searches.`,
568
+ };
569
+ }
570
+ const [, kind, name] = m;
571
+ const { globTool } = await import("./globTool.js");
572
+ const { readFileTool } = await import("./fs-tools.js");
573
+ const { getOrBuildIndex } = await import("./workspace-index.js");
574
+ let files;
575
+ if (input.pathGlob && input.pathGlob.trim() !== "") {
576
+ files = await globTool(input.pathGlob, root);
577
+ }
578
+ else {
579
+ const index = await getOrBuildIndex(root);
580
+ files = index.entries.map((e) => e.relPath).filter((p) => guessJsLanguage(p) !== null);
581
+ }
582
+ const matches = [];
583
+ const languages = new Set();
584
+ let scanned = 0;
585
+ for (const file of files) {
586
+ const lang = guessJsLanguage(file);
587
+ if (!lang)
588
+ continue;
589
+ languages.add(lang);
590
+ const read = await readFileTool(root, file);
591
+ if (!read.ok)
592
+ continue;
593
+ if (Buffer.byteLength(read.content, "utf8") > MAX_SCAN_BYTES)
594
+ continue;
595
+ scanned++;
596
+ const scan = scanFile(read.content, lang);
597
+ if ("ok" in scan)
598
+ continue;
599
+ if (kind === "function") {
600
+ for (const d of scan.declarations) {
601
+ if (d.kind === "function" && d.name === name) {
602
+ matches.push({
603
+ file, kind: "function", name: d.name,
604
+ startLine: d.startLine, endLine: d.endLine,
605
+ signature: signatureForLine(read.content, d.startLine),
606
+ line: d.startLine,
607
+ });
608
+ }
609
+ }
610
+ }
611
+ else if (kind === "class") {
612
+ for (const d of scan.declarations) {
613
+ if (d.kind === "class" && d.name === name) {
614
+ matches.push({
615
+ file, kind: "class", name: d.name,
616
+ startLine: d.startLine, endLine: d.endLine,
617
+ signature: signatureForLine(read.content, d.startLine),
618
+ line: d.startLine,
619
+ });
620
+ }
621
+ }
622
+ }
623
+ else {
624
+ const decls = scan.declarations.filter((d) => d.name === name);
625
+ for (const ref of scan.references) {
626
+ if (ref.name !== name)
627
+ continue;
628
+ if (resolveReference(ref, decls)) {
629
+ matches.push({
630
+ file, kind: "call", name,
631
+ startLine: ref.startLine, endLine: ref.startLine,
632
+ signature: signatureForLine(read.content, ref.startLine),
633
+ line: ref.startLine,
634
+ });
635
+ }
636
+ }
637
+ }
638
+ }
639
+ return {
640
+ ok: true,
641
+ matches,
642
+ total: matches.length,
643
+ language: (languages.size === 0 ? "typescript" : languages.size === 1 ? [...languages][0] : "mixed"),
644
+ note: scanned === 0 ? "no supported TS/JS files matched — try a different pathGlob." : undefined,
645
+ };
646
+ }
647
+ /**
648
+ * Whole-function rewrite (TS/JS only): replaces the declaration's line range
649
+ * with `newCode`. Refuses when the name is not unique, when the file can't
650
+ * be scanned, or for non-TS/JS files — never partial.
651
+ */
652
+ export async function updateFunctionTool(root, input, ctx) {
653
+ const lang = guessJsLanguage(input.path);
654
+ if (!lang) {
655
+ return {
656
+ ok: false,
657
+ code: "unsupported_language",
658
+ error: `update_function supports TypeScript/JavaScript only — "${input.path}" is not a TS/JS file. Fall back to edit_file/line_patch/sed_tool for other languages.`,
659
+ };
660
+ }
661
+ let full;
662
+ try {
663
+ full = resolveInWorkspace(root, input.path);
664
+ }
665
+ catch (e) {
666
+ return { ok: false, error: e.message, code: "workspace_escape" };
667
+ }
668
+ let content;
669
+ try {
670
+ content = await fs.readFile(full, "utf8");
671
+ }
672
+ catch {
673
+ return {
674
+ ok: false,
675
+ code: "file_not_found",
676
+ error: `"${input.path}" doesn't exist or can't be read. Use write_file to create it first.`,
677
+ };
678
+ }
679
+ if (Buffer.byteLength(content, "utf8") > MAX_SCAN_BYTES) {
680
+ return {
681
+ ok: false,
682
+ code: "parse_error",
683
+ error: `"${input.path}" exceeds the ${MAX_SCAN_BYTES}-byte scan ceiling — use edit_file/line_patch with a tight range instead.`,
684
+ };
685
+ }
686
+ const scan = scanFile(content, lang);
687
+ if ("ok" in scan) {
688
+ return { ok: false, code: "parse_error", error: `couldn't scan "${input.path}": ${scan.error}` };
689
+ }
690
+ if (scan.parseError) {
691
+ return { ok: false, code: "parse_error", error: `scan of "${input.path}" reported: ${scan.parseError}. Fix the syntax issue or use edit_file instead.` };
692
+ }
693
+ const unique = findUniqueDeclaration(input.functionName, scan.declarations, new Set(["function", "class"]));
694
+ if (!unique.ok)
695
+ return { ...unique };
696
+ const { decl } = unique;
697
+ const lines = content.split("\n");
698
+ const start = decl.startLine;
699
+ const end = Math.max(decl.startLine, Math.min(decl.endLine, lines.length));
700
+ const before = lines.slice(0, start - 1);
701
+ const after = lines.slice(end);
702
+ let next = [...before, ...input.newCode.split("\n"), ...after].join("\n");
703
+ if (ctx) {
704
+ const syntax = getCommentSyntax(input.path);
705
+ if (syntax) {
706
+ try {
707
+ const meta = await incrementFileVersion(root, input.path, ctx.taskId, ctx.subtaskId);
708
+ const injected = injectVersionHeader(next, syntax, meta);
709
+ next = injected.content;
710
+ }
711
+ catch (e) {
712
+ return { ok: false, error: e.message, code: "parse_error" };
713
+ }
714
+ }
715
+ }
716
+ try {
717
+ await fs.writeFile(full, next, "utf8");
718
+ await upsertEntry(root, path.relative(root, full));
719
+ const sha1After = await hashFile(full);
720
+ return {
721
+ ok: true,
722
+ relPath: path.relative(root, full).split(path.sep).join("/"),
723
+ functionName: input.functionName,
724
+ oldLineRange: [start, end],
725
+ newLineRange: [start, start + input.newCode.split("\n").length - 1],
726
+ sha1After,
727
+ };
728
+ }
729
+ catch (e) {
730
+ return { ok: false, error: e.message, code: "parse_error" };
731
+ }
732
+ }
733
+ /**
734
+ * Scope-aware identifier rename (TS/JS only): replaces exactly the
735
+ * identifier tokens whose binding resolves to the declared symbol. Strings,
736
+ * comments, template literals, and property access targets are never
737
+ * touched. Blind sed is NOT used.
738
+ */
739
+ export async function renameSymbolTool(root, input, ctx) {
740
+ const lang = guessJsLanguage(input.path);
741
+ if (!lang) {
742
+ return {
743
+ ok: false,
744
+ code: "unsupported_language",
745
+ error: `rename_symbol supports TypeScript/JavaScript only — "${input.path}" is not a TS/JS file. Use sed_tool for other languages (with careful boundaries).`,
746
+ };
747
+ }
748
+ if (typeof input.newName !== "string" || !/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(input.newName)) {
749
+ return {
750
+ ok: false,
751
+ code: "no_match",
752
+ error: `"${String(input.newName)}" is not a valid identifier. newName must be a plain identifier (letters, digits, _, $).`,
753
+ };
754
+ }
755
+ let full;
756
+ try {
757
+ full = resolveInWorkspace(root, input.path);
758
+ }
759
+ catch (e) {
760
+ return { ok: false, error: e.message, code: "workspace_escape" };
761
+ }
762
+ let content;
763
+ try {
764
+ content = await fs.readFile(full, "utf8");
765
+ }
766
+ catch {
767
+ return {
768
+ ok: false,
769
+ code: "file_not_found",
770
+ error: `"${input.path}" doesn't exist or can't be read. Use write_file to create it first.`,
771
+ };
772
+ }
773
+ if (Buffer.byteLength(content, "utf8") > MAX_SCAN_BYTES) {
774
+ return {
775
+ ok: false,
776
+ code: "parse_error",
777
+ error: `"${input.path}" exceeds the ${MAX_SCAN_BYTES}-byte scan ceiling — use sed_tool with precise boundaries instead.`,
778
+ };
779
+ }
780
+ const scan = scanFile(content, lang);
781
+ if ("ok" in scan) {
782
+ return { ok: false, code: "parse_error", error: `couldn't scan "${input.path}": ${scan.error}` };
783
+ }
784
+ if (scan.parseError) {
785
+ return { ok: false, code: "parse_error", error: `scan of "${input.path}" reported: ${scan.parseError}. Fix the syntax issue or use sed_tool instead.` };
786
+ }
787
+ const unique = findUniqueDeclaration(input.name, scan.declarations);
788
+ if (!unique.ok)
789
+ return { ...unique };
790
+ const renames = [];
791
+ renames.push({ line: unique.decl.startLine, column: unique.decl.startCol, to: input.newName });
792
+ for (const ref of scan.references) {
793
+ if (ref.name !== input.name)
794
+ continue;
795
+ const resolved = resolveReference(ref, scan.declarations);
796
+ if (resolved && resolved === unique.decl) {
797
+ renames.push({ line: ref.startLine, column: ref.startCol, to: input.newName });
798
+ }
799
+ }
800
+ if (renames.length === 0) {
801
+ return {
802
+ ok: false,
803
+ code: "no_match",
804
+ error: `"${input.name}" was declared but no rename targets were found — this is unexpected; re-check the file content.`,
805
+ };
806
+ }
807
+ const lines = content.split("\n");
808
+ const byLine = new Map();
809
+ for (const r of renames) {
810
+ const list = byLine.get(r.line) ?? [];
811
+ list.push({ column: r.column, to: r.to, length: input.name.length });
812
+ byLine.set(r.line, list);
813
+ }
814
+ for (const [lineNo, edits] of byLine) {
815
+ const idx = lineNo - 1;
816
+ const line = lines[idx] ?? "";
817
+ const sorted = [...edits].sort((a, b) => b.column - a.column);
818
+ let next = line;
819
+ for (const edit of sorted) {
820
+ next = next.slice(0, edit.column) + edit.to + next.slice(edit.column + edit.length);
821
+ }
822
+ lines[idx] = next;
823
+ }
824
+ let nextContent = lines.join("\n");
825
+ if (ctx) {
826
+ const syntax = getCommentSyntax(input.path);
827
+ if (syntax) {
828
+ try {
829
+ const meta = await incrementFileVersion(root, input.path, ctx.taskId, ctx.subtaskId);
830
+ const injected = injectVersionHeader(nextContent, syntax, meta);
831
+ nextContent = injected.content;
832
+ }
833
+ catch (e) {
834
+ return { ok: false, error: e.message, code: "parse_error" };
835
+ }
836
+ }
837
+ }
838
+ try {
839
+ await fs.writeFile(full, nextContent, "utf8");
840
+ await upsertEntry(root, path.relative(root, full));
841
+ const sha1After = await hashFile(full);
842
+ return {
843
+ ok: true,
844
+ relPath: path.relative(root, full).split(path.sep).join("/"),
845
+ renames,
846
+ count: renames.length,
847
+ sha1After,
848
+ };
849
+ }
850
+ catch (e) {
851
+ return { ok: false, error: e.message, code: "parse_error" };
852
+ }
853
+ }