attocode 0.2.2 → 0.2.4

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 (382) hide show
  1. package/CHANGELOG.md +169 -3
  2. package/README.md +65 -5
  3. package/dist/src/adapters.d.ts.map +1 -1
  4. package/dist/src/adapters.js +15 -11
  5. package/dist/src/adapters.js.map +1 -1
  6. package/dist/src/agent.d.ts +44 -98
  7. package/dist/src/agent.d.ts.map +1 -1
  8. package/dist/src/agent.js +716 -2648
  9. package/dist/src/agent.js.map +1 -1
  10. package/dist/src/cli.d.ts.map +1 -1
  11. package/dist/src/cli.js +25 -3
  12. package/dist/src/cli.js.map +1 -1
  13. package/dist/src/commands/handler.d.ts.map +1 -1
  14. package/dist/src/commands/handler.js +11 -3
  15. package/dist/src/commands/handler.js.map +1 -1
  16. package/dist/src/commands/init-commands.d.ts.map +1 -1
  17. package/dist/src/commands/init-commands.js +16 -1
  18. package/dist/src/commands/init-commands.js.map +1 -1
  19. package/dist/src/commands/init.d.ts.map +1 -1
  20. package/dist/src/commands/init.js +31 -0
  21. package/dist/src/commands/init.js.map +1 -1
  22. package/dist/src/config/base-types.d.ts +45 -0
  23. package/dist/src/config/base-types.d.ts.map +1 -0
  24. package/dist/src/config/base-types.js +9 -0
  25. package/dist/src/config/base-types.js.map +1 -0
  26. package/dist/src/config/config-manager.d.ts +35 -0
  27. package/dist/src/config/config-manager.d.ts.map +1 -0
  28. package/dist/src/config/config-manager.js +108 -0
  29. package/dist/src/config/config-manager.js.map +1 -0
  30. package/dist/src/config/index.d.ts +4 -0
  31. package/dist/src/config/index.d.ts.map +1 -0
  32. package/dist/src/config/index.js +3 -0
  33. package/dist/src/config/index.js.map +1 -0
  34. package/dist/src/config/schema.d.ts +1546 -0
  35. package/dist/src/config/schema.d.ts.map +1 -0
  36. package/dist/src/config/schema.js +268 -0
  37. package/dist/src/config/schema.js.map +1 -0
  38. package/dist/src/config.d.ts +4 -1
  39. package/dist/src/config.d.ts.map +1 -1
  40. package/dist/src/config.js +8 -12
  41. package/dist/src/config.js.map +1 -1
  42. package/dist/src/core/agent-state-machine.d.ts +131 -0
  43. package/dist/src/core/agent-state-machine.d.ts.map +1 -0
  44. package/dist/src/core/agent-state-machine.js +302 -0
  45. package/dist/src/core/agent-state-machine.js.map +1 -0
  46. package/dist/src/core/base-manager.d.ts +79 -0
  47. package/dist/src/core/base-manager.d.ts.map +1 -0
  48. package/dist/src/core/base-manager.js +170 -0
  49. package/dist/src/core/base-manager.js.map +1 -0
  50. package/dist/src/core/completion-analyzer.d.ts +15 -0
  51. package/dist/src/core/completion-analyzer.d.ts.map +1 -0
  52. package/dist/src/core/completion-analyzer.js +53 -0
  53. package/dist/src/core/completion-analyzer.js.map +1 -0
  54. package/dist/src/core/execution-loop.d.ts +46 -0
  55. package/dist/src/core/execution-loop.d.ts.map +1 -0
  56. package/dist/src/core/execution-loop.js +1258 -0
  57. package/dist/src/core/execution-loop.js.map +1 -0
  58. package/dist/src/core/index.d.ts +7 -0
  59. package/dist/src/core/index.d.ts.map +1 -1
  60. package/dist/src/core/index.js +9 -0
  61. package/dist/src/core/index.js.map +1 -1
  62. package/dist/src/core/process-handlers.d.ts.map +1 -1
  63. package/dist/src/core/process-handlers.js +14 -0
  64. package/dist/src/core/process-handlers.js.map +1 -1
  65. package/dist/src/core/protocol/types.d.ts +4 -4
  66. package/dist/src/core/response-handler.d.ts +16 -0
  67. package/dist/src/core/response-handler.d.ts.map +1 -0
  68. package/dist/src/core/response-handler.js +234 -0
  69. package/dist/src/core/response-handler.js.map +1 -0
  70. package/dist/src/core/subagent-spawner.d.ts +43 -0
  71. package/dist/src/core/subagent-spawner.d.ts.map +1 -0
  72. package/dist/src/core/subagent-spawner.js +966 -0
  73. package/dist/src/core/subagent-spawner.js.map +1 -0
  74. package/dist/src/core/tool-executor.d.ts +59 -0
  75. package/dist/src/core/tool-executor.d.ts.map +1 -0
  76. package/dist/src/core/tool-executor.js +677 -0
  77. package/dist/src/core/tool-executor.js.map +1 -0
  78. package/dist/src/core/types.d.ts +133 -0
  79. package/dist/src/core/types.d.ts.map +1 -0
  80. package/dist/src/core/types.js +12 -0
  81. package/dist/src/core/types.js.map +1 -0
  82. package/dist/src/defaults.d.ts +8 -3
  83. package/dist/src/defaults.d.ts.map +1 -1
  84. package/dist/src/defaults.js +65 -3
  85. package/dist/src/defaults.js.map +1 -1
  86. package/dist/src/integrations/agent-registry.d.ts +11 -0
  87. package/dist/src/integrations/agent-registry.d.ts.map +1 -1
  88. package/dist/src/integrations/agent-registry.js.map +1 -1
  89. package/dist/src/integrations/auto-compaction.d.ts.map +1 -1
  90. package/dist/src/integrations/auto-compaction.js +8 -3
  91. package/dist/src/integrations/auto-compaction.js.map +1 -1
  92. package/dist/src/integrations/bash-policy.d.ts +33 -0
  93. package/dist/src/integrations/bash-policy.d.ts.map +1 -0
  94. package/dist/src/integrations/bash-policy.js +142 -0
  95. package/dist/src/integrations/bash-policy.js.map +1 -0
  96. package/dist/src/integrations/budget-pool.d.ts +7 -0
  97. package/dist/src/integrations/budget-pool.d.ts.map +1 -1
  98. package/dist/src/integrations/budget-pool.js +43 -0
  99. package/dist/src/integrations/budget-pool.js.map +1 -1
  100. package/dist/src/integrations/codebase-ast.d.ts +52 -0
  101. package/dist/src/integrations/codebase-ast.d.ts.map +1 -0
  102. package/dist/src/integrations/codebase-ast.js +457 -0
  103. package/dist/src/integrations/codebase-ast.js.map +1 -0
  104. package/dist/src/integrations/codebase-context.d.ts +23 -0
  105. package/dist/src/integrations/codebase-context.d.ts.map +1 -1
  106. package/dist/src/integrations/codebase-context.js +230 -17
  107. package/dist/src/integrations/codebase-context.js.map +1 -1
  108. package/dist/src/integrations/compaction.d.ts.map +1 -1
  109. package/dist/src/integrations/compaction.js +14 -6
  110. package/dist/src/integrations/compaction.js.map +1 -1
  111. package/dist/src/integrations/context-engineering.d.ts +8 -0
  112. package/dist/src/integrations/context-engineering.d.ts.map +1 -1
  113. package/dist/src/integrations/context-engineering.js +19 -0
  114. package/dist/src/integrations/context-engineering.js.map +1 -1
  115. package/dist/src/integrations/delegation-protocol.js +2 -2
  116. package/dist/src/integrations/delegation-protocol.js.map +1 -1
  117. package/dist/src/integrations/economics.d.ts +67 -1
  118. package/dist/src/integrations/economics.d.ts.map +1 -1
  119. package/dist/src/integrations/economics.js +328 -33
  120. package/dist/src/integrations/economics.js.map +1 -1
  121. package/dist/src/integrations/edit-validator.d.ts +30 -0
  122. package/dist/src/integrations/edit-validator.d.ts.map +1 -0
  123. package/dist/src/integrations/edit-validator.js +85 -0
  124. package/dist/src/integrations/edit-validator.js.map +1 -0
  125. package/dist/src/integrations/file-cache.d.ts +7 -0
  126. package/dist/src/integrations/file-cache.d.ts.map +1 -1
  127. package/dist/src/integrations/file-cache.js +54 -0
  128. package/dist/src/integrations/file-cache.js.map +1 -1
  129. package/dist/src/integrations/health-check.d.ts.map +1 -1
  130. package/dist/src/integrations/health-check.js +3 -2
  131. package/dist/src/integrations/health-check.js.map +1 -1
  132. package/dist/src/integrations/hierarchical-config.d.ts +3 -0
  133. package/dist/src/integrations/hierarchical-config.d.ts.map +1 -1
  134. package/dist/src/integrations/hierarchical-config.js +20 -0
  135. package/dist/src/integrations/hierarchical-config.js.map +1 -1
  136. package/dist/src/integrations/hooks.d.ts +2 -0
  137. package/dist/src/integrations/hooks.d.ts.map +1 -1
  138. package/dist/src/integrations/hooks.js +99 -15
  139. package/dist/src/integrations/hooks.js.map +1 -1
  140. package/dist/src/integrations/index.d.ts +10 -1
  141. package/dist/src/integrations/index.d.ts.map +1 -1
  142. package/dist/src/integrations/index.js +12 -2
  143. package/dist/src/integrations/index.js.map +1 -1
  144. package/dist/src/integrations/logger.d.ts +104 -0
  145. package/dist/src/integrations/logger.d.ts.map +1 -0
  146. package/dist/src/integrations/logger.js +219 -0
  147. package/dist/src/integrations/logger.js.map +1 -0
  148. package/dist/src/integrations/lsp.d.ts.map +1 -1
  149. package/dist/src/integrations/lsp.js +5 -4
  150. package/dist/src/integrations/lsp.js.map +1 -1
  151. package/dist/src/integrations/mcp-client.d.ts.map +1 -1
  152. package/dist/src/integrations/mcp-client.js +8 -7
  153. package/dist/src/integrations/mcp-client.js.map +1 -1
  154. package/dist/src/integrations/observability.d.ts.map +1 -1
  155. package/dist/src/integrations/observability.js +5 -4
  156. package/dist/src/integrations/observability.js.map +1 -1
  157. package/dist/src/integrations/openrouter-pricing.d.ts.map +1 -1
  158. package/dist/src/integrations/openrouter-pricing.js +4 -3
  159. package/dist/src/integrations/openrouter-pricing.js.map +1 -1
  160. package/dist/src/integrations/persistence.d.ts.map +1 -1
  161. package/dist/src/integrations/persistence.js +5 -4
  162. package/dist/src/integrations/persistence.js.map +1 -1
  163. package/dist/src/integrations/planning.d.ts.map +1 -1
  164. package/dist/src/integrations/planning.js +5 -4
  165. package/dist/src/integrations/planning.js.map +1 -1
  166. package/dist/src/integrations/policy-engine.d.ts +55 -0
  167. package/dist/src/integrations/policy-engine.d.ts.map +1 -0
  168. package/dist/src/integrations/policy-engine.js +247 -0
  169. package/dist/src/integrations/policy-engine.js.map +1 -0
  170. package/dist/src/integrations/retry.d.ts +1 -0
  171. package/dist/src/integrations/retry.d.ts.map +1 -1
  172. package/dist/src/integrations/retry.js.map +1 -1
  173. package/dist/src/integrations/routing.d.ts.map +1 -1
  174. package/dist/src/integrations/routing.js +2 -1
  175. package/dist/src/integrations/routing.js.map +1 -1
  176. package/dist/src/integrations/safety.d.ts +5 -4
  177. package/dist/src/integrations/safety.d.ts.map +1 -1
  178. package/dist/src/integrations/safety.js +45 -20
  179. package/dist/src/integrations/safety.js.map +1 -1
  180. package/dist/src/integrations/sandbox/basic.d.ts +7 -0
  181. package/dist/src/integrations/sandbox/basic.d.ts.map +1 -1
  182. package/dist/src/integrations/sandbox/basic.js +27 -2
  183. package/dist/src/integrations/sandbox/basic.js.map +1 -1
  184. package/dist/src/integrations/sandbox/docker.d.ts.map +1 -1
  185. package/dist/src/integrations/sandbox/docker.js +2 -1
  186. package/dist/src/integrations/sandbox/docker.js.map +1 -1
  187. package/dist/src/integrations/sandbox/index.d.ts +6 -0
  188. package/dist/src/integrations/sandbox/index.d.ts.map +1 -1
  189. package/dist/src/integrations/sandbox/index.js +8 -4
  190. package/dist/src/integrations/sandbox/index.js.map +1 -1
  191. package/dist/src/integrations/sandbox/landlock.d.ts.map +1 -1
  192. package/dist/src/integrations/sandbox/landlock.js +3 -0
  193. package/dist/src/integrations/sandbox/landlock.js.map +1 -1
  194. package/dist/src/integrations/self-improvement.d.ts.map +1 -1
  195. package/dist/src/integrations/self-improvement.js +12 -0
  196. package/dist/src/integrations/self-improvement.js.map +1 -1
  197. package/dist/src/integrations/session-store.d.ts +1 -0
  198. package/dist/src/integrations/session-store.d.ts.map +1 -1
  199. package/dist/src/integrations/session-store.js +1 -0
  200. package/dist/src/integrations/session-store.js.map +1 -1
  201. package/dist/src/integrations/shared-blackboard.d.ts +3 -0
  202. package/dist/src/integrations/shared-blackboard.d.ts.map +1 -1
  203. package/dist/src/integrations/shared-blackboard.js +47 -0
  204. package/dist/src/integrations/shared-blackboard.js.map +1 -1
  205. package/dist/src/integrations/smart-decomposer.d.ts +45 -1
  206. package/dist/src/integrations/smart-decomposer.d.ts.map +1 -1
  207. package/dist/src/integrations/smart-decomposer.js +486 -30
  208. package/dist/src/integrations/smart-decomposer.js.map +1 -1
  209. package/dist/src/integrations/sqlite-store.d.ts +2 -0
  210. package/dist/src/integrations/sqlite-store.d.ts.map +1 -1
  211. package/dist/src/integrations/sqlite-store.js +18 -6
  212. package/dist/src/integrations/sqlite-store.js.map +1 -1
  213. package/dist/src/integrations/swarm/failure-classifier.d.ts +11 -0
  214. package/dist/src/integrations/swarm/failure-classifier.d.ts.map +1 -0
  215. package/dist/src/integrations/swarm/failure-classifier.js +95 -0
  216. package/dist/src/integrations/swarm/failure-classifier.js.map +1 -0
  217. package/dist/src/integrations/swarm/index.d.ts +1 -1
  218. package/dist/src/integrations/swarm/index.d.ts.map +1 -1
  219. package/dist/src/integrations/swarm/index.js.map +1 -1
  220. package/dist/src/integrations/swarm/model-selector.d.ts +15 -0
  221. package/dist/src/integrations/swarm/model-selector.d.ts.map +1 -1
  222. package/dist/src/integrations/swarm/model-selector.js +100 -20
  223. package/dist/src/integrations/swarm/model-selector.js.map +1 -1
  224. package/dist/src/integrations/swarm/swarm-budget.d.ts +4 -0
  225. package/dist/src/integrations/swarm/swarm-budget.d.ts.map +1 -1
  226. package/dist/src/integrations/swarm/swarm-budget.js +6 -0
  227. package/dist/src/integrations/swarm/swarm-budget.js.map +1 -1
  228. package/dist/src/integrations/swarm/swarm-config-loader.d.ts +8 -0
  229. package/dist/src/integrations/swarm/swarm-config-loader.d.ts.map +1 -1
  230. package/dist/src/integrations/swarm/swarm-config-loader.js +249 -7
  231. package/dist/src/integrations/swarm/swarm-config-loader.js.map +1 -1
  232. package/dist/src/integrations/swarm/swarm-event-bridge.d.ts +86 -1
  233. package/dist/src/integrations/swarm/swarm-event-bridge.d.ts.map +1 -1
  234. package/dist/src/integrations/swarm/swarm-event-bridge.js +207 -23
  235. package/dist/src/integrations/swarm/swarm-event-bridge.js.map +1 -1
  236. package/dist/src/integrations/swarm/swarm-events.d.ts +58 -1
  237. package/dist/src/integrations/swarm/swarm-events.d.ts.map +1 -1
  238. package/dist/src/integrations/swarm/swarm-events.js +22 -5
  239. package/dist/src/integrations/swarm/swarm-events.js.map +1 -1
  240. package/dist/src/integrations/swarm/swarm-orchestrator.d.ts +147 -8
  241. package/dist/src/integrations/swarm/swarm-orchestrator.d.ts.map +1 -1
  242. package/dist/src/integrations/swarm/swarm-orchestrator.js +2179 -132
  243. package/dist/src/integrations/swarm/swarm-orchestrator.js.map +1 -1
  244. package/dist/src/integrations/swarm/swarm-quality-gate.d.ts +83 -2
  245. package/dist/src/integrations/swarm/swarm-quality-gate.d.ts.map +1 -1
  246. package/dist/src/integrations/swarm/swarm-quality-gate.js +278 -19
  247. package/dist/src/integrations/swarm/swarm-quality-gate.js.map +1 -1
  248. package/dist/src/integrations/swarm/swarm-state-store.d.ts +4 -1
  249. package/dist/src/integrations/swarm/swarm-state-store.d.ts.map +1 -1
  250. package/dist/src/integrations/swarm/swarm-state-store.js +8 -1
  251. package/dist/src/integrations/swarm/swarm-state-store.js.map +1 -1
  252. package/dist/src/integrations/swarm/task-queue.d.ts +54 -0
  253. package/dist/src/integrations/swarm/task-queue.d.ts.map +1 -1
  254. package/dist/src/integrations/swarm/task-queue.js +310 -12
  255. package/dist/src/integrations/swarm/task-queue.js.map +1 -1
  256. package/dist/src/integrations/swarm/types.d.ts +251 -13
  257. package/dist/src/integrations/swarm/types.d.ts.map +1 -1
  258. package/dist/src/integrations/swarm/types.js +70 -8
  259. package/dist/src/integrations/swarm/types.js.map +1 -1
  260. package/dist/src/integrations/swarm/worker-pool.d.ts +21 -4
  261. package/dist/src/integrations/swarm/worker-pool.d.ts.map +1 -1
  262. package/dist/src/integrations/swarm/worker-pool.js +223 -44
  263. package/dist/src/integrations/swarm/worker-pool.js.map +1 -1
  264. package/dist/src/integrations/task-manager.d.ts +33 -1
  265. package/dist/src/integrations/task-manager.d.ts.map +1 -1
  266. package/dist/src/integrations/task-manager.js +78 -4
  267. package/dist/src/integrations/task-manager.js.map +1 -1
  268. package/dist/src/integrations/tool-recommendation.d.ts +7 -4
  269. package/dist/src/integrations/tool-recommendation.d.ts.map +1 -1
  270. package/dist/src/integrations/tool-recommendation.js +58 -5
  271. package/dist/src/integrations/tool-recommendation.js.map +1 -1
  272. package/dist/src/integrations/work-log.js +4 -4
  273. package/dist/src/integrations/work-log.js.map +1 -1
  274. package/dist/src/main.js +106 -30
  275. package/dist/src/main.js.map +1 -1
  276. package/dist/src/modes/repl.d.ts.map +1 -1
  277. package/dist/src/modes/repl.js +50 -12
  278. package/dist/src/modes/repl.js.map +1 -1
  279. package/dist/src/modes/tui.d.ts.map +1 -1
  280. package/dist/src/modes/tui.js +41 -6
  281. package/dist/src/modes/tui.js.map +1 -1
  282. package/dist/src/modes.d.ts.map +1 -1
  283. package/dist/src/modes.js +4 -27
  284. package/dist/src/modes.js.map +1 -1
  285. package/dist/src/observability/tracer.d.ts.map +1 -1
  286. package/dist/src/observability/tracer.js +2 -1
  287. package/dist/src/observability/tracer.js.map +1 -1
  288. package/dist/src/persistence/schema.d.ts.map +1 -1
  289. package/dist/src/persistence/schema.js +11 -0
  290. package/dist/src/persistence/schema.js.map +1 -1
  291. package/dist/src/providers/adapters/anthropic.d.ts.map +1 -1
  292. package/dist/src/providers/adapters/anthropic.js +3 -2
  293. package/dist/src/providers/adapters/anthropic.js.map +1 -1
  294. package/dist/src/providers/adapters/openai.d.ts.map +1 -1
  295. package/dist/src/providers/adapters/openai.js +3 -2
  296. package/dist/src/providers/adapters/openai.js.map +1 -1
  297. package/dist/src/providers/adapters/openrouter.d.ts.map +1 -1
  298. package/dist/src/providers/adapters/openrouter.js +11 -11
  299. package/dist/src/providers/adapters/openrouter.js.map +1 -1
  300. package/dist/src/providers/circuit-breaker.d.ts +1 -0
  301. package/dist/src/providers/circuit-breaker.d.ts.map +1 -1
  302. package/dist/src/providers/circuit-breaker.js.map +1 -1
  303. package/dist/src/providers/provider.d.ts.map +1 -1
  304. package/dist/src/providers/provider.js +2 -1
  305. package/dist/src/providers/provider.js.map +1 -1
  306. package/dist/src/providers/resilient-provider.d.ts.map +1 -1
  307. package/dist/src/providers/resilient-provider.js +2 -1
  308. package/dist/src/providers/resilient-provider.js.map +1 -1
  309. package/dist/src/session-picker.d.ts.map +1 -1
  310. package/dist/src/session-picker.js +40 -5
  311. package/dist/src/session-picker.js.map +1 -1
  312. package/dist/src/shared/budget-tracker.d.ts +65 -0
  313. package/dist/src/shared/budget-tracker.d.ts.map +1 -0
  314. package/dist/src/shared/budget-tracker.js +128 -0
  315. package/dist/src/shared/budget-tracker.js.map +1 -0
  316. package/dist/src/shared/context-engine.d.ts +64 -0
  317. package/dist/src/shared/context-engine.d.ts.map +1 -0
  318. package/dist/src/shared/context-engine.js +117 -0
  319. package/dist/src/shared/context-engine.js.map +1 -0
  320. package/dist/src/shared/index.d.ts +12 -0
  321. package/dist/src/shared/index.d.ts.map +1 -0
  322. package/dist/src/shared/index.js +12 -0
  323. package/dist/src/shared/index.js.map +1 -0
  324. package/dist/src/shared/persistence.d.ts +57 -0
  325. package/dist/src/shared/persistence.d.ts.map +1 -0
  326. package/dist/src/shared/persistence.js +168 -0
  327. package/dist/src/shared/persistence.js.map +1 -0
  328. package/dist/src/shared/shared-context-state.d.ts +89 -0
  329. package/dist/src/shared/shared-context-state.d.ts.map +1 -0
  330. package/dist/src/shared/shared-context-state.js +175 -0
  331. package/dist/src/shared/shared-context-state.js.map +1 -0
  332. package/dist/src/shared/shared-economics-state.d.ts +61 -0
  333. package/dist/src/shared/shared-economics-state.d.ts.map +1 -0
  334. package/dist/src/shared/shared-economics-state.js +100 -0
  335. package/dist/src/shared/shared-economics-state.js.map +1 -0
  336. package/dist/src/tools/agent.d.ts.map +1 -1
  337. package/dist/src/tools/agent.js +11 -2
  338. package/dist/src/tools/agent.js.map +1 -1
  339. package/dist/src/tools/bash.d.ts +1 -1
  340. package/dist/src/tools/bash.d.ts.map +1 -1
  341. package/dist/src/tools/bash.js +2 -1
  342. package/dist/src/tools/bash.js.map +1 -1
  343. package/dist/src/tools/coercion.d.ts +6 -0
  344. package/dist/src/tools/coercion.d.ts.map +1 -1
  345. package/dist/src/tools/coercion.js +13 -0
  346. package/dist/src/tools/coercion.js.map +1 -1
  347. package/dist/src/tools/file.d.ts +5 -5
  348. package/dist/src/tools/file.js +2 -2
  349. package/dist/src/tools/file.js.map +1 -1
  350. package/dist/src/tools/permission.d.ts.map +1 -1
  351. package/dist/src/tools/permission.js +10 -116
  352. package/dist/src/tools/permission.js.map +1 -1
  353. package/dist/src/tools/types.d.ts +1 -0
  354. package/dist/src/tools/types.d.ts.map +1 -1
  355. package/dist/src/tools/types.js.map +1 -1
  356. package/dist/src/tracing/trace-collector.d.ts +292 -0
  357. package/dist/src/tracing/trace-collector.d.ts.map +1 -1
  358. package/dist/src/tracing/trace-collector.js +249 -5
  359. package/dist/src/tracing/trace-collector.js.map +1 -1
  360. package/dist/src/tracing/types.d.ts +200 -1
  361. package/dist/src/tracing/types.d.ts.map +1 -1
  362. package/dist/src/tracing/types.js.map +1 -1
  363. package/dist/src/tricks/failure-evidence.d.ts.map +1 -1
  364. package/dist/src/tricks/failure-evidence.js +2 -1
  365. package/dist/src/tricks/failure-evidence.js.map +1 -1
  366. package/dist/src/tui/app.d.ts +13 -0
  367. package/dist/src/tui/app.d.ts.map +1 -1
  368. package/dist/src/tui/app.js +162 -19
  369. package/dist/src/tui/app.js.map +1 -1
  370. package/dist/src/tui/components/ErrorBoundary.d.ts.map +1 -1
  371. package/dist/src/tui/components/ErrorBoundary.js +3 -2
  372. package/dist/src/tui/components/ErrorBoundary.js.map +1 -1
  373. package/dist/src/tui/event-display.d.ts.map +1 -1
  374. package/dist/src/tui/event-display.js +36 -62
  375. package/dist/src/tui/event-display.js.map +1 -1
  376. package/dist/src/tui/index.d.ts +4 -0
  377. package/dist/src/tui/index.d.ts.map +1 -1
  378. package/dist/src/tui/index.js +17 -0
  379. package/dist/src/tui/index.js.map +1 -1
  380. package/dist/src/types.d.ts +214 -1
  381. package/dist/src/types.d.ts.map +1 -1
  382. package/package.json +18 -3
@@ -108,11 +108,10 @@ export class SmartDecomposer {
108
108
  continue;
109
109
  }
110
110
  }
111
- // Both attempts failed → fall back to heuristic
112
- this.emit({ type: 'llm.fallback', reason: 'LLM failed after 2 attempts', task });
113
- const heuristicResult = this.decomposeHeuristic(task, context);
114
- subtasks = heuristicResult.subtasks;
115
- strategy = heuristicResult.strategy;
111
+ // Both attempts failed → return empty so orchestrator can try lastResortDecompose
112
+ this.emit({ type: 'llm.fallback', reason: 'LLM failed after 2 attempts — skipping heuristic', task });
113
+ subtasks = [];
114
+ strategy = 'adaptive';
116
115
  llmAssisted = false;
117
116
  }
118
117
  }
@@ -180,6 +179,9 @@ export class SmartDecomposer {
180
179
  idMap.set(`task-${index}`, id);
181
180
  idMap.set(`subtask-${index}`, id);
182
181
  idMap.set(`st-${index}`, id);
182
+ // F14: Populate modifies/reads from relevantFiles so downstream consumers
183
+ // (F12 hollow retry prompts, quality gate) get concrete file targets.
184
+ const isModifyType = ['implement', 'fix', 'refactor', 'integrate', 'test', 'deploy'].includes(s.type);
183
185
  return {
184
186
  id,
185
187
  description: s.description,
@@ -189,6 +191,8 @@ export class SmartDecomposer {
189
191
  type: s.type,
190
192
  parallelizable: s.parallelizable,
191
193
  relevantFiles: s.relevantFiles,
194
+ modifies: isModifyType ? s.relevantFiles : undefined,
195
+ reads: s.relevantFiles,
192
196
  suggestedRole: s.suggestedRole,
193
197
  };
194
198
  });
@@ -671,7 +675,14 @@ export class SmartDecomposer {
671
675
  }
672
676
  }
673
677
  if (group.length === 0) {
674
- // No progress - likely a cycle, break to avoid infinite loop
678
+ // No progress circular dependency detected.
679
+ // Force remaining tasks into sequential single-task groups
680
+ // so they still reach the task queue instead of silently vanishing.
681
+ for (const id of remaining) {
682
+ groups.push([id]);
683
+ completed.add(id);
684
+ }
685
+ remaining.clear();
675
686
  break;
676
687
  }
677
688
  groups.push(group);
@@ -789,6 +800,73 @@ export class SmartDecomposer {
789
800
  }
790
801
  }
791
802
  }
803
+ /**
804
+ * F5: Validate a decomposition result for structural correctness, feasibility, and granularity.
805
+ *
806
+ * Checks:
807
+ * 1. Structural: no cycles, valid dependency refs, each subtask has description
808
+ * 2. Feasibility: referenced files exist (warning only)
809
+ * 3. Granularity: no subtask complexity > 7 (should split further)
810
+ */
811
+ export function validateDecomposition(result) {
812
+ const issues = [];
813
+ const warnings = [];
814
+ const taskIds = new Set(result.subtasks.map(s => s.id));
815
+ // 1. Structural checks
816
+ // Cycle detection
817
+ if (result.dependencyGraph.cycles.length > 0) {
818
+ for (const cycle of result.dependencyGraph.cycles) {
819
+ issues.push(`Dependency cycle detected: ${cycle.join(' → ')}`);
820
+ }
821
+ }
822
+ // Valid dependency references
823
+ for (const subtask of result.subtasks) {
824
+ for (const dep of subtask.dependencies) {
825
+ if (!taskIds.has(dep)) {
826
+ issues.push(`Task ${subtask.id} references non-existent dependency: ${dep}`);
827
+ }
828
+ if (dep === subtask.id) {
829
+ issues.push(`Task ${subtask.id} depends on itself`);
830
+ }
831
+ }
832
+ // Each subtask must have a meaningful description
833
+ if (!subtask.description || subtask.description.trim().length < 5) {
834
+ issues.push(`Task ${subtask.id} has empty or trivial description`);
835
+ }
836
+ }
837
+ // 2. Feasibility: check if referenced files exist (warnings only — files may be created by earlier tasks)
838
+ for (const subtask of result.subtasks) {
839
+ if (subtask.relevantFiles) {
840
+ for (const file of subtask.relevantFiles) {
841
+ try {
842
+ const fs = require('node:fs');
843
+ const path = require('node:path');
844
+ if (!fs.existsSync(path.resolve(file))) {
845
+ warnings.push(`Task ${subtask.id} references non-existent file: ${file}`);
846
+ }
847
+ }
848
+ catch {
849
+ // Can't check — skip
850
+ }
851
+ }
852
+ }
853
+ }
854
+ // 3. Granularity: flag overly complex subtasks
855
+ for (const subtask of result.subtasks) {
856
+ if (subtask.complexity > 7) {
857
+ warnings.push(`Task ${subtask.id} has complexity ${subtask.complexity} (>7) — consider splitting further`);
858
+ }
859
+ }
860
+ // Additional structural check: at least 2 subtasks
861
+ if (result.subtasks.length < 2) {
862
+ issues.push(`Decomposition produced only ${result.subtasks.length} subtask(s) — too few for swarm mode`);
863
+ }
864
+ return {
865
+ valid: issues.length === 0,
866
+ issues,
867
+ warnings,
868
+ };
869
+ }
792
870
  // =============================================================================
793
871
  // FACTORY FUNCTIONS
794
872
  // =============================================================================
@@ -854,37 +932,415 @@ export function createDecompositionPrompt(task, context) {
854
932
  return parts.join('\n');
855
933
  }
856
934
  /**
857
- * Parse LLM response into decomposition result.
935
+ * Normalize a raw subtask object from JSON into a consistent shape.
858
936
  */
859
- export function parseDecompositionResponse(response) {
860
- try {
861
- // Try to extract JSON from the response
862
- const jsonMatch = response.match(/\{[\s\S]*\}/);
863
- if (!jsonMatch) {
864
- throw new Error('No JSON found in response');
937
+ function normalizeSubtask(s) {
938
+ return {
939
+ description: s.description || s.desc || s.title || s.name || '',
940
+ type: s.type || s.task_type || s.category || 'implement',
941
+ complexity: s.complexity || s.difficulty || 3,
942
+ dependencies: s.dependencies || s.deps || s.depends_on || [],
943
+ parallelizable: s.parallelizable ?? s.parallel ?? true,
944
+ relevantFiles: s.relevantFiles || s.relevant_files || s.files,
945
+ suggestedRole: s.suggestedRole || s.suggested_role || s.role,
946
+ };
947
+ }
948
+ /**
949
+ * Try to extract subtasks from a parsed JSON object/array.
950
+ * Returns null if the structure doesn't contain usable subtask data.
951
+ */
952
+ function extractSubtasksFromParsed(parsed) {
953
+ // Handle array-at-root: some models return [{...}, {...}] instead of {"subtasks": [...]}
954
+ if (Array.isArray(parsed)) {
955
+ parsed = { subtasks: parsed, strategy: 'adaptive', reasoning: '(array-at-root)' };
956
+ }
957
+ // Normalize alternative key names: tasks, steps, task_list → subtasks
958
+ const subtasksArray = parsed.subtasks
959
+ ?? parsed.tasks
960
+ ?? parsed.steps
961
+ ?? parsed.task_list
962
+ ?? parsed.decomposition;
963
+ if (!subtasksArray || !Array.isArray(subtasksArray) || subtasksArray.length === 0) {
964
+ return null;
965
+ }
966
+ return {
967
+ subtasks: subtasksArray.map(normalizeSubtask),
968
+ strategy: parsed.strategy || 'adaptive',
969
+ reasoning: parsed.reasoning || '',
970
+ };
971
+ }
972
+ /**
973
+ * Layer 1: Lenient JSON repair.
974
+ * Fixes common LLM JSON mistakes before parsing:
975
+ * - Trailing commas before ] and }
976
+ * - JS-style comments (// and block comments)
977
+ * - Single-quoted strings → double-quoted
978
+ * - Unquoted object keys
979
+ */
980
+ export function repairJSON(jsonStr) {
981
+ let s = jsonStr;
982
+ // Strip JS-style line comments (// ...) outside strings
983
+ s = s.replace(/("(?:[^"\\]|\\.)*")|\/\/[^\n]*/g, (_match, str) => str ?? '');
984
+ // Strip JS-style block comments outside strings
985
+ s = s.replace(/("(?:[^"\\]|\\.)*")|\/\*[\s\S]*?\*\//g, (_match, str) => str ?? '');
986
+ // Replace single-quoted strings with double-quoted (outside existing double-quoted strings)
987
+ s = s.replace(/("(?:[^"\\]|\\.)*")|'((?:[^'\\]|\\.)*)'/g, (_match, dq, sq) => {
988
+ if (dq)
989
+ return dq; // Already double-quoted, keep as-is
990
+ const escaped = sq.replace(/(?<!\\)"/g, '\\"');
991
+ return `"${escaped}"`;
992
+ });
993
+ // Fix unquoted object keys: { key: "value" } → { "key": "value" }
994
+ s = s.replace(/("(?:[^"\\]|\\.)*")|\b([a-zA-Z_][a-zA-Z0-9_]*)\s*:/g, (match, str, key) => {
995
+ if (str)
996
+ return match; // Inside a string, keep as-is
997
+ return `"${key}":`;
998
+ });
999
+ // Strip trailing commas before ] and }
1000
+ s = s.replace(/,\s*([}\]])/g, '$1');
1001
+ return s;
1002
+ }
1003
+ /**
1004
+ * Layer 2: Extract subtasks from natural language (numbered/bulleted lists).
1005
+ * Handles formats like:
1006
+ * - "1. Description" / "1) Description"
1007
+ * - "- Description" / "* Description"
1008
+ * - "Task 1: Description" / "Step 1: Description"
1009
+ * - "- [ ] Description" / "- [x] Description" (markdown task lists)
1010
+ */
1011
+ export function extractSubtasksFromNaturalLanguage(response) {
1012
+ const items = [];
1013
+ // Try markdown task lists first: - [ ] Task / - [x] Task
1014
+ const taskListPattern = /^[ \t]*[-*]\s*\[[ x]\]\s+(.+)$/gm;
1015
+ let match;
1016
+ while ((match = taskListPattern.exec(response)) !== null) {
1017
+ const desc = match[1].trim();
1018
+ if (desc.length > 5)
1019
+ items.push(desc);
1020
+ }
1021
+ if (items.length >= 2)
1022
+ return buildSubtasksFromList(items);
1023
+ // Try numbered lists: 1. Desc / 1) Desc / 1: Desc
1024
+ items.length = 0;
1025
+ const numberedPattern = /^[ \t]*\d+[.):\-]\s+(.+)$/gm;
1026
+ while ((match = numberedPattern.exec(response)) !== null) {
1027
+ const desc = match[1].trim();
1028
+ if (desc.length > 5)
1029
+ items.push(desc);
1030
+ }
1031
+ if (items.length >= 2)
1032
+ return buildSubtasksFromList(items);
1033
+ // Try bulleted lists: - Desc / * Desc (but not markdown task lists already tried)
1034
+ items.length = 0;
1035
+ const bulletPattern = /^[ \t]*[-*]\s+(?!\[[ x]\])(.+)$/gm;
1036
+ while ((match = bulletPattern.exec(response)) !== null) {
1037
+ const desc = match[1].trim();
1038
+ if (desc.length > 5)
1039
+ items.push(desc);
1040
+ }
1041
+ if (items.length >= 2)
1042
+ return buildSubtasksFromList(items);
1043
+ // Try "Task N:" / "Step N:" / "Subtask N:" style headers
1044
+ items.length = 0;
1045
+ const headerPattern = /^[ \t]*(?:task|step|subtask|phase)\s*\d+[:.]\s*(.+)$/gim;
1046
+ while ((match = headerPattern.exec(response)) !== null) {
1047
+ const desc = match[1].trim();
1048
+ if (desc.length > 5)
1049
+ items.push(desc);
1050
+ }
1051
+ if (items.length >= 2)
1052
+ return buildSubtasksFromList(items);
1053
+ // Try markdown headers: ## Subtask 1 / ### Step: Description
1054
+ items.length = 0;
1055
+ const mdHeaderPattern = /^#{2,4}\s+(?:(?:subtask|step|task|phase)\s*\d*[:.]*\s*)?(.+)$/gim;
1056
+ while ((match = mdHeaderPattern.exec(response)) !== null) {
1057
+ const desc = match[1].trim();
1058
+ // Skip generic headers like "Summary", "Strategy", "Overview"
1059
+ if (desc.length > 5 && !/^(summary|strategy|overview|reasoning|conclusion|notes?)$/i.test(desc)) {
1060
+ items.push(desc);
865
1061
  }
866
- const parsed = JSON.parse(jsonMatch[0]);
867
- return {
868
- subtasks: (parsed.subtasks || []).map((s) => ({
869
- description: s.description || '',
870
- type: s.type || 'implement',
871
- complexity: s.complexity || 3,
872
- dependencies: s.dependencies || [],
873
- parallelizable: s.parallelizable ?? true,
874
- relevantFiles: s.relevantFiles,
875
- suggestedRole: s.suggestedRole,
876
- })),
877
- strategy: parsed.strategy || 'adaptive',
878
- reasoning: parsed.reasoning || '',
879
- };
880
1062
  }
881
- catch (error) {
882
- // Return default if parsing fails — preserve error info for diagnostics
1063
+ if (items.length >= 2)
1064
+ return buildSubtasksFromList(items);
1065
+ return null;
1066
+ }
1067
+ /**
1068
+ * Build an LLMDecomposeResult from a flat list of description strings.
1069
+ * Assigns sequential dependencies and infers task type from keywords.
1070
+ */
1071
+ function buildSubtasksFromList(items) {
1072
+ const TYPE_KEYWORDS = {
1073
+ research: ['research', 'investigate', 'explore', 'analyze', 'understand', 'study', 'review existing'],
1074
+ design: ['design', 'plan', 'architect', 'schema', 'structure'],
1075
+ test: ['test', 'verify', 'validate', 'assert', 'check'],
1076
+ refactor: ['refactor', 'clean up', 'reorganize', 'simplify'],
1077
+ document: ['document', 'readme', 'docs', 'comment'],
1078
+ integrate: ['integrate', 'wire', 'connect', 'combine', 'merge'],
1079
+ deploy: ['deploy', 'release', 'publish', 'ship'],
1080
+ };
1081
+ return {
1082
+ subtasks: items.map((desc, i) => {
1083
+ const lower = desc.toLowerCase();
1084
+ let type = 'implement';
1085
+ for (const [t, keywords] of Object.entries(TYPE_KEYWORDS)) {
1086
+ if (keywords.some(k => lower.includes(k))) {
1087
+ type = t;
1088
+ break;
1089
+ }
1090
+ }
1091
+ return {
1092
+ description: desc,
1093
+ type,
1094
+ complexity: 3,
1095
+ dependencies: i > 0 ? [String(i - 1)] : [],
1096
+ parallelizable: i === 0 || type === 'research' || type === 'test',
1097
+ };
1098
+ }),
1099
+ strategy: 'sequential',
1100
+ reasoning: '(extracted from natural language list)',
1101
+ };
1102
+ }
1103
+ /**
1104
+ * Layer 3: Last-ditch single mega-task extraction.
1105
+ * If there's meaningful text but no structure could be found,
1106
+ * wrap the response as a single "implement" subtask so the swarm
1107
+ * has something to work with rather than aborting entirely.
1108
+ */
1109
+ function extractMegaTask(response) {
1110
+ // Strip code blocks, JSON fragments, and whitespace to get prose content
1111
+ const prose = response
1112
+ .replace(/```[\s\S]*?```/g, '')
1113
+ .replace(/\{[\s\S]*?\}/g, '')
1114
+ .replace(/\[[\s\S]*?\]/g, '')
1115
+ .trim();
1116
+ // Only create mega-task if there's substantial text (not just JSON garbage)
1117
+ if (prose.length < 20)
1118
+ return null;
1119
+ const desc = prose.length > 200
1120
+ ? prose.slice(0, 200).replace(/\s+\S*$/, '') + '...'
1121
+ : prose;
1122
+ return {
1123
+ subtasks: [{
1124
+ description: desc,
1125
+ type: 'implement',
1126
+ complexity: 5,
1127
+ dependencies: [],
1128
+ parallelizable: false,
1129
+ }],
1130
+ strategy: 'adaptive',
1131
+ reasoning: '(single mega-task — parser could not extract structured subtasks)',
1132
+ };
1133
+ }
1134
+ /**
1135
+ * Parse LLM response into decomposition result.
1136
+ *
1137
+ * Uses progressive fallback layers to handle messy LLM output:
1138
+ * 1. Standard JSON extraction (code blocks, raw JSON)
1139
+ * 2. Lenient JSON repair (trailing commas, comments, single quotes, unquoted keys)
1140
+ * 3. Truncated JSON recovery (missing closing brackets)
1141
+ * 4. Natural language extraction (numbered/bulleted lists, markdown task lists)
1142
+ * 5. Single mega-task fallback (wrap prose as one subtask)
1143
+ */
1144
+ export function parseDecompositionResponse(response) {
1145
+ if (!response || response.trim().length === 0) {
883
1146
  return {
884
1147
  subtasks: [],
885
1148
  strategy: 'adaptive',
886
- reasoning: `Failed to parse LLM response: ${error.message}`,
1149
+ reasoning: '',
1150
+ parseError: 'Empty response from LLM',
887
1151
  };
888
1152
  }
1153
+ // ── Step 1: Extract JSON string (code block or raw) ──────────────
1154
+ let jsonStr;
1155
+ const codeBlockMatch = response.match(/```(?:json)?\s*\n?([\s\S]*?)```/);
1156
+ if (codeBlockMatch) {
1157
+ jsonStr = codeBlockMatch[1].trim();
1158
+ }
1159
+ if (!jsonStr) {
1160
+ // If the response starts with `[`, try array regex first to avoid
1161
+ // \{[\s\S]*\} greedily matching across multiple objects in the array
1162
+ const trimmed = response.trim();
1163
+ const jsonMatch = trimmed.startsWith('[')
1164
+ ? (response.match(/\[[\s\S]*\]/) || response.match(/\{[\s\S]*\}/))
1165
+ : (response.match(/\{[\s\S]*\}/) || response.match(/\[[\s\S]*\]/));
1166
+ if (jsonMatch)
1167
+ jsonStr = jsonMatch[0];
1168
+ }
1169
+ // ── Step 2: Try strict JSON parse ────────────────────────────────
1170
+ if (jsonStr) {
1171
+ try {
1172
+ const parsed = JSON.parse(jsonStr);
1173
+ const result = extractSubtasksFromParsed(parsed);
1174
+ if (result)
1175
+ return result;
1176
+ }
1177
+ catch {
1178
+ // Strict parse failed — continue to lenient repair
1179
+ }
1180
+ // ── Step 3: Lenient JSON repair + parse ──────────────────────────
1181
+ try {
1182
+ const repaired = repairJSON(jsonStr);
1183
+ const parsed = JSON.parse(repaired);
1184
+ const result = extractSubtasksFromParsed(parsed);
1185
+ if (result) {
1186
+ result.reasoning = result.reasoning
1187
+ ? result.reasoning + ' (repaired JSON)'
1188
+ : '(repaired JSON)';
1189
+ return result;
1190
+ }
1191
+ }
1192
+ catch {
1193
+ // Repaired parse also failed — continue to truncation recovery
1194
+ }
1195
+ }
1196
+ // ── Step 4: Truncated JSON recovery ────────────────────────────────
1197
+ const recovered = tryRecoverTruncatedJSON(response);
1198
+ if (recovered) {
1199
+ try {
1200
+ const parsed = JSON.parse(recovered);
1201
+ const result = extractSubtasksFromParsed(parsed);
1202
+ if (result) {
1203
+ result.reasoning = result.reasoning
1204
+ ? result.reasoning + ' (recovered from truncated response)'
1205
+ : '(recovered from truncated response)';
1206
+ return result;
1207
+ }
1208
+ }
1209
+ catch {
1210
+ // Truncation recovery also failed — try repaired version
1211
+ try {
1212
+ const repairedRecovered = repairJSON(recovered);
1213
+ const parsed = JSON.parse(repairedRecovered);
1214
+ const result = extractSubtasksFromParsed(parsed);
1215
+ if (result) {
1216
+ result.reasoning = '(recovered from truncated + repaired JSON)';
1217
+ return result;
1218
+ }
1219
+ }
1220
+ catch {
1221
+ // All JSON approaches exhausted
1222
+ }
1223
+ }
1224
+ }
1225
+ // ── Step 5: Natural language extraction ────────────────────────────
1226
+ const nlResult = extractSubtasksFromNaturalLanguage(response);
1227
+ if (nlResult)
1228
+ return nlResult;
1229
+ // ── Step 6: Single mega-task fallback ──────────────────────────────
1230
+ const megaResult = extractMegaTask(response);
1231
+ if (megaResult)
1232
+ return megaResult;
1233
+ // ── Truly nothing worked ───────────────────────────────────────────
1234
+ return {
1235
+ subtasks: [],
1236
+ strategy: 'adaptive',
1237
+ reasoning: '',
1238
+ parseError: `All parse strategies failed. First 200 chars: ${response.slice(0, 200)}`,
1239
+ };
1240
+ }
1241
+ /**
1242
+ * Attempt to recover a truncated JSON response by trimming incomplete trailing
1243
+ * content and adding missing closing brackets/braces.
1244
+ *
1245
+ * Works for the common case where the LLM output was cut off mid-JSON-array,
1246
+ * e.g.: `{"subtasks": [ {...}, {...}, {"desc` → trim last incomplete object → close array & object.
1247
+ */
1248
+ function tryRecoverTruncatedJSON(response) {
1249
+ // Extract JSON portion (from code block or raw)
1250
+ let jsonStr;
1251
+ const codeBlockMatch = response.match(/```(?:json)?\s*\n?([\s\S]*)/);
1252
+ if (codeBlockMatch) {
1253
+ // No closing ``` required — that's the truncation
1254
+ jsonStr = codeBlockMatch[1].replace(/```\s*$/, '').trim();
1255
+ }
1256
+ if (!jsonStr) {
1257
+ const jsonMatch = response.match(/\{[\s\S]*/);
1258
+ if (jsonMatch)
1259
+ jsonStr = jsonMatch[0].trim();
1260
+ }
1261
+ if (!jsonStr)
1262
+ return null;
1263
+ // Find the last complete JSON object in the subtasks array.
1264
+ // Strategy: find last `}` that closes a complete array element, trim there, close brackets.
1265
+ // We search backwards for `},` or `}\n` patterns that likely end a complete subtask object.
1266
+ let lastGoodPos = -1;
1267
+ let braceDepth = 0;
1268
+ let bracketDepth = 0;
1269
+ let inString = false;
1270
+ let escape = false;
1271
+ for (let i = 0; i < jsonStr.length; i++) {
1272
+ const ch = jsonStr[i];
1273
+ if (escape) {
1274
+ escape = false;
1275
+ continue;
1276
+ }
1277
+ if (ch === '\\' && inString) {
1278
+ escape = true;
1279
+ continue;
1280
+ }
1281
+ if (ch === '"') {
1282
+ inString = !inString;
1283
+ continue;
1284
+ }
1285
+ if (inString)
1286
+ continue;
1287
+ if (ch === '{')
1288
+ braceDepth++;
1289
+ else if (ch === '}') {
1290
+ braceDepth--;
1291
+ // When we close an object at brace depth 1 (inside the top-level object),
1292
+ // this is likely a complete subtask object inside the array
1293
+ if (braceDepth === 1 && bracketDepth === 1) {
1294
+ lastGoodPos = i;
1295
+ }
1296
+ }
1297
+ else if (ch === '[')
1298
+ bracketDepth++;
1299
+ else if (ch === ']')
1300
+ bracketDepth--;
1301
+ }
1302
+ if (lastGoodPos === -1)
1303
+ return null;
1304
+ // Trim to last complete subtask object, then close the JSON structure
1305
+ let trimmed = jsonStr.slice(0, lastGoodPos + 1);
1306
+ // Remove trailing comma if present
1307
+ trimmed = trimmed.replace(/,\s*$/, '');
1308
+ // Close open brackets: we need to close the subtasks array and the root object
1309
+ // Count what's still open
1310
+ let openBraces = 0;
1311
+ let openBrackets = 0;
1312
+ inString = false;
1313
+ escape = false;
1314
+ for (let i = 0; i < trimmed.length; i++) {
1315
+ const ch = trimmed[i];
1316
+ if (escape) {
1317
+ escape = false;
1318
+ continue;
1319
+ }
1320
+ if (ch === '\\' && inString) {
1321
+ escape = true;
1322
+ continue;
1323
+ }
1324
+ if (ch === '"') {
1325
+ inString = !inString;
1326
+ continue;
1327
+ }
1328
+ if (inString)
1329
+ continue;
1330
+ if (ch === '{')
1331
+ openBraces++;
1332
+ else if (ch === '}')
1333
+ openBraces--;
1334
+ else if (ch === '[')
1335
+ openBrackets++;
1336
+ else if (ch === ']')
1337
+ openBrackets--;
1338
+ }
1339
+ // Close remaining open structures
1340
+ for (let i = 0; i < openBrackets; i++)
1341
+ trimmed += ']';
1342
+ for (let i = 0; i < openBraces; i++)
1343
+ trimmed += '}';
1344
+ return trimmed;
889
1345
  }
890
1346
  //# sourceMappingURL=smart-decomposer.js.map