@astralyn/pi 0.81.1-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 (1065) hide show
  1. package/CHANGELOG.md +5113 -0
  2. package/README.md +677 -0
  3. package/dist/bun/cli.d.ts +3 -0
  4. package/dist/bun/cli.d.ts.map +1 -0
  5. package/dist/bun/cli.js +11 -0
  6. package/dist/bun/cli.js.map +1 -0
  7. package/dist/bun/register-bedrock.d.ts +2 -0
  8. package/dist/bun/register-bedrock.d.ts.map +1 -0
  9. package/dist/bun/register-bedrock.js +4 -0
  10. package/dist/bun/register-bedrock.js.map +1 -0
  11. package/dist/bun/restore-sandbox-env.d.ts +17 -0
  12. package/dist/bun/restore-sandbox-env.d.ts.map +1 -0
  13. package/dist/bun/restore-sandbox-env.js +36 -0
  14. package/dist/bun/restore-sandbox-env.js.map +1 -0
  15. package/dist/cli/args.d.ts +57 -0
  16. package/dist/cli/args.d.ts.map +1 -0
  17. package/dist/cli/args.js +381 -0
  18. package/dist/cli/args.js.map +1 -0
  19. package/dist/cli/config-selector.d.ts +16 -0
  20. package/dist/cli/config-selector.d.ts.map +1 -0
  21. package/dist/cli/config-selector.js +31 -0
  22. package/dist/cli/config-selector.js.map +1 -0
  23. package/dist/cli/file-processor.d.ts +15 -0
  24. package/dist/cli/file-processor.d.ts.map +1 -0
  25. package/dist/cli/file-processor.js +70 -0
  26. package/dist/cli/file-processor.js.map +1 -0
  27. package/dist/cli/initial-message.d.ts +18 -0
  28. package/dist/cli/initial-message.d.ts.map +1 -0
  29. package/dist/cli/initial-message.js +22 -0
  30. package/dist/cli/initial-message.js.map +1 -0
  31. package/dist/cli/list-models.d.ts +9 -0
  32. package/dist/cli/list-models.d.ts.map +1 -0
  33. package/dist/cli/list-models.js +98 -0
  34. package/dist/cli/list-models.js.map +1 -0
  35. package/dist/cli/project-trust.d.ts +10 -0
  36. package/dist/cli/project-trust.d.ts.map +1 -0
  37. package/dist/cli/project-trust.js +48 -0
  38. package/dist/cli/project-trust.js.map +1 -0
  39. package/dist/cli/session-picker.d.ts +10 -0
  40. package/dist/cli/session-picker.d.ts.map +1 -0
  41. package/dist/cli/session-picker.js +36 -0
  42. package/dist/cli/session-picker.js.map +1 -0
  43. package/dist/cli/startup-ui.d.ts +20 -0
  44. package/dist/cli/startup-ui.d.ts.map +1 -0
  45. package/dist/cli/startup-ui.js +184 -0
  46. package/dist/cli/startup-ui.js.map +1 -0
  47. package/dist/cli.d.ts +3 -0
  48. package/dist/cli.d.ts.map +1 -0
  49. package/dist/cli.js +18 -0
  50. package/dist/cli.js.map +1 -0
  51. package/dist/config.d.ts +96 -0
  52. package/dist/config.d.ts.map +1 -0
  53. package/dist/config.js +455 -0
  54. package/dist/config.js.map +1 -0
  55. package/dist/core/agent-session-runtime.d.ts +119 -0
  56. package/dist/core/agent-session-runtime.d.ts.map +1 -0
  57. package/dist/core/agent-session-runtime.js +306 -0
  58. package/dist/core/agent-session-runtime.js.map +1 -0
  59. package/dist/core/agent-session-services.d.ts +85 -0
  60. package/dist/core/agent-session-services.d.ts.map +1 -0
  61. package/dist/core/agent-session-services.js +133 -0
  62. package/dist/core/agent-session-services.js.map +1 -0
  63. package/dist/core/agent-session.d.ts +642 -0
  64. package/dist/core/agent-session.d.ts.map +1 -0
  65. package/dist/core/agent-session.js +2679 -0
  66. package/dist/core/agent-session.js.map +1 -0
  67. package/dist/core/auth-guidance.d.ts +5 -0
  68. package/dist/core/auth-guidance.d.ts.map +1 -0
  69. package/dist/core/auth-guidance.js +21 -0
  70. package/dist/core/auth-guidance.js.map +1 -0
  71. package/dist/core/auth-storage.d.ts +56 -0
  72. package/dist/core/auth-storage.d.ts.map +1 -0
  73. package/dist/core/auth-storage.js +229 -0
  74. package/dist/core/auth-storage.js.map +1 -0
  75. package/dist/core/bash-executor.d.ts +32 -0
  76. package/dist/core/bash-executor.d.ts.map +1 -0
  77. package/dist/core/bash-executor.js +111 -0
  78. package/dist/core/bash-executor.js.map +1 -0
  79. package/dist/core/cache-stats.d.ts +49 -0
  80. package/dist/core/cache-stats.d.ts.map +1 -0
  81. package/dist/core/cache-stats.js +101 -0
  82. package/dist/core/cache-stats.js.map +1 -0
  83. package/dist/core/compaction/branch-summarization.d.ts +98 -0
  84. package/dist/core/compaction/branch-summarization.d.ts.map +1 -0
  85. package/dist/core/compaction/branch-summarization.js +246 -0
  86. package/dist/core/compaction/branch-summarization.js.map +1 -0
  87. package/dist/core/compaction/compaction.d.ts +137 -0
  88. package/dist/core/compaction/compaction.d.ts.map +1 -0
  89. package/dist/core/compaction/compaction.js +637 -0
  90. package/dist/core/compaction/compaction.js.map +1 -0
  91. package/dist/core/compaction/index.d.ts +7 -0
  92. package/dist/core/compaction/index.d.ts.map +1 -0
  93. package/dist/core/compaction/index.js +7 -0
  94. package/dist/core/compaction/index.js.map +1 -0
  95. package/dist/core/compaction/utils.d.ts +38 -0
  96. package/dist/core/compaction/utils.d.ts.map +1 -0
  97. package/dist/core/compaction/utils.js +142 -0
  98. package/dist/core/compaction/utils.js.map +1 -0
  99. package/dist/core/defaults.d.ts +3 -0
  100. package/dist/core/defaults.d.ts.map +1 -0
  101. package/dist/core/defaults.js +2 -0
  102. package/dist/core/defaults.js.map +1 -0
  103. package/dist/core/diagnostics.d.ts +15 -0
  104. package/dist/core/diagnostics.d.ts.map +1 -0
  105. package/dist/core/diagnostics.js +2 -0
  106. package/dist/core/diagnostics.js.map +1 -0
  107. package/dist/core/event-bus.d.ts +9 -0
  108. package/dist/core/event-bus.d.ts.map +1 -0
  109. package/dist/core/event-bus.js +25 -0
  110. package/dist/core/event-bus.js.map +1 -0
  111. package/dist/core/exec.d.ts +29 -0
  112. package/dist/core/exec.d.ts.map +1 -0
  113. package/dist/core/exec.js +75 -0
  114. package/dist/core/exec.js.map +1 -0
  115. package/dist/core/experimental.d.ts +2 -0
  116. package/dist/core/experimental.d.ts.map +1 -0
  117. package/dist/core/experimental.js +4 -0
  118. package/dist/core/experimental.js.map +1 -0
  119. package/dist/core/export-html/ansi-to-html.d.ts +22 -0
  120. package/dist/core/export-html/ansi-to-html.d.ts.map +1 -0
  121. package/dist/core/export-html/ansi-to-html.js +249 -0
  122. package/dist/core/export-html/ansi-to-html.js.map +1 -0
  123. package/dist/core/export-html/index.d.ts +37 -0
  124. package/dist/core/export-html/index.d.ts.map +1 -0
  125. package/dist/core/export-html/index.js +226 -0
  126. package/dist/core/export-html/index.js.map +1 -0
  127. package/dist/core/export-html/template.css +1066 -0
  128. package/dist/core/export-html/template.html +55 -0
  129. package/dist/core/export-html/template.js +1864 -0
  130. package/dist/core/export-html/tool-renderer.d.ts +34 -0
  131. package/dist/core/export-html/tool-renderer.d.ts.map +1 -0
  132. package/dist/core/export-html/tool-renderer.js +108 -0
  133. package/dist/core/export-html/tool-renderer.js.map +1 -0
  134. package/dist/core/export-html/vendor/highlight.min.js +1213 -0
  135. package/dist/core/export-html/vendor/marked.min.js +78 -0
  136. package/dist/core/extensions/index.d.ts +12 -0
  137. package/dist/core/extensions/index.d.ts.map +1 -0
  138. package/dist/core/extensions/index.js +9 -0
  139. package/dist/core/extensions/index.js.map +1 -0
  140. package/dist/core/extensions/loader.d.ts +23 -0
  141. package/dist/core/extensions/loader.d.ts.map +1 -0
  142. package/dist/core/extensions/loader.js +558 -0
  143. package/dist/core/extensions/loader.js.map +1 -0
  144. package/dist/core/extensions/runner.d.ts +171 -0
  145. package/dist/core/extensions/runner.d.ts.map +1 -0
  146. package/dist/core/extensions/runner.js +953 -0
  147. package/dist/core/extensions/runner.js.map +1 -0
  148. package/dist/core/extensions/types.d.ts +1259 -0
  149. package/dist/core/extensions/types.d.ts.map +1 -0
  150. package/dist/core/extensions/types.js +45 -0
  151. package/dist/core/extensions/types.js.map +1 -0
  152. package/dist/core/extensions/wrapper.d.ts +20 -0
  153. package/dist/core/extensions/wrapper.d.ts.map +1 -0
  154. package/dist/core/extensions/wrapper.js +41 -0
  155. package/dist/core/extensions/wrapper.js.map +1 -0
  156. package/dist/core/footer-data-provider.d.ts +54 -0
  157. package/dist/core/footer-data-provider.d.ts.map +1 -0
  158. package/dist/core/footer-data-provider.js +338 -0
  159. package/dist/core/footer-data-provider.js.map +1 -0
  160. package/dist/core/http-dispatcher.d.ts +22 -0
  161. package/dist/core/http-dispatcher.d.ts.map +1 -0
  162. package/dist/core/http-dispatcher.js +91 -0
  163. package/dist/core/http-dispatcher.js.map +1 -0
  164. package/dist/core/index.d.ts +13 -0
  165. package/dist/core/index.d.ts.map +1 -0
  166. package/dist/core/index.js +13 -0
  167. package/dist/core/index.js.map +1 -0
  168. package/dist/core/keybindings.d.ts +363 -0
  169. package/dist/core/keybindings.d.ts.map +1 -0
  170. package/dist/core/keybindings.js +300 -0
  171. package/dist/core/keybindings.js.map +1 -0
  172. package/dist/core/messages.d.ts +77 -0
  173. package/dist/core/messages.d.ts.map +1 -0
  174. package/dist/core/messages.js +123 -0
  175. package/dist/core/messages.js.map +1 -0
  176. package/dist/core/model-config.d.ts +512 -0
  177. package/dist/core/model-config.d.ts.map +1 -0
  178. package/dist/core/model-config.js +243 -0
  179. package/dist/core/model-config.js.map +1 -0
  180. package/dist/core/model-registry.d.ts +43 -0
  181. package/dist/core/model-registry.d.ts.map +1 -0
  182. package/dist/core/model-registry.js +104 -0
  183. package/dist/core/model-registry.js.map +1 -0
  184. package/dist/core/model-resolver.d.ts +121 -0
  185. package/dist/core/model-resolver.d.ts.map +1 -0
  186. package/dist/core/model-resolver.js +534 -0
  187. package/dist/core/model-resolver.js.map +1 -0
  188. package/dist/core/model-runtime.d.ts +82 -0
  189. package/dist/core/model-runtime.d.ts.map +1 -0
  190. package/dist/core/model-runtime.js +441 -0
  191. package/dist/core/model-runtime.js.map +1 -0
  192. package/dist/core/models-store.d.ts +17 -0
  193. package/dist/core/models-store.d.ts.map +1 -0
  194. package/dist/core/models-store.js +45 -0
  195. package/dist/core/models-store.js.map +1 -0
  196. package/dist/core/output-guard.d.ts +7 -0
  197. package/dist/core/output-guard.d.ts.map +1 -0
  198. package/dist/core/output-guard.js +89 -0
  199. package/dist/core/output-guard.js.map +1 -0
  200. package/dist/core/package-manager.d.ts +210 -0
  201. package/dist/core/package-manager.d.ts.map +1 -0
  202. package/dist/core/package-manager.js +2135 -0
  203. package/dist/core/package-manager.js.map +1 -0
  204. package/dist/core/project-trust.d.ts +15 -0
  205. package/dist/core/project-trust.d.ts.map +1 -0
  206. package/dist/core/project-trust.js +59 -0
  207. package/dist/core/project-trust.js.map +1 -0
  208. package/dist/core/prompt-templates.d.ts +54 -0
  209. package/dist/core/prompt-templates.d.ts.map +1 -0
  210. package/dist/core/prompt-templates.js +236 -0
  211. package/dist/core/prompt-templates.js.map +1 -0
  212. package/dist/core/provider-attribution.d.ts +4 -0
  213. package/dist/core/provider-attribution.d.ts.map +1 -0
  214. package/dist/core/provider-attribution.js +72 -0
  215. package/dist/core/provider-attribution.js.map +1 -0
  216. package/dist/core/provider-composer.d.ts +55 -0
  217. package/dist/core/provider-composer.d.ts.map +1 -0
  218. package/dist/core/provider-composer.js +375 -0
  219. package/dist/core/provider-composer.js.map +1 -0
  220. package/dist/core/radius.d.ts +2 -0
  221. package/dist/core/radius.d.ts.map +1 -0
  222. package/dist/core/radius.js +2 -0
  223. package/dist/core/radius.js.map +1 -0
  224. package/dist/core/remote-catalog-provider.d.ts +5 -0
  225. package/dist/core/remote-catalog-provider.d.ts.map +1 -0
  226. package/dist/core/remote-catalog-provider.js +102 -0
  227. package/dist/core/remote-catalog-provider.js.map +1 -0
  228. package/dist/core/resolve-config-value.d.ts +30 -0
  229. package/dist/core/resolve-config-value.d.ts.map +1 -0
  230. package/dist/core/resolve-config-value.js +247 -0
  231. package/dist/core/resolve-config-value.js.map +1 -0
  232. package/dist/core/resource-loader.d.ts +206 -0
  233. package/dist/core/resource-loader.d.ts.map +1 -0
  234. package/dist/core/resource-loader.js +817 -0
  235. package/dist/core/resource-loader.js.map +1 -0
  236. package/dist/core/runtime-credentials.d.ts +15 -0
  237. package/dist/core/runtime-credentials.d.ts.map +1 -0
  238. package/dist/core/runtime-credentials.js +36 -0
  239. package/dist/core/runtime-credentials.js.map +1 -0
  240. package/dist/core/sdk.d.ts +106 -0
  241. package/dist/core/sdk.d.ts.map +1 -0
  242. package/dist/core/sdk.js +267 -0
  243. package/dist/core/sdk.js.map +1 -0
  244. package/dist/core/session-cwd.d.ts +19 -0
  245. package/dist/core/session-cwd.d.ts.map +1 -0
  246. package/dist/core/session-cwd.js +38 -0
  247. package/dist/core/session-cwd.js.map +1 -0
  248. package/dist/core/session-manager.d.ts +356 -0
  249. package/dist/core/session-manager.d.ts.map +1 -0
  250. package/dist/core/session-manager.js +1338 -0
  251. package/dist/core/session-manager.js.map +1 -0
  252. package/dist/core/settings-manager.d.ts +297 -0
  253. package/dist/core/settings-manager.d.ts.map +1 -0
  254. package/dist/core/settings-manager.js +902 -0
  255. package/dist/core/settings-manager.js.map +1 -0
  256. package/dist/core/skills.d.ts +60 -0
  257. package/dist/core/skills.d.ts.map +1 -0
  258. package/dist/core/skills.js +387 -0
  259. package/dist/core/skills.js.map +1 -0
  260. package/dist/core/slash-commands.d.ts +15 -0
  261. package/dist/core/slash-commands.d.ts.map +1 -0
  262. package/dist/core/slash-commands.js +26 -0
  263. package/dist/core/slash-commands.js.map +1 -0
  264. package/dist/core/source-info.d.ts +18 -0
  265. package/dist/core/source-info.d.ts.map +1 -0
  266. package/dist/core/source-info.js +19 -0
  267. package/dist/core/source-info.js.map +1 -0
  268. package/dist/core/system-prompt.d.ts +28 -0
  269. package/dist/core/system-prompt.d.ts.map +1 -0
  270. package/dist/core/system-prompt.js +110 -0
  271. package/dist/core/system-prompt.js.map +1 -0
  272. package/dist/core/telemetry.d.ts +3 -0
  273. package/dist/core/telemetry.d.ts.map +1 -0
  274. package/dist/core/telemetry.js +9 -0
  275. package/dist/core/telemetry.js.map +1 -0
  276. package/dist/core/timings.d.ts +10 -0
  277. package/dist/core/timings.d.ts.map +1 -0
  278. package/dist/core/timings.js +41 -0
  279. package/dist/core/timings.js.map +1 -0
  280. package/dist/core/tools/bash.d.ts +68 -0
  281. package/dist/core/tools/bash.d.ts.map +1 -0
  282. package/dist/core/tools/bash.js +361 -0
  283. package/dist/core/tools/bash.js.map +1 -0
  284. package/dist/core/tools/edit-diff.d.ts +106 -0
  285. package/dist/core/tools/edit-diff.d.ts.map +1 -0
  286. package/dist/core/tools/edit-diff.js +424 -0
  287. package/dist/core/tools/edit-diff.js.map +1 -0
  288. package/dist/core/tools/edit.d.ts +50 -0
  289. package/dist/core/tools/edit.d.ts.map +1 -0
  290. package/dist/core/tools/edit.js +261 -0
  291. package/dist/core/tools/edit.js.map +1 -0
  292. package/dist/core/tools/file-mutation-queue.d.ts +6 -0
  293. package/dist/core/tools/file-mutation-queue.d.ts.map +1 -0
  294. package/dist/core/tools/file-mutation-queue.js +52 -0
  295. package/dist/core/tools/file-mutation-queue.js.map +1 -0
  296. package/dist/core/tools/find.d.ts +35 -0
  297. package/dist/core/tools/find.d.ts.map +1 -0
  298. package/dist/core/tools/find.js +305 -0
  299. package/dist/core/tools/find.js.map +1 -0
  300. package/dist/core/tools/grep.d.ts +37 -0
  301. package/dist/core/tools/grep.d.ts.map +1 -0
  302. package/dist/core/tools/grep.js +304 -0
  303. package/dist/core/tools/grep.js.map +1 -0
  304. package/dist/core/tools/index.d.ts +40 -0
  305. package/dist/core/tools/index.d.ts.map +1 -0
  306. package/dist/core/tools/index.js +112 -0
  307. package/dist/core/tools/index.js.map +1 -0
  308. package/dist/core/tools/ls.d.ts +37 -0
  309. package/dist/core/tools/ls.d.ts.map +1 -0
  310. package/dist/core/tools/ls.js +167 -0
  311. package/dist/core/tools/ls.js.map +1 -0
  312. package/dist/core/tools/output-accumulator.d.ts +52 -0
  313. package/dist/core/tools/output-accumulator.d.ts.map +1 -0
  314. package/dist/core/tools/output-accumulator.js +184 -0
  315. package/dist/core/tools/output-accumulator.js.map +1 -0
  316. package/dist/core/tools/path-utils.d.ts +10 -0
  317. package/dist/core/tools/path-utils.d.ts.map +1 -0
  318. package/dist/core/tools/path-utils.js +99 -0
  319. package/dist/core/tools/path-utils.js.map +1 -0
  320. package/dist/core/tools/read.d.ts +35 -0
  321. package/dist/core/tools/read.d.ts.map +1 -0
  322. package/dist/core/tools/read.js +276 -0
  323. package/dist/core/tools/read.js.map +1 -0
  324. package/dist/core/tools/render-utils.d.ts +24 -0
  325. package/dist/core/tools/render-utils.d.ts.map +1 -0
  326. package/dist/core/tools/render-utils.js +65 -0
  327. package/dist/core/tools/render-utils.js.map +1 -0
  328. package/dist/core/tools/tool-definition-wrapper.d.ts +14 -0
  329. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -0
  330. package/dist/core/tools/tool-definition-wrapper.js +34 -0
  331. package/dist/core/tools/tool-definition-wrapper.js.map +1 -0
  332. package/dist/core/tools/truncate.d.ts +70 -0
  333. package/dist/core/tools/truncate.d.ts.map +1 -0
  334. package/dist/core/tools/truncate.js +215 -0
  335. package/dist/core/tools/truncate.js.map +1 -0
  336. package/dist/core/tools/write.d.ts +26 -0
  337. package/dist/core/tools/write.d.ts.map +1 -0
  338. package/dist/core/tools/write.js +197 -0
  339. package/dist/core/tools/write.js.map +1 -0
  340. package/dist/core/trust-manager.d.ts +36 -0
  341. package/dist/core/trust-manager.d.ts.map +1 -0
  342. package/dist/core/trust-manager.js +202 -0
  343. package/dist/core/trust-manager.js.map +1 -0
  344. package/dist/core/usage-totals.d.ts +19 -0
  345. package/dist/core/usage-totals.d.ts.map +1 -0
  346. package/dist/core/usage-totals.js +52 -0
  347. package/dist/core/usage-totals.js.map +1 -0
  348. package/dist/extensions/deepwiki/client.d.ts +14 -0
  349. package/dist/extensions/deepwiki/client.d.ts.map +1 -0
  350. package/dist/extensions/deepwiki/client.js +196 -0
  351. package/dist/extensions/deepwiki/client.js.map +1 -0
  352. package/dist/extensions/deepwiki/constants.d.ts +13 -0
  353. package/dist/extensions/deepwiki/constants.d.ts.map +1 -0
  354. package/dist/extensions/deepwiki/constants.js +18 -0
  355. package/dist/extensions/deepwiki/constants.js.map +1 -0
  356. package/dist/extensions/deepwiki/contents.d.ts +63 -0
  357. package/dist/extensions/deepwiki/contents.d.ts.map +1 -0
  358. package/dist/extensions/deepwiki/contents.js +174 -0
  359. package/dist/extensions/deepwiki/contents.js.map +1 -0
  360. package/dist/extensions/deepwiki/execute.d.ts +25 -0
  361. package/dist/extensions/deepwiki/execute.d.ts.map +1 -0
  362. package/dist/extensions/deepwiki/execute.js +78 -0
  363. package/dist/extensions/deepwiki/execute.js.map +1 -0
  364. package/dist/extensions/deepwiki/http.d.ts +12 -0
  365. package/dist/extensions/deepwiki/http.d.ts.map +1 -0
  366. package/dist/extensions/deepwiki/http.js +74 -0
  367. package/dist/extensions/deepwiki/http.js.map +1 -0
  368. package/dist/extensions/deepwiki/index.d.ts +9 -0
  369. package/dist/extensions/deepwiki/index.d.ts.map +1 -0
  370. package/dist/extensions/deepwiki/index.js +25 -0
  371. package/dist/extensions/deepwiki/index.js.map +1 -0
  372. package/dist/extensions/deepwiki/render.d.ts +14 -0
  373. package/dist/extensions/deepwiki/render.d.ts.map +1 -0
  374. package/dist/extensions/deepwiki/render.js +166 -0
  375. package/dist/extensions/deepwiki/render.js.map +1 -0
  376. package/dist/extensions/deepwiki/schema.d.ts +13 -0
  377. package/dist/extensions/deepwiki/schema.d.ts.map +1 -0
  378. package/dist/extensions/deepwiki/schema.js +208 -0
  379. package/dist/extensions/deepwiki/schema.js.map +1 -0
  380. package/dist/extensions/index.d.ts +3 -0
  381. package/dist/extensions/index.d.ts.map +1 -0
  382. package/dist/extensions/index.js +17 -0
  383. package/dist/extensions/index.js.map +1 -0
  384. package/dist/extensions/llama/client.d.ts +61 -0
  385. package/dist/extensions/llama/client.d.ts.map +1 -0
  386. package/dist/extensions/llama/client.js +302 -0
  387. package/dist/extensions/llama/client.js.map +1 -0
  388. package/dist/extensions/llama/huggingface.d.ts +23 -0
  389. package/dist/extensions/llama/huggingface.d.ts.map +1 -0
  390. package/dist/extensions/llama/huggingface.js +141 -0
  391. package/dist/extensions/llama/huggingface.js.map +1 -0
  392. package/dist/extensions/llama/index.d.ts +3 -0
  393. package/dist/extensions/llama/index.d.ts.map +1 -0
  394. package/dist/extensions/llama/index.js +208 -0
  395. package/dist/extensions/llama/index.js.map +1 -0
  396. package/dist/extensions/llama/provider.d.ts +10 -0
  397. package/dist/extensions/llama/provider.d.ts.map +1 -0
  398. package/dist/extensions/llama/provider.js +102 -0
  399. package/dist/extensions/llama/provider.js.map +1 -0
  400. package/dist/extensions/llama/ui.d.ts +42 -0
  401. package/dist/extensions/llama/ui.d.ts.map +1 -0
  402. package/dist/extensions/llama/ui.js +416 -0
  403. package/dist/extensions/llama/ui.js.map +1 -0
  404. package/dist/extensions/question/constants.d.ts +13 -0
  405. package/dist/extensions/question/constants.d.ts.map +1 -0
  406. package/dist/extensions/question/constants.js +17 -0
  407. package/dist/extensions/question/constants.js.map +1 -0
  408. package/dist/extensions/question/dialog-primitives.d.ts +6 -0
  409. package/dist/extensions/question/dialog-primitives.d.ts.map +1 -0
  410. package/dist/extensions/question/dialog-primitives.js +20 -0
  411. package/dist/extensions/question/dialog-primitives.js.map +1 -0
  412. package/dist/extensions/question/dialog.d.ts +10 -0
  413. package/dist/extensions/question/dialog.d.ts.map +1 -0
  414. package/dist/extensions/question/dialog.js +519 -0
  415. package/dist/extensions/question/dialog.js.map +1 -0
  416. package/dist/extensions/question/index.d.ts +9 -0
  417. package/dist/extensions/question/index.d.ts.map +1 -0
  418. package/dist/extensions/question/index.js +32 -0
  419. package/dist/extensions/question/index.js.map +1 -0
  420. package/dist/extensions/question/limits.d.ts +11 -0
  421. package/dist/extensions/question/limits.d.ts.map +1 -0
  422. package/dist/extensions/question/limits.js +11 -0
  423. package/dist/extensions/question/limits.js.map +1 -0
  424. package/dist/extensions/question/render-cache.d.ts +9 -0
  425. package/dist/extensions/question/render-cache.d.ts.map +1 -0
  426. package/dist/extensions/question/render-cache.js +18 -0
  427. package/dist/extensions/question/render-cache.js.map +1 -0
  428. package/dist/extensions/question/render.d.ts +17 -0
  429. package/dist/extensions/question/render.d.ts.map +1 -0
  430. package/dist/extensions/question/render.js +47 -0
  431. package/dist/extensions/question/render.js.map +1 -0
  432. package/dist/extensions/question/results.d.ts +8 -0
  433. package/dist/extensions/question/results.d.ts.map +1 -0
  434. package/dist/extensions/question/results.js +68 -0
  435. package/dist/extensions/question/results.js.map +1 -0
  436. package/dist/extensions/question/schema.d.ts +22 -0
  437. package/dist/extensions/question/schema.d.ts.map +1 -0
  438. package/dist/extensions/question/schema.js +98 -0
  439. package/dist/extensions/question/schema.js.map +1 -0
  440. package/dist/extensions/question/state.d.ts +9 -0
  441. package/dist/extensions/question/state.d.ts.map +1 -0
  442. package/dist/extensions/question/state.js +76 -0
  443. package/dist/extensions/question/state.js.map +1 -0
  444. package/dist/extensions/question/types.d.ts +60 -0
  445. package/dist/extensions/question/types.d.ts.map +1 -0
  446. package/dist/extensions/question/types.js +2 -0
  447. package/dist/extensions/question/types.js.map +1 -0
  448. package/dist/extensions/rewind/config.d.ts +16 -0
  449. package/dist/extensions/rewind/config.d.ts.map +1 -0
  450. package/dist/extensions/rewind/config.js +69 -0
  451. package/dist/extensions/rewind/config.js.map +1 -0
  452. package/dist/extensions/rewind/engine.d.ts +97 -0
  453. package/dist/extensions/rewind/engine.d.ts.map +1 -0
  454. package/dist/extensions/rewind/engine.js +747 -0
  455. package/dist/extensions/rewind/engine.js.map +1 -0
  456. package/dist/extensions/rewind/gc.d.ts +35 -0
  457. package/dist/extensions/rewind/gc.d.ts.map +1 -0
  458. package/dist/extensions/rewind/gc.js +169 -0
  459. package/dist/extensions/rewind/gc.js.map +1 -0
  460. package/dist/extensions/rewind/index.d.ts +3 -0
  461. package/dist/extensions/rewind/index.d.ts.map +1 -0
  462. package/dist/extensions/rewind/index.js +253 -0
  463. package/dist/extensions/rewind/index.js.map +1 -0
  464. package/dist/extensions/rewind/menu.d.ts +13 -0
  465. package/dist/extensions/rewind/menu.d.ts.map +1 -0
  466. package/dist/extensions/rewind/menu.js +118 -0
  467. package/dist/extensions/rewind/menu.js.map +1 -0
  468. package/dist/extensions/rewind/paths.d.ts +4 -0
  469. package/dist/extensions/rewind/paths.d.ts.map +1 -0
  470. package/dist/extensions/rewind/paths.js +15 -0
  471. package/dist/extensions/rewind/paths.js.map +1 -0
  472. package/dist/extensions/rewind/restore.d.ts +37 -0
  473. package/dist/extensions/rewind/restore.d.ts.map +1 -0
  474. package/dist/extensions/rewind/restore.js +52 -0
  475. package/dist/extensions/rewind/restore.js.map +1 -0
  476. package/dist/extensions/rewind/snapshot.d.ts +45 -0
  477. package/dist/extensions/rewind/snapshot.d.ts.map +1 -0
  478. package/dist/extensions/rewind/snapshot.js +21 -0
  479. package/dist/extensions/rewind/snapshot.js.map +1 -0
  480. package/dist/extensions/rewind/storage.d.ts +12 -0
  481. package/dist/extensions/rewind/storage.d.ts.map +1 -0
  482. package/dist/extensions/rewind/storage.js +33 -0
  483. package/dist/extensions/rewind/storage.js.map +1 -0
  484. package/dist/extensions/rewind/text.d.ts +7 -0
  485. package/dist/extensions/rewind/text.d.ts.map +1 -0
  486. package/dist/extensions/rewind/text.js +19 -0
  487. package/dist/extensions/rewind/text.js.map +1 -0
  488. package/dist/extensions/rewind/tool-path.d.ts +3 -0
  489. package/dist/extensions/rewind/tool-path.d.ts.map +1 -0
  490. package/dist/extensions/rewind/tool-path.js +9 -0
  491. package/dist/extensions/rewind/tool-path.js.map +1 -0
  492. package/dist/extensions/router/constants.d.ts +20 -0
  493. package/dist/extensions/router/constants.d.ts.map +1 -0
  494. package/dist/extensions/router/constants.js +27 -0
  495. package/dist/extensions/router/constants.js.map +1 -0
  496. package/dist/extensions/router/dialog.d.ts +38 -0
  497. package/dist/extensions/router/dialog.d.ts.map +1 -0
  498. package/dist/extensions/router/dialog.js +407 -0
  499. package/dist/extensions/router/dialog.js.map +1 -0
  500. package/dist/extensions/router/index.d.ts +15 -0
  501. package/dist/extensions/router/index.d.ts.map +1 -0
  502. package/dist/extensions/router/index.js +61 -0
  503. package/dist/extensions/router/index.js.map +1 -0
  504. package/dist/extensions/router/presets.d.ts +48 -0
  505. package/dist/extensions/router/presets.d.ts.map +1 -0
  506. package/dist/extensions/router/presets.js +109 -0
  507. package/dist/extensions/router/presets.js.map +1 -0
  508. package/dist/extensions/router/probe.d.ts +20 -0
  509. package/dist/extensions/router/probe.d.ts.map +1 -0
  510. package/dist/extensions/router/probe.js +125 -0
  511. package/dist/extensions/router/probe.js.map +1 -0
  512. package/dist/extensions/router/register.d.ts +34 -0
  513. package/dist/extensions/router/register.d.ts.map +1 -0
  514. package/dist/extensions/router/register.js +81 -0
  515. package/dist/extensions/router/register.js.map +1 -0
  516. package/dist/extensions/router/store.d.ts +12 -0
  517. package/dist/extensions/router/store.d.ts.map +1 -0
  518. package/dist/extensions/router/store.js +164 -0
  519. package/dist/extensions/router/store.js.map +1 -0
  520. package/dist/extensions/router/stream.d.ts +16 -0
  521. package/dist/extensions/router/stream.d.ts.map +1 -0
  522. package/dist/extensions/router/stream.js +198 -0
  523. package/dist/extensions/router/stream.js.map +1 -0
  524. package/dist/extensions/router/types.d.ts +23 -0
  525. package/dist/extensions/router/types.d.ts.map +1 -0
  526. package/dist/extensions/router/types.js +2 -0
  527. package/dist/extensions/router/types.js.map +1 -0
  528. package/dist/extensions/router/ui.d.ts +9 -0
  529. package/dist/extensions/router/ui.d.ts.map +1 -0
  530. package/dist/extensions/router/ui.js +538 -0
  531. package/dist/extensions/router/ui.js.map +1 -0
  532. package/dist/extensions/statusline/index.d.ts +3 -0
  533. package/dist/extensions/statusline/index.d.ts.map +1 -0
  534. package/dist/extensions/statusline/index.js +367 -0
  535. package/dist/extensions/statusline/index.js.map +1 -0
  536. package/dist/extensions/todo/constants.d.ts +16 -0
  537. package/dist/extensions/todo/constants.d.ts.map +1 -0
  538. package/dist/extensions/todo/constants.js +20 -0
  539. package/dist/extensions/todo/constants.js.map +1 -0
  540. package/dist/extensions/todo/index.d.ts +17 -0
  541. package/dist/extensions/todo/index.d.ts.map +1 -0
  542. package/dist/extensions/todo/index.js +83 -0
  543. package/dist/extensions/todo/index.js.map +1 -0
  544. package/dist/extensions/todo/overlay.d.ts +24 -0
  545. package/dist/extensions/todo/overlay.d.ts.map +1 -0
  546. package/dist/extensions/todo/overlay.js +139 -0
  547. package/dist/extensions/todo/overlay.js.map +1 -0
  548. package/dist/extensions/todo/schema.d.ts +41 -0
  549. package/dist/extensions/todo/schema.d.ts.map +1 -0
  550. package/dist/extensions/todo/schema.js +36 -0
  551. package/dist/extensions/todo/schema.js.map +1 -0
  552. package/dist/extensions/todo/state.d.ts +57 -0
  553. package/dist/extensions/todo/state.d.ts.map +1 -0
  554. package/dist/extensions/todo/state.js +452 -0
  555. package/dist/extensions/todo/state.js.map +1 -0
  556. package/dist/extensions/todo/view.d.ts +8 -0
  557. package/dist/extensions/todo/view.d.ts.map +1 -0
  558. package/dist/extensions/todo/view.js +119 -0
  559. package/dist/extensions/todo/view.js.map +1 -0
  560. package/dist/index.d.ts +35 -0
  561. package/dist/index.d.ts.map +1 -0
  562. package/dist/index.js +47 -0
  563. package/dist/index.js.map +1 -0
  564. package/dist/main.d.ts +12 -0
  565. package/dist/main.d.ts.map +1 -0
  566. package/dist/main.js +704 -0
  567. package/dist/main.js.map +1 -0
  568. package/dist/migrations.d.ts +33 -0
  569. package/dist/migrations.d.ts.map +1 -0
  570. package/dist/migrations.js +281 -0
  571. package/dist/migrations.js.map +1 -0
  572. package/dist/modes/index.d.ts +9 -0
  573. package/dist/modes/index.d.ts.map +1 -0
  574. package/dist/modes/index.js +8 -0
  575. package/dist/modes/index.js.map +1 -0
  576. package/dist/modes/interactive/assets/clankolas.png +0 -0
  577. package/dist/modes/interactive/components/armin.d.ts +34 -0
  578. package/dist/modes/interactive/components/armin.d.ts.map +1 -0
  579. package/dist/modes/interactive/components/armin.js +333 -0
  580. package/dist/modes/interactive/components/armin.js.map +1 -0
  581. package/dist/modes/interactive/components/assistant-message.d.ts +22 -0
  582. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -0
  583. package/dist/modes/interactive/components/assistant-message.js +141 -0
  584. package/dist/modes/interactive/components/assistant-message.js.map +1 -0
  585. package/dist/modes/interactive/components/bash-execution.d.ts +34 -0
  586. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -0
  587. package/dist/modes/interactive/components/bash-execution.js +175 -0
  588. package/dist/modes/interactive/components/bash-execution.js.map +1 -0
  589. package/dist/modes/interactive/components/bordered-loader.d.ts +16 -0
  590. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -0
  591. package/dist/modes/interactive/components/bordered-loader.js +54 -0
  592. package/dist/modes/interactive/components/bordered-loader.js.map +1 -0
  593. package/dist/modes/interactive/components/branch-summary-message.d.ts +16 -0
  594. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -0
  595. package/dist/modes/interactive/components/branch-summary-message.js +44 -0
  596. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -0
  597. package/dist/modes/interactive/components/compaction-summary-message.d.ts +16 -0
  598. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -0
  599. package/dist/modes/interactive/components/compaction-summary-message.js +45 -0
  600. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -0
  601. package/dist/modes/interactive/components/config-selector.d.ts +102 -0
  602. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -0
  603. package/dist/modes/interactive/components/config-selector.js +761 -0
  604. package/dist/modes/interactive/components/config-selector.js.map +1 -0
  605. package/dist/modes/interactive/components/countdown-timer.d.ts +14 -0
  606. package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -0
  607. package/dist/modes/interactive/components/countdown-timer.js +33 -0
  608. package/dist/modes/interactive/components/countdown-timer.js.map +1 -0
  609. package/dist/modes/interactive/components/custom-editor.d.ts +21 -0
  610. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -0
  611. package/dist/modes/interactive/components/custom-editor.js +70 -0
  612. package/dist/modes/interactive/components/custom-editor.js.map +1 -0
  613. package/dist/modes/interactive/components/custom-entry.d.ts +19 -0
  614. package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -0
  615. package/dist/modes/interactive/components/custom-entry.js +52 -0
  616. package/dist/modes/interactive/components/custom-entry.js.map +1 -0
  617. package/dist/modes/interactive/components/custom-message.d.ts +20 -0
  618. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -0
  619. package/dist/modes/interactive/components/custom-message.js +79 -0
  620. package/dist/modes/interactive/components/custom-message.js.map +1 -0
  621. package/dist/modes/interactive/components/daxnuts.d.ts +23 -0
  622. package/dist/modes/interactive/components/daxnuts.d.ts.map +1 -0
  623. package/dist/modes/interactive/components/daxnuts.js +140 -0
  624. package/dist/modes/interactive/components/daxnuts.js.map +1 -0
  625. package/dist/modes/interactive/components/diff.d.ts +12 -0
  626. package/dist/modes/interactive/components/diff.d.ts.map +1 -0
  627. package/dist/modes/interactive/components/diff.js +133 -0
  628. package/dist/modes/interactive/components/diff.js.map +1 -0
  629. package/dist/modes/interactive/components/dynamic-border.d.ts +15 -0
  630. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -0
  631. package/dist/modes/interactive/components/dynamic-border.js +21 -0
  632. package/dist/modes/interactive/components/dynamic-border.js.map +1 -0
  633. package/dist/modes/interactive/components/earendil-announcement.d.ts +5 -0
  634. package/dist/modes/interactive/components/earendil-announcement.d.ts.map +1 -0
  635. package/dist/modes/interactive/components/earendil-announcement.js +40 -0
  636. package/dist/modes/interactive/components/earendil-announcement.js.map +1 -0
  637. package/dist/modes/interactive/components/extension-editor.d.ts +22 -0
  638. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -0
  639. package/dist/modes/interactive/components/extension-editor.js +128 -0
  640. package/dist/modes/interactive/components/extension-editor.js.map +1 -0
  641. package/dist/modes/interactive/components/extension-input.d.ts +23 -0
  642. package/dist/modes/interactive/components/extension-input.d.ts.map +1 -0
  643. package/dist/modes/interactive/components/extension-input.js +61 -0
  644. package/dist/modes/interactive/components/extension-input.js.map +1 -0
  645. package/dist/modes/interactive/components/extension-selector.d.ts +26 -0
  646. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -0
  647. package/dist/modes/interactive/components/extension-selector.js +83 -0
  648. package/dist/modes/interactive/components/extension-selector.js.map +1 -0
  649. package/dist/modes/interactive/components/first-time-setup.d.ts +25 -0
  650. package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -0
  651. package/dist/modes/interactive/components/first-time-setup.js +103 -0
  652. package/dist/modes/interactive/components/first-time-setup.js.map +1 -0
  653. package/dist/modes/interactive/components/footer.d.ts +32 -0
  654. package/dist/modes/interactive/components/footer.d.ts.map +1 -0
  655. package/dist/modes/interactive/components/footer.js +222 -0
  656. package/dist/modes/interactive/components/footer.js.map +1 -0
  657. package/dist/modes/interactive/components/index.d.ts +34 -0
  658. package/dist/modes/interactive/components/index.d.ts.map +1 -0
  659. package/dist/modes/interactive/components/index.js +35 -0
  660. package/dist/modes/interactive/components/index.js.map +1 -0
  661. package/dist/modes/interactive/components/keybinding-hints.d.ts +13 -0
  662. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -0
  663. package/dist/modes/interactive/components/keybinding-hints.js +36 -0
  664. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -0
  665. package/dist/modes/interactive/components/login-dialog.d.ts +52 -0
  666. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -0
  667. package/dist/modes/interactive/components/login-dialog.js +188 -0
  668. package/dist/modes/interactive/components/login-dialog.js.map +1 -0
  669. package/dist/modes/interactive/components/model-selector.d.ts +54 -0
  670. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -0
  671. package/dist/modes/interactive/components/model-selector.js +310 -0
  672. package/dist/modes/interactive/components/model-selector.js.map +1 -0
  673. package/dist/modes/interactive/components/oauth-selector.d.ts +33 -0
  674. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -0
  675. package/dist/modes/interactive/components/oauth-selector.js +163 -0
  676. package/dist/modes/interactive/components/oauth-selector.js.map +1 -0
  677. package/dist/modes/interactive/components/scoped-models-selector.d.ts +42 -0
  678. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -0
  679. package/dist/modes/interactive/components/scoped-models-selector.js +293 -0
  680. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -0
  681. package/dist/modes/interactive/components/session-selector-search.d.ts +23 -0
  682. package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -0
  683. package/dist/modes/interactive/components/session-selector-search.js +155 -0
  684. package/dist/modes/interactive/components/session-selector-search.js.map +1 -0
  685. package/dist/modes/interactive/components/session-selector.d.ts +95 -0
  686. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -0
  687. package/dist/modes/interactive/components/session-selector.js +867 -0
  688. package/dist/modes/interactive/components/session-selector.js.map +1 -0
  689. package/dist/modes/interactive/components/settings-selector.d.ts +77 -0
  690. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -0
  691. package/dist/modes/interactive/components/settings-selector.js +593 -0
  692. package/dist/modes/interactive/components/settings-selector.js.map +1 -0
  693. package/dist/modes/interactive/components/show-images-selector.d.ts +10 -0
  694. package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -0
  695. package/dist/modes/interactive/components/show-images-selector.js +39 -0
  696. package/dist/modes/interactive/components/show-images-selector.js.map +1 -0
  697. package/dist/modes/interactive/components/skill-invocation-message.d.ts +17 -0
  698. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -0
  699. package/dist/modes/interactive/components/skill-invocation-message.js +47 -0
  700. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -0
  701. package/dist/modes/interactive/components/status-indicator.d.ts +28 -0
  702. package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -0
  703. package/dist/modes/interactive/components/status-indicator.js +60 -0
  704. package/dist/modes/interactive/components/status-indicator.js.map +1 -0
  705. package/dist/modes/interactive/components/theme-selector.d.ts +11 -0
  706. package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -0
  707. package/dist/modes/interactive/components/theme-selector.js +50 -0
  708. package/dist/modes/interactive/components/theme-selector.js.map +1 -0
  709. package/dist/modes/interactive/components/thinking-selector.d.ts +11 -0
  710. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -0
  711. package/dist/modes/interactive/components/thinking-selector.js +52 -0
  712. package/dist/modes/interactive/components/thinking-selector.js.map +1 -0
  713. package/dist/modes/interactive/components/tool-execution.d.ts +62 -0
  714. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -0
  715. package/dist/modes/interactive/components/tool-execution.js +361 -0
  716. package/dist/modes/interactive/components/tool-execution.js.map +1 -0
  717. package/dist/modes/interactive/components/tree-selector.d.ts +94 -0
  718. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -0
  719. package/dist/modes/interactive/components/tree-selector.js +1245 -0
  720. package/dist/modes/interactive/components/tree-selector.js.map +1 -0
  721. package/dist/modes/interactive/components/trust-selector.d.ts +23 -0
  722. package/dist/modes/interactive/components/trust-selector.d.ts.map +1 -0
  723. package/dist/modes/interactive/components/trust-selector.js +91 -0
  724. package/dist/modes/interactive/components/trust-selector.js.map +1 -0
  725. package/dist/modes/interactive/components/user-message-selector.d.ts +30 -0
  726. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -0
  727. package/dist/modes/interactive/components/user-message-selector.js +114 -0
  728. package/dist/modes/interactive/components/user-message-selector.js.map +1 -0
  729. package/dist/modes/interactive/components/user-message.d.ts +14 -0
  730. package/dist/modes/interactive/components/user-message.d.ts.map +1 -0
  731. package/dist/modes/interactive/components/user-message.js +42 -0
  732. package/dist/modes/interactive/components/user-message.js.map +1 -0
  733. package/dist/modes/interactive/components/visual-truncate.d.ts +24 -0
  734. package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -0
  735. package/dist/modes/interactive/components/visual-truncate.js +33 -0
  736. package/dist/modes/interactive/components/visual-truncate.js.map +1 -0
  737. package/dist/modes/interactive/interactive-mode.d.ts +394 -0
  738. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -0
  739. package/dist/modes/interactive/interactive-mode.js +5039 -0
  740. package/dist/modes/interactive/interactive-mode.js.map +1 -0
  741. package/dist/modes/interactive/model-search.d.ts +12 -0
  742. package/dist/modes/interactive/model-search.d.ts.map +1 -0
  743. package/dist/modes/interactive/model-search.js +15 -0
  744. package/dist/modes/interactive/model-search.js.map +1 -0
  745. package/dist/modes/interactive/theme/dark.json +87 -0
  746. package/dist/modes/interactive/theme/ice-cream-dark.json +101 -0
  747. package/dist/modes/interactive/theme/ice-cream-light.json +101 -0
  748. package/dist/modes/interactive/theme/light.json +86 -0
  749. package/dist/modes/interactive/theme/theme-controller.d.ts +29 -0
  750. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -0
  751. package/dist/modes/interactive/theme/theme-controller.js +102 -0
  752. package/dist/modes/interactive/theme/theme-controller.js.map +1 -0
  753. package/dist/modes/interactive/theme/theme-schema.json +340 -0
  754. package/dist/modes/interactive/theme/theme.d.ts +120 -0
  755. package/dist/modes/interactive/theme/theme.d.ts.map +1 -0
  756. package/dist/modes/interactive/theme/theme.js +1063 -0
  757. package/dist/modes/interactive/theme/theme.js.map +1 -0
  758. package/dist/modes/print-mode.d.ts +28 -0
  759. package/dist/modes/print-mode.d.ts.map +1 -0
  760. package/dist/modes/print-mode.js +132 -0
  761. package/dist/modes/print-mode.js.map +1 -0
  762. package/dist/modes/rpc/jsonl.d.ts +17 -0
  763. package/dist/modes/rpc/jsonl.d.ts.map +1 -0
  764. package/dist/modes/rpc/jsonl.js +49 -0
  765. package/dist/modes/rpc/jsonl.js.map +1 -0
  766. package/dist/modes/rpc/rpc-client.d.ts +246 -0
  767. package/dist/modes/rpc/rpc-client.d.ts.map +1 -0
  768. package/dist/modes/rpc/rpc-client.js +488 -0
  769. package/dist/modes/rpc/rpc-client.js.map +1 -0
  770. package/dist/modes/rpc/rpc-mode.d.ts +20 -0
  771. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -0
  772. package/dist/modes/rpc/rpc-mode.js +639 -0
  773. package/dist/modes/rpc/rpc-mode.js.map +1 -0
  774. package/dist/modes/rpc/rpc-types.d.ts +457 -0
  775. package/dist/modes/rpc/rpc-types.d.ts.map +1 -0
  776. package/dist/modes/rpc/rpc-types.js +8 -0
  777. package/dist/modes/rpc/rpc-types.js.map +1 -0
  778. package/dist/package-manager-cli.d.ts +8 -0
  779. package/dist/package-manager-cli.d.ts.map +1 -0
  780. package/dist/package-manager-cli.js +775 -0
  781. package/dist/package-manager-cli.js.map +1 -0
  782. package/dist/rpc-entry.d.ts +3 -0
  783. package/dist/rpc-entry.d.ts.map +1 -0
  784. package/dist/rpc-entry.js +10 -0
  785. package/dist/rpc-entry.js.map +1 -0
  786. package/dist/utils/ansi.d.ts +2 -0
  787. package/dist/utils/ansi.d.ts.map +1 -0
  788. package/dist/utils/ansi.js +52 -0
  789. package/dist/utils/ansi.js.map +1 -0
  790. package/dist/utils/changelog.d.ts +22 -0
  791. package/dist/utils/changelog.d.ts.map +1 -0
  792. package/dist/utils/changelog.js +165 -0
  793. package/dist/utils/changelog.js.map +1 -0
  794. package/dist/utils/child-process.d.ts +18 -0
  795. package/dist/utils/child-process.d.ts.map +1 -0
  796. package/dist/utils/child-process.js +106 -0
  797. package/dist/utils/child-process.js.map +1 -0
  798. package/dist/utils/clipboard-image.d.ts +11 -0
  799. package/dist/utils/clipboard-image.d.ts.map +1 -0
  800. package/dist/utils/clipboard-image.js +245 -0
  801. package/dist/utils/clipboard-image.js.map +1 -0
  802. package/dist/utils/clipboard-native.d.ts +11 -0
  803. package/dist/utils/clipboard-native.d.ts.map +1 -0
  804. package/dist/utils/clipboard-native.js +20 -0
  805. package/dist/utils/clipboard-native.js.map +1 -0
  806. package/dist/utils/clipboard.d.ts +4 -0
  807. package/dist/utils/clipboard.d.ts.map +1 -0
  808. package/dist/utils/clipboard.js +130 -0
  809. package/dist/utils/clipboard.js.map +1 -0
  810. package/dist/utils/deprecation.d.ts +4 -0
  811. package/dist/utils/deprecation.d.ts.map +1 -0
  812. package/dist/utils/deprecation.js +13 -0
  813. package/dist/utils/deprecation.js.map +1 -0
  814. package/dist/utils/exif-orientation.d.ts +5 -0
  815. package/dist/utils/exif-orientation.d.ts.map +1 -0
  816. package/dist/utils/exif-orientation.js +158 -0
  817. package/dist/utils/exif-orientation.js.map +1 -0
  818. package/dist/utils/frontmatter.d.ts +8 -0
  819. package/dist/utils/frontmatter.d.ts.map +1 -0
  820. package/dist/utils/frontmatter.js +26 -0
  821. package/dist/utils/frontmatter.js.map +1 -0
  822. package/dist/utils/fs-watch.d.ts +5 -0
  823. package/dist/utils/fs-watch.d.ts.map +1 -0
  824. package/dist/utils/fs-watch.js +25 -0
  825. package/dist/utils/fs-watch.js.map +1 -0
  826. package/dist/utils/git.d.ts +26 -0
  827. package/dist/utils/git.d.ts.map +1 -0
  828. package/dist/utils/git.js +195 -0
  829. package/dist/utils/git.js.map +1 -0
  830. package/dist/utils/html.d.ts +7 -0
  831. package/dist/utils/html.d.ts.map +1 -0
  832. package/dist/utils/html.js +40 -0
  833. package/dist/utils/html.js.map +1 -0
  834. package/dist/utils/image-convert.d.ts +10 -0
  835. package/dist/utils/image-convert.d.ts.map +1 -0
  836. package/dist/utils/image-convert.js +45 -0
  837. package/dist/utils/image-convert.js.map +1 -0
  838. package/dist/utils/image-process.d.ts +18 -0
  839. package/dist/utils/image-process.d.ts.map +1 -0
  840. package/dist/utils/image-process.js +83 -0
  841. package/dist/utils/image-process.js.map +1 -0
  842. package/dist/utils/image-resize-core.d.ts +30 -0
  843. package/dist/utils/image-resize-core.d.ts.map +1 -0
  844. package/dist/utils/image-resize-core.js +124 -0
  845. package/dist/utils/image-resize-core.js.map +1 -0
  846. package/dist/utils/image-resize-worker.d.ts +2 -0
  847. package/dist/utils/image-resize-worker.d.ts.map +1 -0
  848. package/dist/utils/image-resize-worker.js +31 -0
  849. package/dist/utils/image-resize-worker.js.map +1 -0
  850. package/dist/utils/image-resize.d.ts +16 -0
  851. package/dist/utils/image-resize.d.ts.map +1 -0
  852. package/dist/utils/image-resize.js +97 -0
  853. package/dist/utils/image-resize.js.map +1 -0
  854. package/dist/utils/json.d.ts +3 -0
  855. package/dist/utils/json.d.ts.map +1 -0
  856. package/dist/utils/json.js +7 -0
  857. package/dist/utils/json.js.map +1 -0
  858. package/dist/utils/mime.d.ts +3 -0
  859. package/dist/utils/mime.d.ts.map +1 -0
  860. package/dist/utils/mime.js +110 -0
  861. package/dist/utils/mime.js.map +1 -0
  862. package/dist/utils/open-browser.d.ts +9 -0
  863. package/dist/utils/open-browser.d.ts.map +1 -0
  864. package/dist/utils/open-browser.js +22 -0
  865. package/dist/utils/open-browser.js.map +1 -0
  866. package/dist/utils/paths.d.ts +31 -0
  867. package/dist/utils/paths.d.ts.map +1 -0
  868. package/dist/utils/paths.js +92 -0
  869. package/dist/utils/paths.js.map +1 -0
  870. package/dist/utils/photon.d.ts +21 -0
  871. package/dist/utils/photon.d.ts.map +1 -0
  872. package/dist/utils/photon.js +121 -0
  873. package/dist/utils/photon.js.map +1 -0
  874. package/dist/utils/pi-user-agent.d.ts +2 -0
  875. package/dist/utils/pi-user-agent.d.ts.map +1 -0
  876. package/dist/utils/pi-user-agent.js +5 -0
  877. package/dist/utils/pi-user-agent.js.map +1 -0
  878. package/dist/utils/shell.d.ts +31 -0
  879. package/dist/utils/shell.d.ts.map +1 -0
  880. package/dist/utils/shell.js +202 -0
  881. package/dist/utils/shell.js.map +1 -0
  882. package/dist/utils/sleep.d.ts +5 -0
  883. package/dist/utils/sleep.d.ts.map +1 -0
  884. package/dist/utils/sleep.js +17 -0
  885. package/dist/utils/sleep.js.map +1 -0
  886. package/dist/utils/syntax-highlight.d.ts +12 -0
  887. package/dist/utils/syntax-highlight.d.ts.map +1 -0
  888. package/dist/utils/syntax-highlight.js +118 -0
  889. package/dist/utils/syntax-highlight.js.map +1 -0
  890. package/dist/utils/tools-manager.d.ts +3 -0
  891. package/dist/utils/tools-manager.d.ts.map +1 -0
  892. package/dist/utils/tools-manager.js +328 -0
  893. package/dist/utils/tools-manager.js.map +1 -0
  894. package/dist/utils/version-check.d.ts +15 -0
  895. package/dist/utils/version-check.d.ts.map +1 -0
  896. package/dist/utils/version-check.js +54 -0
  897. package/dist/utils/version-check.js.map +1 -0
  898. package/dist/utils/windows-self-update.d.ts +3 -0
  899. package/dist/utils/windows-self-update.d.ts.map +1 -0
  900. package/dist/utils/windows-self-update.js +77 -0
  901. package/dist/utils/windows-self-update.js.map +1 -0
  902. package/docs/compaction.md +401 -0
  903. package/docs/containerization.md +111 -0
  904. package/docs/custom-provider.md +763 -0
  905. package/docs/development.md +71 -0
  906. package/docs/docs.json +156 -0
  907. package/docs/extensions.md +2953 -0
  908. package/docs/images/doom-extension.png +0 -0
  909. package/docs/images/exy.png +0 -0
  910. package/docs/images/interactive-mode.png +0 -0
  911. package/docs/images/tree-view.png +0 -0
  912. package/docs/index.md +77 -0
  913. package/docs/json.md +86 -0
  914. package/docs/keybindings.md +198 -0
  915. package/docs/llama-cpp.md +99 -0
  916. package/docs/models.md +540 -0
  917. package/docs/packages.md +228 -0
  918. package/docs/prompt-templates.md +96 -0
  919. package/docs/providers.md +301 -0
  920. package/docs/quickstart.md +165 -0
  921. package/docs/rpc.md +1559 -0
  922. package/docs/sdk.md +1186 -0
  923. package/docs/security.md +59 -0
  924. package/docs/session-format.md +436 -0
  925. package/docs/sessions.md +145 -0
  926. package/docs/settings.md +319 -0
  927. package/docs/shell-aliases.md +13 -0
  928. package/docs/skills.md +231 -0
  929. package/docs/terminal-setup.md +142 -0
  930. package/docs/termux.md +127 -0
  931. package/docs/themes.md +301 -0
  932. package/docs/tmux.md +63 -0
  933. package/docs/tui.md +942 -0
  934. package/docs/usage.md +311 -0
  935. package/docs/windows.md +17 -0
  936. package/examples/README.md +25 -0
  937. package/examples/extensions/README.md +213 -0
  938. package/examples/extensions/auto-commit-on-exit.ts +49 -0
  939. package/examples/extensions/bash-spawn-hook.ts +30 -0
  940. package/examples/extensions/bookmark.ts +50 -0
  941. package/examples/extensions/border-status-editor.ts +145 -0
  942. package/examples/extensions/built-in-tool-renderer.ts +249 -0
  943. package/examples/extensions/claude-rules.ts +86 -0
  944. package/examples/extensions/commands.ts +72 -0
  945. package/examples/extensions/confirm-destructive.ts +59 -0
  946. package/examples/extensions/custom-compaction.ts +129 -0
  947. package/examples/extensions/custom-footer.ts +64 -0
  948. package/examples/extensions/custom-header.ts +73 -0
  949. package/examples/extensions/custom-provider-anthropic/index.ts +604 -0
  950. package/examples/extensions/custom-provider-anthropic/package-lock.json +24 -0
  951. package/examples/extensions/custom-provider-anthropic/package.json +19 -0
  952. package/examples/extensions/custom-provider-gitlab-duo/index.ts +404 -0
  953. package/examples/extensions/custom-provider-gitlab-duo/package.json +16 -0
  954. package/examples/extensions/custom-provider-gitlab-duo/test.ts +82 -0
  955. package/examples/extensions/dirty-repo-guard.ts +56 -0
  956. package/examples/extensions/doom-overlay/README.md +46 -0
  957. package/examples/extensions/doom-overlay/doom/build/doom.js +21 -0
  958. package/examples/extensions/doom-overlay/doom/build/doom.wasm +0 -0
  959. package/examples/extensions/doom-overlay/doom/build.sh +152 -0
  960. package/examples/extensions/doom-overlay/doom/doomgeneric_pi.c +72 -0
  961. package/examples/extensions/doom-overlay/doom-component.ts +132 -0
  962. package/examples/extensions/doom-overlay/doom-engine.ts +173 -0
  963. package/examples/extensions/doom-overlay/doom-keys.ts +104 -0
  964. package/examples/extensions/doom-overlay/index.ts +74 -0
  965. package/examples/extensions/doom-overlay/wad-finder.ts +51 -0
  966. package/examples/extensions/dynamic-resources/SKILL.md +8 -0
  967. package/examples/extensions/dynamic-resources/dynamic.json +79 -0
  968. package/examples/extensions/dynamic-resources/dynamic.md +5 -0
  969. package/examples/extensions/dynamic-resources/index.ts +15 -0
  970. package/examples/extensions/dynamic-tools.ts +74 -0
  971. package/examples/extensions/entry-renderer.ts +41 -0
  972. package/examples/extensions/event-bus.ts +43 -0
  973. package/examples/extensions/file-trigger.ts +41 -0
  974. package/examples/extensions/git-checkpoint.ts +53 -0
  975. package/examples/extensions/git-merge-and-resolve.ts +115 -0
  976. package/examples/extensions/github-issue-autocomplete.ts +185 -0
  977. package/examples/extensions/gondolin/index.ts +531 -0
  978. package/examples/extensions/gondolin/package-lock.json +185 -0
  979. package/examples/extensions/gondolin/package.json +19 -0
  980. package/examples/extensions/handoff.ts +191 -0
  981. package/examples/extensions/hello.ts +26 -0
  982. package/examples/extensions/hidden-thinking-label.ts +53 -0
  983. package/examples/extensions/inline-bash.ts +94 -0
  984. package/examples/extensions/input-transform-streaming.ts +39 -0
  985. package/examples/extensions/input-transform.ts +43 -0
  986. package/examples/extensions/interactive-shell.ts +196 -0
  987. package/examples/extensions/kimi-deferred-tools.ts +61 -0
  988. package/examples/extensions/mac-system-theme.ts +47 -0
  989. package/examples/extensions/message-renderer.ts +59 -0
  990. package/examples/extensions/minimal-mode.ts +426 -0
  991. package/examples/extensions/modal-editor.ts +85 -0
  992. package/examples/extensions/model-status.ts +31 -0
  993. package/examples/extensions/notify.ts +55 -0
  994. package/examples/extensions/overlay-qa-tests.ts +1450 -0
  995. package/examples/extensions/overlay-test.ts +153 -0
  996. package/examples/extensions/permission-gate.ts +34 -0
  997. package/examples/extensions/pirate.ts +47 -0
  998. package/examples/extensions/plan-mode/README.md +66 -0
  999. package/examples/extensions/plan-mode/index.ts +390 -0
  1000. package/examples/extensions/plan-mode/utils.ts +168 -0
  1001. package/examples/extensions/preset.ts +436 -0
  1002. package/examples/extensions/project-trust.ts +64 -0
  1003. package/examples/extensions/prompt-customizer.ts +97 -0
  1004. package/examples/extensions/protected-paths.ts +30 -0
  1005. package/examples/extensions/provider-payload.ts +18 -0
  1006. package/examples/extensions/qna.ts +122 -0
  1007. package/examples/extensions/question.ts +286 -0
  1008. package/examples/extensions/questionnaire.ts +448 -0
  1009. package/examples/extensions/rainbow-editor.ts +88 -0
  1010. package/examples/extensions/reload-runtime.ts +37 -0
  1011. package/examples/extensions/rpc-demo.ts +118 -0
  1012. package/examples/extensions/sandbox/index.ts +321 -0
  1013. package/examples/extensions/sandbox/package-lock.json +92 -0
  1014. package/examples/extensions/sandbox/package.json +19 -0
  1015. package/examples/extensions/send-user-message.ts +97 -0
  1016. package/examples/extensions/session-name.ts +27 -0
  1017. package/examples/extensions/shutdown-command.ts +63 -0
  1018. package/examples/extensions/snake.ts +343 -0
  1019. package/examples/extensions/space-invaders.ts +560 -0
  1020. package/examples/extensions/ssh.ts +220 -0
  1021. package/examples/extensions/status-line.ts +32 -0
  1022. package/examples/extensions/structured-output.ts +65 -0
  1023. package/examples/extensions/subagent/README.md +175 -0
  1024. package/examples/extensions/subagent/agents/planner.md +37 -0
  1025. package/examples/extensions/subagent/agents/reviewer.md +35 -0
  1026. package/examples/extensions/subagent/agents/scout.md +50 -0
  1027. package/examples/extensions/subagent/agents/worker.md +24 -0
  1028. package/examples/extensions/subagent/agents.ts +126 -0
  1029. package/examples/extensions/subagent/index.ts +1009 -0
  1030. package/examples/extensions/subagent/prompts/implement-and-review.md +10 -0
  1031. package/examples/extensions/subagent/prompts/implement.md +10 -0
  1032. package/examples/extensions/subagent/prompts/scout-and-plan.md +9 -0
  1033. package/examples/extensions/summarize.ts +207 -0
  1034. package/examples/extensions/system-prompt-header.ts +17 -0
  1035. package/examples/extensions/tic-tac-toe.ts +1008 -0
  1036. package/examples/extensions/timed-confirm.ts +70 -0
  1037. package/examples/extensions/titlebar-spinner.ts +58 -0
  1038. package/examples/extensions/todo.ts +297 -0
  1039. package/examples/extensions/tool-override.ts +144 -0
  1040. package/examples/extensions/tools.ts +146 -0
  1041. package/examples/extensions/trigger-compact.ts +50 -0
  1042. package/examples/extensions/truncated-tool.ts +195 -0
  1043. package/examples/extensions/widget-placement.ts +9 -0
  1044. package/examples/extensions/with-deps/index.ts +32 -0
  1045. package/examples/extensions/with-deps/package-lock.json +31 -0
  1046. package/examples/extensions/with-deps/package.json +22 -0
  1047. package/examples/extensions/working-indicator.ts +123 -0
  1048. package/examples/extensions/working-message-test.ts +25 -0
  1049. package/examples/rpc-extension-ui.ts +632 -0
  1050. package/examples/sdk/01-minimal.ts +26 -0
  1051. package/examples/sdk/02-custom-model.ts +50 -0
  1052. package/examples/sdk/03-custom-prompt.ts +70 -0
  1053. package/examples/sdk/04-skills.ts +55 -0
  1054. package/examples/sdk/05-tools.ts +48 -0
  1055. package/examples/sdk/06-extensions.ts +94 -0
  1056. package/examples/sdk/07-context-files.ts +42 -0
  1057. package/examples/sdk/08-prompt-templates.ts +51 -0
  1058. package/examples/sdk/09-api-keys-and-oauth.ts +34 -0
  1059. package/examples/sdk/10-settings.ts +53 -0
  1060. package/examples/sdk/11-sessions.ts +52 -0
  1061. package/examples/sdk/12-full-control.ts +72 -0
  1062. package/examples/sdk/13-session-runtime.ts +67 -0
  1063. package/examples/sdk/README.md +140 -0
  1064. package/npm-shrinkwrap.json +1824 -0
  1065. package/package.json +99 -0
@@ -0,0 +1,9 @@
1
+ import type { CustomAnswer, DisplayOption, Question, QuestionAnswer, QuestionState } from "./types.ts";
2
+ export declare function newQuestionState(): QuestionState;
3
+ export declare function selectedCustomAnswer(state: QuestionState): CustomAnswer | undefined;
4
+ export declare function hasMultiAnswer(state: QuestionState): boolean;
5
+ export declare function hasAnswer(state: QuestionState): boolean;
6
+ export declare function displayOptions(question: Question): DisplayOption[];
7
+ export declare function firstUnanswered(states: QuestionState[]): number | undefined;
8
+ export declare function orderedAnswers(questions: Question[], states: QuestionState[]): QuestionAnswer[];
9
+ //# sourceMappingURL=state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../src/extensions/question/state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAGnH,wBAAgB,gBAAgB,IAAI,aAAa,CAMhD;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,aAAa,GAAG,YAAY,GAAG,SAAS,CAEnF;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAE5D;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAEvD;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,aAAa,EAAE,CAKlE;AAWD,wBAAgB,eAAe,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,GAAG,SAAS,CAM3E;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,aAAa,EAAE,GAAG,cAAc,EAAE,CAmC/F","sourcesContent":["import type { AnswerNote, CustomAnswer, DisplayOption, Question, QuestionAnswer, QuestionState } from \"./types.ts\";\nimport { OTHER_OPTION } from \"./types.ts\";\n\nexport function newQuestionState(): QuestionState {\n\treturn {\n\t\toptionIndex: 0,\n\t\tmultiSelected: new Set(),\n\t\tnotesByOption: new Map(),\n\t};\n}\n\nexport function selectedCustomAnswer(state: QuestionState): CustomAnswer | undefined {\n\treturn state.customAnswer?.selected ? state.customAnswer : undefined;\n}\n\nexport function hasMultiAnswer(state: QuestionState): boolean {\n\treturn state.multiSelected.size > 0 || selectedCustomAnswer(state) !== undefined;\n}\n\nexport function hasAnswer(state: QuestionState): boolean {\n\treturn Boolean(state.singleAnswer) || hasMultiAnswer(state);\n}\n\nexport function displayOptions(question: Question): DisplayOption[] {\n\treturn [\n\t\t...question.options.map((option, optionIndex) => ({ ...option, kind: \"option\" as const, optionIndex })),\n\t\tOTHER_OPTION,\n\t];\n}\n\nfunction noteEntries(state: QuestionState, allowedOptions: readonly string[]): AnswerNote[] | undefined {\n\tconst allowed = new Set(allowedOptions);\n\tconst entries = [...state.notesByOption.entries()]\n\t\t.filter(([option]) => allowed.has(option))\n\t\t.filter(([, text]) => text.trim().length > 0)\n\t\t.map(([option, text]) => ({ option, text: text.trim() }));\n\treturn entries.length ? entries : undefined;\n}\n\nexport function firstUnanswered(states: QuestionState[]): number | undefined {\n\tfor (let i = 0; i < states.length; i++) {\n\t\tconst state = states[i];\n\t\tif (!hasAnswer(state)) return i;\n\t}\n\treturn undefined;\n}\n\nexport function orderedAnswers(questions: Question[], states: QuestionState[]): QuestionAnswer[] {\n\tconst answers: QuestionAnswer[] = [];\n\tfor (let i = 0; i < questions.length; i++) {\n\t\tconst question = questions[i];\n\t\tconst state = states[i];\n\t\tif (state.singleAnswer) {\n\t\t\tconst notes =\n\t\t\t\tstate.singleAnswer.kind === \"option\" && state.singleAnswer.answer\n\t\t\t\t\t? noteEntries(state, [state.singleAnswer.answer])\n\t\t\t\t\t: undefined;\n\t\t\tanswers.push(notes ? { ...state.singleAnswer, notes } : state.singleAnswer);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (question.multiSelect && hasMultiAnswer(state)) {\n\t\t\tconst selected: string[] = [];\n\t\t\tfor (const idx of [...state.multiSelected].sort((a, b) => a - b)) {\n\t\t\t\tconst option = question.options[idx];\n\t\t\t\tif (option) selected.push(option.label);\n\t\t\t}\n\t\t\tconst custom = selectedCustomAnswer(state);\n\t\t\tif (custom) selected.push(custom.text);\n\t\t\tconst notes = noteEntries(state, selected);\n\t\t\tanswers.push({\n\t\t\t\tquestionIndex: i,\n\t\t\t\tquestion: question.question,\n\t\t\t\theader: question.header,\n\t\t\t\tkind: \"multi\",\n\t\t\t\tanswer: null,\n\t\t\t\tselected,\n\t\t\t\t...(notes ? { notes } : {}),\n\t\t\t});\n\t\t}\n\t}\n\treturn answers;\n}\n"]}
@@ -0,0 +1,76 @@
1
+ import { OTHER_OPTION } from "./types.js";
2
+ export function newQuestionState() {
3
+ return {
4
+ optionIndex: 0,
5
+ multiSelected: new Set(),
6
+ notesByOption: new Map(),
7
+ };
8
+ }
9
+ export function selectedCustomAnswer(state) {
10
+ return state.customAnswer?.selected ? state.customAnswer : undefined;
11
+ }
12
+ export function hasMultiAnswer(state) {
13
+ return state.multiSelected.size > 0 || selectedCustomAnswer(state) !== undefined;
14
+ }
15
+ export function hasAnswer(state) {
16
+ return Boolean(state.singleAnswer) || hasMultiAnswer(state);
17
+ }
18
+ export function displayOptions(question) {
19
+ return [
20
+ ...question.options.map((option, optionIndex) => ({ ...option, kind: "option", optionIndex })),
21
+ OTHER_OPTION,
22
+ ];
23
+ }
24
+ function noteEntries(state, allowedOptions) {
25
+ const allowed = new Set(allowedOptions);
26
+ const entries = [...state.notesByOption.entries()]
27
+ .filter(([option]) => allowed.has(option))
28
+ .filter(([, text]) => text.trim().length > 0)
29
+ .map(([option, text]) => ({ option, text: text.trim() }));
30
+ return entries.length ? entries : undefined;
31
+ }
32
+ export function firstUnanswered(states) {
33
+ for (let i = 0; i < states.length; i++) {
34
+ const state = states[i];
35
+ if (!hasAnswer(state))
36
+ return i;
37
+ }
38
+ return undefined;
39
+ }
40
+ export function orderedAnswers(questions, states) {
41
+ const answers = [];
42
+ for (let i = 0; i < questions.length; i++) {
43
+ const question = questions[i];
44
+ const state = states[i];
45
+ if (state.singleAnswer) {
46
+ const notes = state.singleAnswer.kind === "option" && state.singleAnswer.answer
47
+ ? noteEntries(state, [state.singleAnswer.answer])
48
+ : undefined;
49
+ answers.push(notes ? { ...state.singleAnswer, notes } : state.singleAnswer);
50
+ continue;
51
+ }
52
+ if (question.multiSelect && hasMultiAnswer(state)) {
53
+ const selected = [];
54
+ for (const idx of [...state.multiSelected].sort((a, b) => a - b)) {
55
+ const option = question.options[idx];
56
+ if (option)
57
+ selected.push(option.label);
58
+ }
59
+ const custom = selectedCustomAnswer(state);
60
+ if (custom)
61
+ selected.push(custom.text);
62
+ const notes = noteEntries(state, selected);
63
+ answers.push({
64
+ questionIndex: i,
65
+ question: question.question,
66
+ header: question.header,
67
+ kind: "multi",
68
+ answer: null,
69
+ selected,
70
+ ...(notes ? { notes } : {}),
71
+ });
72
+ }
73
+ }
74
+ return answers;
75
+ }
76
+ //# sourceMappingURL=state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../../../src/extensions/question/state.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,UAAU,gBAAgB,GAAkB;IACjD,OAAO;QACN,WAAW,EAAE,CAAC;QACd,aAAa,EAAE,IAAI,GAAG,EAAE;QACxB,aAAa,EAAE,IAAI,GAAG,EAAE;KACxB,CAAC;AAAA,CACF;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAoB,EAA4B;IACpF,OAAO,KAAK,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC;AAAA,CACrE;AAED,MAAM,UAAU,cAAc,CAAC,KAAoB,EAAW;IAC7D,OAAO,KAAK,CAAC,aAAa,CAAC,IAAI,GAAG,CAAC,IAAI,oBAAoB,CAAC,KAAK,CAAC,KAAK,SAAS,CAAC;AAAA,CACjF;AAED,MAAM,UAAU,SAAS,CAAC,KAAoB,EAAW;IACxD,OAAO,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,cAAc,CAAC,KAAK,CAAC,CAAC;AAAA,CAC5D;AAED,MAAM,UAAU,cAAc,CAAC,QAAkB,EAAmB;IACnE,OAAO;QACN,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,IAAI,EAAE,QAAiB,EAAE,WAAW,EAAE,CAAC,CAAC;QACvG,YAAY;KACZ,CAAC;AAAA,CACF;AAED,SAAS,WAAW,CAAC,KAAoB,EAAE,cAAiC,EAA4B;IACvG,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,cAAc,CAAC,CAAC;IACxC,MAAM,OAAO,GAAG,CAAC,GAAG,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC;SAChD,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;SACzC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;SAC5C,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;IAC3D,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;AAAA,CAC5C;AAED,MAAM,UAAU,eAAe,CAAC,MAAuB,EAAsB;IAC5E,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QACxB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;YAAE,OAAO,CAAC,CAAC;IACjC,CAAC;IACD,OAAO,SAAS,CAAC;AAAA,CACjB;AAED,MAAM,UAAU,cAAc,CAAC,SAAqB,EAAE,MAAuB,EAAoB;IAChG,MAAM,OAAO,GAAqB,EAAE,CAAC;IACrC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3C,MAAM,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QACxB,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;YACxB,MAAM,KAAK,GACV,KAAK,CAAC,YAAY,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,YAAY,CAAC,MAAM;gBAChE,CAAC,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;gBACjD,CAAC,CAAC,SAAS,CAAC;YACd,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,CAAC,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YAC5E,SAAS;QACV,CAAC;QAED,IAAI,QAAQ,CAAC,WAAW,IAAI,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;YACnD,MAAM,QAAQ,GAAa,EAAE,CAAC;YAC9B,KAAK,MAAM,GAAG,IAAI,CAAC,GAAG,KAAK,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;gBAClE,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBACrC,IAAI,MAAM;oBAAE,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACzC,CAAC;YACD,MAAM,MAAM,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;YAC3C,IAAI,MAAM;gBAAE,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACvC,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;YAC3C,OAAO,CAAC,IAAI,CAAC;gBACZ,aAAa,EAAE,CAAC;gBAChB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;gBAC3B,MAAM,EAAE,QAAQ,CAAC,MAAM;gBACvB,IAAI,EAAE,OAAO;gBACb,MAAM,EAAE,IAAI;gBACZ,QAAQ;gBACR,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC3B,CAAC,CAAC;QACJ,CAAC;IACF,CAAC;IACD,OAAO,OAAO,CAAC;AAAA,CACf","sourcesContent":["import type { AnswerNote, CustomAnswer, DisplayOption, Question, QuestionAnswer, QuestionState } from \"./types.ts\";\nimport { OTHER_OPTION } from \"./types.ts\";\n\nexport function newQuestionState(): QuestionState {\n\treturn {\n\t\toptionIndex: 0,\n\t\tmultiSelected: new Set(),\n\t\tnotesByOption: new Map(),\n\t};\n}\n\nexport function selectedCustomAnswer(state: QuestionState): CustomAnswer | undefined {\n\treturn state.customAnswer?.selected ? state.customAnswer : undefined;\n}\n\nexport function hasMultiAnswer(state: QuestionState): boolean {\n\treturn state.multiSelected.size > 0 || selectedCustomAnswer(state) !== undefined;\n}\n\nexport function hasAnswer(state: QuestionState): boolean {\n\treturn Boolean(state.singleAnswer) || hasMultiAnswer(state);\n}\n\nexport function displayOptions(question: Question): DisplayOption[] {\n\treturn [\n\t\t...question.options.map((option, optionIndex) => ({ ...option, kind: \"option\" as const, optionIndex })),\n\t\tOTHER_OPTION,\n\t];\n}\n\nfunction noteEntries(state: QuestionState, allowedOptions: readonly string[]): AnswerNote[] | undefined {\n\tconst allowed = new Set(allowedOptions);\n\tconst entries = [...state.notesByOption.entries()]\n\t\t.filter(([option]) => allowed.has(option))\n\t\t.filter(([, text]) => text.trim().length > 0)\n\t\t.map(([option, text]) => ({ option, text: text.trim() }));\n\treturn entries.length ? entries : undefined;\n}\n\nexport function firstUnanswered(states: QuestionState[]): number | undefined {\n\tfor (let i = 0; i < states.length; i++) {\n\t\tconst state = states[i];\n\t\tif (!hasAnswer(state)) return i;\n\t}\n\treturn undefined;\n}\n\nexport function orderedAnswers(questions: Question[], states: QuestionState[]): QuestionAnswer[] {\n\tconst answers: QuestionAnswer[] = [];\n\tfor (let i = 0; i < questions.length; i++) {\n\t\tconst question = questions[i];\n\t\tconst state = states[i];\n\t\tif (state.singleAnswer) {\n\t\t\tconst notes =\n\t\t\t\tstate.singleAnswer.kind === \"option\" && state.singleAnswer.answer\n\t\t\t\t\t? noteEntries(state, [state.singleAnswer.answer])\n\t\t\t\t\t: undefined;\n\t\t\tanswers.push(notes ? { ...state.singleAnswer, notes } : state.singleAnswer);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (question.multiSelect && hasMultiAnswer(state)) {\n\t\t\tconst selected: string[] = [];\n\t\t\tfor (const idx of [...state.multiSelected].sort((a, b) => a - b)) {\n\t\t\t\tconst option = question.options[idx];\n\t\t\t\tif (option) selected.push(option.label);\n\t\t\t}\n\t\t\tconst custom = selectedCustomAnswer(state);\n\t\t\tif (custom) selected.push(custom.text);\n\t\t\tconst notes = noteEntries(state, selected);\n\t\t\tanswers.push({\n\t\t\t\tquestionIndex: i,\n\t\t\t\tquestion: question.question,\n\t\t\t\theader: question.header,\n\t\t\t\tkind: \"multi\",\n\t\t\t\tanswer: null,\n\t\t\t\tselected,\n\t\t\t\t...(notes ? { notes } : {}),\n\t\t\t});\n\t\t}\n\t}\n\treturn answers;\n}\n"]}
@@ -0,0 +1,60 @@
1
+ export interface QuestionOption {
2
+ label: string;
3
+ description: string;
4
+ preview?: string;
5
+ }
6
+ export interface Question {
7
+ question: string;
8
+ header: string;
9
+ options: QuestionOption[];
10
+ multiSelect?: boolean;
11
+ }
12
+ export type InputMode = "custom" | "notes" | undefined;
13
+ export type QuestionToolError = "no_ui" | "no_questions" | "too_many_questions" | "invalid_option_count" | "duplicate_question" | "duplicate_option_label" | "reserved_label" | "invalid_text_length";
14
+ export interface AnswerNote {
15
+ option: string;
16
+ text: string;
17
+ }
18
+ export interface QuestionAnswer {
19
+ questionIndex: number;
20
+ question: string;
21
+ header: string;
22
+ kind: "option" | "custom" | "multi";
23
+ answer: string | null;
24
+ selected?: string[];
25
+ notes?: AnswerNote[];
26
+ preview?: string;
27
+ }
28
+ export type QuestionOutcome = "answered" | "cancelled" | "needs_clarification" | "error";
29
+ export interface QuestionToolDetails {
30
+ answers: QuestionAnswer[];
31
+ outcome: QuestionOutcome;
32
+ cancelled: boolean;
33
+ error?: QuestionToolError;
34
+ }
35
+ export interface CustomAnswer {
36
+ text: string;
37
+ selected: boolean;
38
+ }
39
+ export interface QuestionState {
40
+ optionIndex: number;
41
+ singleAnswer?: QuestionAnswer;
42
+ multiSelected: Set<number>;
43
+ customAnswer?: CustomAnswer;
44
+ notesByOption: Map<string, string>;
45
+ warning?: string;
46
+ }
47
+ export interface DialogResult {
48
+ answers: QuestionAnswer[];
49
+ outcome: QuestionOutcome;
50
+ }
51
+ export type DisplayOption = (QuestionOption & {
52
+ kind: "option";
53
+ optionIndex: number;
54
+ }) | {
55
+ kind: "other";
56
+ label: string;
57
+ isOther: true;
58
+ };
59
+ export declare const OTHER_OPTION: DisplayOption;
60
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/extensions/question/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,QAAQ;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,WAAW,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;AAEvD,MAAM,MAAM,iBAAiB,GAC1B,OAAO,GACP,cAAc,GACd,oBAAoB,GACpB,sBAAsB,GACtB,oBAAoB,GACpB,wBAAwB,GACxB,gBAAgB,GAChB,qBAAqB,CAAC;AAEzB,MAAM,WAAW,UAAU;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,cAAc;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;IACpC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,WAAW,GAAG,qBAAqB,GAAG,OAAO,CAAC;AAEzF,MAAM,WAAW,mBAAmB;IACnC,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,OAAO,EAAE,eAAe,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,iBAAiB,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,cAAc,CAAC;IAC9B,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC5B,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,OAAO,EAAE,eAAe,CAAC;CACzB;AAED,MAAM,MAAM,aAAa,GACtB,CAAC,cAAc,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,GAC1D;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,IAAI,CAAA;CAAE,CAAC;AAEnD,eAAO,MAAM,YAAY,EAAE,aAA0E,CAAC","sourcesContent":["export interface QuestionOption {\n\tlabel: string;\n\tdescription: string;\n\tpreview?: string;\n}\n\nexport interface Question {\n\tquestion: string;\n\theader: string;\n\toptions: QuestionOption[];\n\tmultiSelect?: boolean;\n}\n\nexport type InputMode = \"custom\" | \"notes\" | undefined;\n\nexport type QuestionToolError =\n\t| \"no_ui\"\n\t| \"no_questions\"\n\t| \"too_many_questions\"\n\t| \"invalid_option_count\"\n\t| \"duplicate_question\"\n\t| \"duplicate_option_label\"\n\t| \"reserved_label\"\n\t| \"invalid_text_length\";\n\nexport interface AnswerNote {\n\toption: string;\n\ttext: string;\n}\n\nexport interface QuestionAnswer {\n\tquestionIndex: number;\n\tquestion: string;\n\theader: string;\n\tkind: \"option\" | \"custom\" | \"multi\";\n\tanswer: string | null;\n\tselected?: string[];\n\tnotes?: AnswerNote[];\n\tpreview?: string;\n}\n\nexport type QuestionOutcome = \"answered\" | \"cancelled\" | \"needs_clarification\" | \"error\";\n\nexport interface QuestionToolDetails {\n\tanswers: QuestionAnswer[];\n\toutcome: QuestionOutcome;\n\tcancelled: boolean;\n\terror?: QuestionToolError;\n}\n\nexport interface CustomAnswer {\n\ttext: string;\n\tselected: boolean;\n}\n\nexport interface QuestionState {\n\toptionIndex: number;\n\tsingleAnswer?: QuestionAnswer;\n\tmultiSelected: Set<number>;\n\tcustomAnswer?: CustomAnswer;\n\tnotesByOption: Map<string, string>;\n\twarning?: string;\n}\n\nexport interface DialogResult {\n\tanswers: QuestionAnswer[];\n\toutcome: QuestionOutcome;\n}\n\nexport type DisplayOption =\n\t| (QuestionOption & { kind: \"option\"; optionIndex: number })\n\t| { kind: \"other\"; label: string; isOther: true };\n\nexport const OTHER_OPTION: DisplayOption = { kind: \"other\", label: \"Type something.\", isOther: true };\n"]}
@@ -0,0 +1,2 @@
1
+ export const OTHER_OPTION = { kind: "other", label: "Type something.", isOther: true };
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/extensions/question/types.ts"],"names":[],"mappings":"AAyEA,MAAM,CAAC,MAAM,YAAY,GAAkB,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC","sourcesContent":["export interface QuestionOption {\n\tlabel: string;\n\tdescription: string;\n\tpreview?: string;\n}\n\nexport interface Question {\n\tquestion: string;\n\theader: string;\n\toptions: QuestionOption[];\n\tmultiSelect?: boolean;\n}\n\nexport type InputMode = \"custom\" | \"notes\" | undefined;\n\nexport type QuestionToolError =\n\t| \"no_ui\"\n\t| \"no_questions\"\n\t| \"too_many_questions\"\n\t| \"invalid_option_count\"\n\t| \"duplicate_question\"\n\t| \"duplicate_option_label\"\n\t| \"reserved_label\"\n\t| \"invalid_text_length\";\n\nexport interface AnswerNote {\n\toption: string;\n\ttext: string;\n}\n\nexport interface QuestionAnswer {\n\tquestionIndex: number;\n\tquestion: string;\n\theader: string;\n\tkind: \"option\" | \"custom\" | \"multi\";\n\tanswer: string | null;\n\tselected?: string[];\n\tnotes?: AnswerNote[];\n\tpreview?: string;\n}\n\nexport type QuestionOutcome = \"answered\" | \"cancelled\" | \"needs_clarification\" | \"error\";\n\nexport interface QuestionToolDetails {\n\tanswers: QuestionAnswer[];\n\toutcome: QuestionOutcome;\n\tcancelled: boolean;\n\terror?: QuestionToolError;\n}\n\nexport interface CustomAnswer {\n\ttext: string;\n\tselected: boolean;\n}\n\nexport interface QuestionState {\n\toptionIndex: number;\n\tsingleAnswer?: QuestionAnswer;\n\tmultiSelected: Set<number>;\n\tcustomAnswer?: CustomAnswer;\n\tnotesByOption: Map<string, string>;\n\twarning?: string;\n}\n\nexport interface DialogResult {\n\tanswers: QuestionAnswer[];\n\toutcome: QuestionOutcome;\n}\n\nexport type DisplayOption =\n\t| (QuestionOption & { kind: \"option\"; optionIndex: number })\n\t| { kind: \"other\"; label: string; isOther: true };\n\nexport const OTHER_OPTION: DisplayOption = { kind: \"other\", label: \"Type something.\", isOther: true };\n"]}
@@ -0,0 +1,16 @@
1
+ export interface RewindConfig {
2
+ /** Master switch. When false, no backups are taken and rewind is inert. */
3
+ enabled: boolean;
4
+ /** Backups for sessions whose dir is older than this are GC'd. 0 = keep forever. */
5
+ retentionDays: number;
6
+ /** Cap on retained snapshots per session. */
7
+ maxSnapshots: number;
8
+ }
9
+ export declare const DEFAULT_CONFIG: RewindConfig;
10
+ /** Cached config (reads disk once, then serves memory until reload/save). */
11
+ export declare function loadRewindConfig(): RewindConfig;
12
+ /** Force a disk re-read (call on session_start so external edits take effect). */
13
+ export declare function reloadRewindConfig(): RewindConfig;
14
+ /** Persist and update the in-memory cache so the next turn sees the change. */
15
+ export declare function saveRewindConfig(config: RewindConfig): boolean;
16
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/extensions/rewind/config.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,YAAY;IAC5B,2EAA2E;IAC3E,OAAO,EAAE,OAAO,CAAC;IACjB,oFAAoF;IACpF,aAAa,EAAE,MAAM,CAAC;IACtB,6CAA6C;IAC7C,YAAY,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,cAAc,EAAE,YAI5B,CAAC;AA8BF,6EAA6E;AAC7E,wBAAgB,gBAAgB,IAAI,YAAY,CAG/C;AAED,kFAAkF;AAClF,wBAAgB,kBAAkB,IAAI,YAAY,CAGjD;AAED,+EAA+E;AAC/E,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAW9D","sourcesContent":["/**\n * config.ts — load/save the rewind extension's settings at\n * <rewindDir>/config.json. Tolerant parse, atomic-ish write, sensible defaults\n * so a missing/corrupt file never breaks the session.\n *\n * Settings are user-editable via the /rewind menu (menu.ts).\n */\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\n\nimport { rewindConfigPath } from \"./paths.ts\";\n\nexport interface RewindConfig {\n\t/** Master switch. When false, no backups are taken and rewind is inert. */\n\tenabled: boolean;\n\t/** Backups for sessions whose dir is older than this are GC'd. 0 = keep forever. */\n\tretentionDays: number;\n\t/** Cap on retained snapshots per session. */\n\tmaxSnapshots: number;\n}\n\nexport const DEFAULT_CONFIG: RewindConfig = {\n\tenabled: true,\n\tretentionDays: 30,\n\tmaxSnapshots: 100,\n};\n\n/** In-process cache so lifecycle hooks do not re-read config.json every turn. */\nlet cached: RewindConfig | null = null;\n\nfunction clampInt(value: unknown, min: number, max: number, fallback: number): number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) return fallback;\n\treturn Math.min(max, Math.max(min, Math.round(value)));\n}\n\nfunction normalize(raw: unknown): RewindConfig {\n\tif (!raw || typeof raw !== \"object\") return { ...DEFAULT_CONFIG };\n\tconst r = raw as Partial<RewindConfig>;\n\treturn {\n\t\tenabled: typeof r.enabled === \"boolean\" ? r.enabled : DEFAULT_CONFIG.enabled,\n\t\tretentionDays: clampInt(r.retentionDays, 0, 3650, DEFAULT_CONFIG.retentionDays),\n\t\tmaxSnapshots: clampInt(r.maxSnapshots, 1, 1000, DEFAULT_CONFIG.maxSnapshots),\n\t};\n}\n\nfunction readConfigFromDisk(): RewindConfig {\n\tconst configPath = rewindConfigPath();\n\tif (!existsSync(configPath)) return { ...DEFAULT_CONFIG };\n\ttry {\n\t\treturn normalize(JSON.parse(readFileSync(configPath, \"utf8\")));\n\t} catch {\n\t\treturn { ...DEFAULT_CONFIG };\n\t}\n}\n\n/** Cached config (reads disk once, then serves memory until reload/save). */\nexport function loadRewindConfig(): RewindConfig {\n\tif (!cached) cached = readConfigFromDisk();\n\treturn cached;\n}\n\n/** Force a disk re-read (call on session_start so external edits take effect). */\nexport function reloadRewindConfig(): RewindConfig {\n\tcached = readConfigFromDisk();\n\treturn cached;\n}\n\n/** Persist and update the in-memory cache so the next turn sees the change. */\nexport function saveRewindConfig(config: RewindConfig): boolean {\n\tconst next = normalize(config);\n\tconst configPath = rewindConfigPath();\n\ttry {\n\t\tmkdirSync(dirname(configPath), { recursive: true });\n\t\twriteFileSync(configPath, `${JSON.stringify(next, null, 2)}\\n`, \"utf8\");\n\t\tcached = next;\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n"]}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * config.ts — load/save the rewind extension's settings at
3
+ * <rewindDir>/config.json. Tolerant parse, atomic-ish write, sensible defaults
4
+ * so a missing/corrupt file never breaks the session.
5
+ *
6
+ * Settings are user-editable via the /rewind menu (menu.ts).
7
+ */
8
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
9
+ import { dirname } from "node:path";
10
+ import { rewindConfigPath } from "./paths.js";
11
+ export const DEFAULT_CONFIG = {
12
+ enabled: true,
13
+ retentionDays: 30,
14
+ maxSnapshots: 100,
15
+ };
16
+ /** In-process cache so lifecycle hooks do not re-read config.json every turn. */
17
+ let cached = null;
18
+ function clampInt(value, min, max, fallback) {
19
+ if (typeof value !== "number" || !Number.isFinite(value))
20
+ return fallback;
21
+ return Math.min(max, Math.max(min, Math.round(value)));
22
+ }
23
+ function normalize(raw) {
24
+ if (!raw || typeof raw !== "object")
25
+ return { ...DEFAULT_CONFIG };
26
+ const r = raw;
27
+ return {
28
+ enabled: typeof r.enabled === "boolean" ? r.enabled : DEFAULT_CONFIG.enabled,
29
+ retentionDays: clampInt(r.retentionDays, 0, 3650, DEFAULT_CONFIG.retentionDays),
30
+ maxSnapshots: clampInt(r.maxSnapshots, 1, 1000, DEFAULT_CONFIG.maxSnapshots),
31
+ };
32
+ }
33
+ function readConfigFromDisk() {
34
+ const configPath = rewindConfigPath();
35
+ if (!existsSync(configPath))
36
+ return { ...DEFAULT_CONFIG };
37
+ try {
38
+ return normalize(JSON.parse(readFileSync(configPath, "utf8")));
39
+ }
40
+ catch {
41
+ return { ...DEFAULT_CONFIG };
42
+ }
43
+ }
44
+ /** Cached config (reads disk once, then serves memory until reload/save). */
45
+ export function loadRewindConfig() {
46
+ if (!cached)
47
+ cached = readConfigFromDisk();
48
+ return cached;
49
+ }
50
+ /** Force a disk re-read (call on session_start so external edits take effect). */
51
+ export function reloadRewindConfig() {
52
+ cached = readConfigFromDisk();
53
+ return cached;
54
+ }
55
+ /** Persist and update the in-memory cache so the next turn sees the change. */
56
+ export function saveRewindConfig(config) {
57
+ const next = normalize(config);
58
+ const configPath = rewindConfigPath();
59
+ try {
60
+ mkdirSync(dirname(configPath), { recursive: true });
61
+ writeFileSync(configPath, `${JSON.stringify(next, null, 2)}\n`, "utf8");
62
+ cached = next;
63
+ return true;
64
+ }
65
+ catch {
66
+ return false;
67
+ }
68
+ }
69
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/extensions/rewind/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAW9C,MAAM,CAAC,MAAM,cAAc,GAAiB;IAC3C,OAAO,EAAE,IAAI;IACb,aAAa,EAAE,EAAE;IACjB,YAAY,EAAE,GAAG;CACjB,CAAC;AAEF,iFAAiF;AACjF,IAAI,MAAM,GAAwB,IAAI,CAAC;AAEvC,SAAS,QAAQ,CAAC,KAAc,EAAE,GAAW,EAAE,GAAW,EAAE,QAAgB,EAAU;IACrF,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC1E,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAAA,CACvD;AAED,SAAS,SAAS,CAAC,GAAY,EAAgB;IAC9C,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;IAClE,MAAM,CAAC,GAAG,GAA4B,CAAC;IACvC,OAAO;QACN,OAAO,EAAE,OAAO,CAAC,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC,OAAO;QAC5E,aAAa,EAAE,QAAQ,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC,EAAE,IAAI,EAAE,cAAc,CAAC,aAAa,CAAC;QAC/E,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC,EAAE,IAAI,EAAE,cAAc,CAAC,YAAY,CAAC;KAC5E,CAAC;AAAA,CACF;AAED,SAAS,kBAAkB,GAAiB;IAC3C,MAAM,UAAU,GAAG,gBAAgB,EAAE,CAAC;IACtC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;IAC1D,IAAI,CAAC;QACJ,OAAO,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;IAChE,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;IAC9B,CAAC;AAAA,CACD;AAED,6EAA6E;AAC7E,MAAM,UAAU,gBAAgB,GAAiB;IAChD,IAAI,CAAC,MAAM;QAAE,MAAM,GAAG,kBAAkB,EAAE,CAAC;IAC3C,OAAO,MAAM,CAAC;AAAA,CACd;AAED,kFAAkF;AAClF,MAAM,UAAU,kBAAkB,GAAiB;IAClD,MAAM,GAAG,kBAAkB,EAAE,CAAC;IAC9B,OAAO,MAAM,CAAC;AAAA,CACd;AAED,+EAA+E;AAC/E,MAAM,UAAU,gBAAgB,CAAC,MAAoB,EAAW;IAC/D,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;IAC/B,MAAM,UAAU,GAAG,gBAAgB,EAAE,CAAC;IACtC,IAAI,CAAC;QACJ,SAAS,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACpD,aAAa,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACxE,MAAM,GAAG,IAAI,CAAC;QACd,OAAO,IAAI,CAAC;IACb,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,KAAK,CAAC;IACd,CAAC;AAAA,CACD","sourcesContent":["/**\n * config.ts — load/save the rewind extension's settings at\n * <rewindDir>/config.json. Tolerant parse, atomic-ish write, sensible defaults\n * so a missing/corrupt file never breaks the session.\n *\n * Settings are user-editable via the /rewind menu (menu.ts).\n */\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\n\nimport { rewindConfigPath } from \"./paths.ts\";\n\nexport interface RewindConfig {\n\t/** Master switch. When false, no backups are taken and rewind is inert. */\n\tenabled: boolean;\n\t/** Backups for sessions whose dir is older than this are GC'd. 0 = keep forever. */\n\tretentionDays: number;\n\t/** Cap on retained snapshots per session. */\n\tmaxSnapshots: number;\n}\n\nexport const DEFAULT_CONFIG: RewindConfig = {\n\tenabled: true,\n\tretentionDays: 30,\n\tmaxSnapshots: 100,\n};\n\n/** In-process cache so lifecycle hooks do not re-read config.json every turn. */\nlet cached: RewindConfig | null = null;\n\nfunction clampInt(value: unknown, min: number, max: number, fallback: number): number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) return fallback;\n\treturn Math.min(max, Math.max(min, Math.round(value)));\n}\n\nfunction normalize(raw: unknown): RewindConfig {\n\tif (!raw || typeof raw !== \"object\") return { ...DEFAULT_CONFIG };\n\tconst r = raw as Partial<RewindConfig>;\n\treturn {\n\t\tenabled: typeof r.enabled === \"boolean\" ? r.enabled : DEFAULT_CONFIG.enabled,\n\t\tretentionDays: clampInt(r.retentionDays, 0, 3650, DEFAULT_CONFIG.retentionDays),\n\t\tmaxSnapshots: clampInt(r.maxSnapshots, 1, 1000, DEFAULT_CONFIG.maxSnapshots),\n\t};\n}\n\nfunction readConfigFromDisk(): RewindConfig {\n\tconst configPath = rewindConfigPath();\n\tif (!existsSync(configPath)) return { ...DEFAULT_CONFIG };\n\ttry {\n\t\treturn normalize(JSON.parse(readFileSync(configPath, \"utf8\")));\n\t} catch {\n\t\treturn { ...DEFAULT_CONFIG };\n\t}\n}\n\n/** Cached config (reads disk once, then serves memory until reload/save). */\nexport function loadRewindConfig(): RewindConfig {\n\tif (!cached) cached = readConfigFromDisk();\n\treturn cached;\n}\n\n/** Force a disk re-read (call on session_start so external edits take effect). */\nexport function reloadRewindConfig(): RewindConfig {\n\tcached = readConfigFromDisk();\n\treturn cached;\n}\n\n/** Persist and update the in-memory cache so the next turn sees the change. */\nexport function saveRewindConfig(config: RewindConfig): boolean {\n\tconst next = normalize(config);\n\tconst configPath = rewindConfigPath();\n\ttry {\n\t\tmkdirSync(dirname(configPath), { recursive: true });\n\t\twriteFileSync(configPath, `${JSON.stringify(next, null, 2)}\\n`, \"utf8\");\n\t\tcached = next;\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n"]}
@@ -0,0 +1,97 @@
1
+ import type { FileBackup, FileHistorySnapshot } from "./snapshot.ts";
2
+ /** Worktree identity recorded when we last backed up / confirmed a tracking path. */
3
+ interface SeenStats {
4
+ mtimeMs: number;
5
+ size: number;
6
+ mode: number;
7
+ }
8
+ export interface FileHistoryState {
9
+ /** Finalized + persisted frames, oldest first. */
10
+ snapshots: FileHistorySnapshot[];
11
+ /** All tracking-paths ever edited this session. */
12
+ trackedFiles: Set<string>;
13
+ /** Latest backup per tracking path (finalized + in-progress pending versions). */
14
+ latestByTracking: Map<string, FileBackup>;
15
+ /**
16
+ * Worktree mtime/size/mode at the last backup or unchanged confirmation.
17
+ * beginTurn uses this to skip backup-blob stats/content when the worktree
18
+ * has not moved since we last recorded it (still stats the worktree once).
19
+ */
20
+ lastSeen: Map<string, SeenStats>;
21
+ /** The current turn's working frame (built across the turn, persisted at endTurn). */
22
+ pending: FileHistorySnapshot | null;
23
+ /** Whether the pending frame differs from the last finalized frame. */
24
+ dirty: boolean;
25
+ /** Monotonic activity counter (incremented on every finalized frame). */
26
+ seq: number;
27
+ }
28
+ export interface ApplySnapshotOptions {
29
+ /**
30
+ * Absolute paths already known to differ (e.g. from collectChanges).
31
+ * When set, only those paths are restored/deleted and originChanged is skipped.
32
+ */
33
+ onlyPaths?: ReadonlySet<string>;
34
+ }
35
+ /** Bind a session id to its cwd (for relative-path keying). Call at session_start. */
36
+ export declare function registerSession(sid: string, cwd: string): void;
37
+ export declare function disposeSession(sid: string): void;
38
+ export declare function getSnapshots(sid: string): FileHistorySnapshot[];
39
+ /**
40
+ * Open the working frame for a turn and re-record every tracked file at its
41
+ * current state (reuse latest backup when unchanged, new version when changed).
42
+ * Sets state.dirty when any file produced a new version.
43
+ */
44
+ export declare function beginTurn(sid: string): Promise<void>;
45
+ /**
46
+ * Back up a file about to be edited/written, if not already captured this turn.
47
+ * Call from the tool_call hook BEFORE the edit lands. ENOENT target -> null
48
+ * marker (rewind deletes the created file). Synchronous so the backup is on disk
49
+ * before the hook returns (see createBackupSync).
50
+ */
51
+ export declare function trackEdit(sid: string, absPath: string): void;
52
+ /**
53
+ * Finalize the turn. Returns the snapshot to persist (caller appendEntry's it),
54
+ * or null when nothing changed this turn. Pushes finalized frames into the
55
+ * in-memory ring (capped at MAX_SNAPSHOTS).
56
+ */
57
+ export declare function endTurn(sid: string, userEntryId: string, turnId: string, prompt: string, timestamp: string, maxSnapshots?: number): FileHistorySnapshot | null;
58
+ /**
59
+ * Absolute paths that restoring to `target` would change on disk (empty =
60
+ * nothing to do). Same walk applySnapshot performs, without writing — the
61
+ * caller can both count and preview the files from one pass. Concurrent with
62
+ * IO_CONCURRENCY; result order matches trackedFiles insertion order.
63
+ */
64
+ export declare function collectChanges(sid: string, target: FileHistorySnapshot): Promise<string[]>;
65
+ export interface CoarseDiffStats {
66
+ /** Absolute paths that would change (same as collectChanges). */
67
+ paths: string[];
68
+ /**
69
+ * Coarse line insertions when restoring (lines present in backup, not in
70
+ * current). Bag-of-lines, not a true Myers diff — confirm UI only.
71
+ */
72
+ insertions: number;
73
+ /** Coarse line deletions when restoring (lines present in current, not in backup). */
74
+ deletions: number;
75
+ }
76
+ /**
77
+ * Coarse +N/−M line stats for a restore confirm dialog. Only loads text for
78
+ * paths already known to differ (from collectChanges). Oversized files still
79
+ * appear in `paths` but contribute 0 to line totals. No extra dependency.
80
+ */
81
+ export declare function collectChangeDiffStats(sid: string, target: FileHistorySnapshot, changedPaths: readonly string[]): Promise<CoarseDiffStats>;
82
+ /**
83
+ * Restore the work tree to `target`. Returns the list of changed file paths.
84
+ * Pass `onlyPaths` (from a prior collectChanges) to skip a second originChanged
85
+ * pass and only touch those absolute paths.
86
+ */
87
+ export declare function applySnapshot(sid: string, target: FileHistorySnapshot, opts?: ApplySnapshotOptions): Promise<string[]>;
88
+ /** Rebuild in-memory state from snapshots persisted in the session JSONL. */
89
+ export declare function restoreStateFromSnapshots(sid: string, cwd: string, snapshots: FileHistorySnapshot[], maxSnapshots?: number): void;
90
+ /**
91
+ * Hard-link this session's backup blobs from a previous session's directory
92
+ * (resume/fork carries the conversation + its snapshot index, but the blobs live
93
+ * under the old session id). Falls back to copy. No-op when ids match.
94
+ */
95
+ export declare function migrateBackupsFromSession(prevSid: string, sid: string, snapshots: FileHistorySnapshot[]): Promise<void>;
96
+ export {};
97
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../src/extensions/rewind/engine.ts"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAcrE,qFAAqF;AACrF,UAAU,SAAS;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACb;AAUD,MAAM,WAAW,gBAAgB;IAChC,kDAAkD;IAClD,SAAS,EAAE,mBAAmB,EAAE,CAAC;IACjC,mDAAmD;IACnD,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1B,kFAAkF;IAClF,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAC1C;;;;OAIG;IACH,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACjC,sFAAsF;IACtF,OAAO,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACpC,uEAAuE;IACvE,KAAK,EAAE,OAAO,CAAC;IACf,yEAAyE;IACzE,GAAG,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,oBAAoB;IACpC;;;OAGG;IACH,SAAS,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAChC;AAwDD,sFAAsF;AACtF,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAG9D;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAGhD;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,mBAAmB,EAAE,CAE/D;AAqOD;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAqD1D;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CA2B5D;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CACtB,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,YAAY,SAAgB,GAC1B,mBAAmB,GAAG,IAAI,CAkB5B;AAiCD;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAkBhG;AAED,MAAM,WAAW,eAAe;IAC/B,iEAAiE;IACjE,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB;;;OAGG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB,sFAAsF;IACtF,SAAS,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAsB,sBAAsB,CAC3C,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,mBAAmB,EAC3B,YAAY,EAAE,SAAS,MAAM,EAAE,GAC7B,OAAO,CAAC,eAAe,CAAC,CA+B1B;AAkFD;;;;GAIG;AACH,wBAAsB,aAAa,CAClC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,mBAAmB,EAC3B,IAAI,CAAC,EAAE,oBAAoB,GACzB,OAAO,CAAC,MAAM,EAAE,CAAC,CAuCnB;AAID,6EAA6E;AAC7E,wBAAgB,yBAAyB,CACxC,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,mBAAmB,EAAE,EAChC,YAAY,SAAgB,GAC1B,IAAI,CAyBN;AAED;;;;GAIG;AACH,wBAAsB,yBAAyB,CAC9C,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,mBAAmB,EAAE,GAC9B,OAAO,CAAC,IAAI,CAAC,CAyBf","sourcesContent":["/**\n * engine.ts — file-history backup engine for the rewind extension.\n *\n * Ported from Claude Code 2.1.88's src/utils/fileHistory.ts, adapted from its\n * React state-updater to module-level per-session maps. The core idea (and the\n * reason this exists): we back up ONLY the files Pi's edit/write tools are about\n * to modify — one copyFile before the edit — instead of snapshotting the whole\n * work tree. Cost is proportional to \"how many files Pi changed\", not project\n * size, so it never blocks the session-lifecycle critical path and storage stays\n * tiny.\n *\n * Per turn:\n * - beginTurn() (before_agent_start): open a working frame and re-record every\n * already-tracked file at its current (turn-start) state, reusing the latest\n * backup when unchanged (worktree lastSeen → mtime/size/content), creating a\n * new version when not. lastSeen skips backup-blob IO when the worktree has\n * not moved since the last confirm; content compare streams in 64 KiB chunks.\n * - trackEdit() (tool_call edit|write, before the write): back up a *newly*\n * edited file at its pre-edit state into the working frame (null marker when\n * the target does not exist yet, so rewind deletes the created file).\n * - endTurn() (agent_settled): if anything changed, stamp + return the frame\n * to persist; else discard it. agent_settled (not agent_end) so auto-retry /\n * overflow compact-retry / queued follow-ups share one logical turn.\n *\n * Rewind = applySnapshot(): restore every tracked file to the version recorded in\n * the target frame (copy back / delete for null), touching only files that differ.\n *\n * Backups live at <rewindBackupsDir(sessionId)>/<sha256(relpath)[:16]>@v<n>.\n */\nimport { createHash } from \"node:crypto\";\nimport { chmodSync, copyFileSync, mkdirSync, type Stats, statSync } from \"node:fs\";\nimport { chmod, copyFile, link, mkdir, open, readFile, stat, unlink } from \"node:fs/promises\";\nimport { dirname, isAbsolute, join, relative } from \"node:path\";\nimport type { FileBackup, FileHistorySnapshot } from \"./snapshot.ts\";\nimport { backupsDir } from \"./storage.ts\";\n\n/** Cap on retained snapshots per session (matches CC's MAX_SNAPSHOTS). */\nconst MAX_SNAPSHOTS = 100;\n/** Avoid reading very large files solely to compare backup content. */\nconst MAX_CONTENT_BYTES = 25 * 1024 * 1024;\n/** Cap concurrent backup/compare/restore IO so long tracked sets don't thrash handles. */\nconst IO_CONCURRENCY = 16;\n/** Cap bytes loaded for coarse restore line stats (confirm dialog only). */\nconst MAX_DIFF_BYTES = 1_048_576;\n/** Streaming compare chunk size (avoids buffering whole files up to MAX_CONTENT_BYTES). */\nconst COMPARE_CHUNK_BYTES = 64 * 1024;\n\n/** Worktree identity recorded when we last backed up / confirmed a tracking path. */\ninterface SeenStats {\n\tmtimeMs: number;\n\tsize: number;\n\tmode: number;\n}\n\nfunction seenFromStats(st: Stats): SeenStats {\n\treturn { mtimeMs: st.mtimeMs, size: st.size, mode: st.mode };\n}\n\nfunction sameSeen(a: SeenStats, b: Stats): boolean {\n\treturn a.mtimeMs === b.mtimeMs && a.size === b.size && a.mode === b.mode;\n}\n\nexport interface FileHistoryState {\n\t/** Finalized + persisted frames, oldest first. */\n\tsnapshots: FileHistorySnapshot[];\n\t/** All tracking-paths ever edited this session. */\n\ttrackedFiles: Set<string>;\n\t/** Latest backup per tracking path (finalized + in-progress pending versions). */\n\tlatestByTracking: Map<string, FileBackup>;\n\t/**\n\t * Worktree mtime/size/mode at the last backup or unchanged confirmation.\n\t * beginTurn uses this to skip backup-blob stats/content when the worktree\n\t * has not moved since we last recorded it (still stats the worktree once).\n\t */\n\tlastSeen: Map<string, SeenStats>;\n\t/** The current turn's working frame (built across the turn, persisted at endTurn). */\n\tpending: FileHistorySnapshot | null;\n\t/** Whether the pending frame differs from the last finalized frame. */\n\tdirty: boolean;\n\t/** Monotonic activity counter (incremented on every finalized frame). */\n\tseq: number;\n}\n\nexport interface ApplySnapshotOptions {\n\t/**\n\t * Absolute paths already known to differ (e.g. from collectChanges).\n\t * When set, only those paths are restored/deleted and originChanged is skipped.\n\t */\n\tonlyPaths?: ReadonlySet<string>;\n}\n\n// ---- per-session state ----------------------------------------------------\n\nconst states = new Map<string, FileHistoryState>();\nconst cwds = new Map<string, string>();\n\nfunction freshState(): FileHistoryState {\n\treturn {\n\t\tsnapshots: [],\n\t\ttrackedFiles: new Set(),\n\t\tlatestByTracking: new Map(),\n\t\tlastSeen: new Map(),\n\t\tpending: null,\n\t\tdirty: false,\n\t\tseq: 0,\n\t};\n}\n\n/** Run async work over items with a fixed concurrency cap. Preserves result order. */\nasync function mapPool<T, R>(items: readonly T[], concurrency: number, fn: (item: T) => Promise<R>): Promise<R[]> {\n\tif (items.length === 0) return [];\n\tconst results = new Array<R>(items.length);\n\tlet next = 0;\n\tasync function worker(): Promise<void> {\n\t\tfor (;;) {\n\t\t\tconst i = next++;\n\t\t\tif (i >= items.length) return;\n\t\t\tresults[i] = await fn(items[i]!);\n\t\t}\n\t}\n\tconst n = Math.min(concurrency, items.length);\n\tawait Promise.all(Array.from({ length: n }, () => worker()));\n\treturn results;\n}\n\n/** Rebuild latestByTracking from finalized frames (oldest → newest, last write wins). */\nfunction rebuildLatestIndex(snapshots: FileHistorySnapshot[]): Map<string, FileBackup> {\n\tconst latest = new Map<string, FileBackup>();\n\tfor (const snap of snapshots) {\n\t\tfor (const [tracking, backup] of Object.entries(snap.trackedFileBackups)) {\n\t\t\tlatest.set(tracking, backup);\n\t\t}\n\t}\n\treturn latest;\n}\n\nfunction getState(sid: string): FileHistoryState {\n\tlet s = states.get(sid);\n\tif (!s) {\n\t\ts = freshState();\n\t\tstates.set(sid, s);\n\t}\n\treturn s;\n}\n\n/** Bind a session id to its cwd (for relative-path keying). Call at session_start. */\nexport function registerSession(sid: string, cwd: string): void {\n\tcwds.set(sid, cwd);\n\tgetState(sid);\n}\n\nexport function disposeSession(sid: string): void {\n\tstates.delete(sid);\n\tcwds.delete(sid);\n}\n\nexport function getSnapshots(sid: string): FileHistorySnapshot[] {\n\treturn states.get(sid)?.snapshots ?? [];\n}\n\nfunction cwdFor(sid: string): string {\n\treturn cwds.get(sid) ?? process.cwd();\n}\n\n// ---- path helpers ---------------------------------------------------------\n\n/** Use the cwd-relative path as the tracking key when inside cwd (shorter, portable). */\nfunction shorten(absPath: string, cwd: string): string {\n\tif (!isAbsolute(absPath)) return absPath;\n\tif (absPath === cwd) return absPath;\n\tconst rel = relative(cwd, absPath);\n\tif (!rel || rel.startsWith(\"..\") || isAbsolute(rel)) return absPath;\n\treturn rel;\n}\n\nfunction expand(tracking: string, cwd: string): string {\n\treturn isAbsolute(tracking) ? tracking : join(cwd, tracking);\n}\n\nfunction backupName(tracking: string, version: number): string {\n\tconst h = createHash(\"sha256\").update(tracking).digest(\"hex\").slice(0, 16);\n\treturn `${h}@v${version}`;\n}\n\nfunction backupPathFor(sid: string, name: string): string {\n\treturn join(backupsDir(sid), name);\n}\n\nfunction latestBackupOf(state: FileHistoryState, tracking: string): FileBackup | undefined {\n\treturn state.latestByTracking.get(tracking);\n}\n\n/** First-ever recorded backup for a file (used when rewinding before it was tracked). */\nfunction firstBackupName(state: FileHistoryState, tracking: string): string | null | undefined {\n\tfor (const snap of state.snapshots) {\n\t\tconst b = snap.trackedFileBackups[tracking];\n\t\tif (b && b.version === 1) return b.backupName;\n\t}\n\treturn undefined;\n}\n\n/** Resolve the backup blob name for `tracking` at `target` (null = did not exist). */\nfunction backupNameForTarget(\n\tstate: FileHistoryState,\n\ttarget: FileHistorySnapshot,\n\ttracking: string,\n): string | null | undefined {\n\tconst tb = target.trackedFileBackups[tracking];\n\tif (tb) return tb.backupName;\n\treturn firstBackupName(state, tracking);\n}\n\n// ---- change detection (ported fileHistory.ts compareStatsAndContent;\n// content path streams via filesEqualChunked instead of full-buffer reads)\n\nfunction isENOENT(e: unknown): boolean {\n\treturn !!e && typeof e === \"object\" && (e as { code?: string }).code === \"ENOENT\";\n}\n\nasync function statOrNull(p: string): Promise<Stats | null> {\n\ttry {\n\t\treturn await stat(p);\n\t} catch (e) {\n\t\tif (isENOENT(e)) return null;\n\t\tthrow e;\n\t}\n}\n\n/**\n * Raw-byte equality without buffering whole files. A utf-8 decode maps invalid\n * sequences to U+FFFD, which can make two DIFFERENT binary files compare equal —\n * and then rewind would silently skip both the re-backup and the restore.\n */\nasync function filesEqualChunked(aPath: string, bPath: string, size: number): Promise<boolean> {\n\tif (size === 0) return true;\n\tconst [aHandle, bHandle] = await Promise.all([open(aPath, \"r\"), open(bPath, \"r\")]);\n\ttry {\n\t\tconst aBuf = Buffer.allocUnsafe(COMPARE_CHUNK_BYTES);\n\t\tconst bBuf = Buffer.allocUnsafe(COMPARE_CHUNK_BYTES);\n\t\tlet remaining = size;\n\t\twhile (remaining > 0) {\n\t\t\tconst want = Math.min(COMPARE_CHUNK_BYTES, remaining);\n\t\t\tconst [aRead, bRead] = await Promise.all([\n\t\t\t\taHandle.read(aBuf, 0, want, null),\n\t\t\t\tbHandle.read(bBuf, 0, want, null),\n\t\t\t]);\n\t\t\tif (aRead.bytesRead !== bRead.bytesRead) return false;\n\t\t\tif (aRead.bytesRead === 0) return remaining === 0;\n\t\t\tif (!aBuf.subarray(0, aRead.bytesRead).equals(bBuf.subarray(0, bRead.bytesRead))) return false;\n\t\t\tremaining -= aRead.bytesRead;\n\t\t}\n\t\treturn true;\n\t} finally {\n\t\tawait Promise.allSettled([aHandle.close(), bHandle.close()]);\n\t}\n}\n\n/** True when the on-disk file differs from its backup blob. */\nasync function originChanged(sid: string, filePath: string, name: string, hint?: Stats): Promise<boolean> {\n\tconst backupPath = backupPathFor(sid, name);\n\tconst orig = hint ?? (await statOrNull(filePath).catch(() => null));\n\tconst back = await statOrNull(backupPath).catch(() => null);\n\n\t// One exists, one missing -> changed.\n\tif ((orig === null) !== (back === null)) return true;\n\tif (orig === null || back === null) return false;\n\tif (orig.mode !== back.mode || orig.size !== back.size) return true;\n\t// Original untouched since the backup was written -> unchanged (skip content read).\n\tif (orig.mtimeMs < back.mtimeMs) return false;\n\t// Memory guard: don't load huge files just to byte-compare; assume changed and\n\t// let createBackup stream a new version instead (copyFile never buffers whole files).\n\tif (orig.size > MAX_CONTENT_BYTES) return true;\n\ttry {\n\t\treturn !(await filesEqualChunked(filePath, backupPath, orig.size));\n\t} catch {\n\t\treturn true;\n\t}\n}\n\n// ---- backup / restore IO --------------------------------------------------\n\n/** Copy the file's current contents into a backup blob; null backup when absent. */\nasync function createBackup(\n\tsid: string,\n\tfilePath: string,\n\ttracking: string,\n\tversion: number,\n\tknown?: Stats | null,\n): Promise<FileBackup> {\n\tlet src: Stats;\n\tif (known === null) return { backupName: null, version };\n\tif (known) {\n\t\tsrc = known;\n\t} else {\n\t\ttry {\n\t\t\tsrc = await stat(filePath);\n\t\t} catch (e) {\n\t\t\tif (isENOENT(e)) return { backupName: null, version };\n\t\t\tthrow e;\n\t\t}\n\t}\n\tconst name = backupName(tracking, version);\n\tconst dest = backupPathFor(sid, name);\n\ttry {\n\t\tawait copyFile(filePath, dest);\n\t} catch (e) {\n\t\tif (!isENOENT(e)) throw e;\n\t\tawait mkdir(dirname(dest), { recursive: true });\n\t\tawait copyFile(filePath, dest);\n\t}\n\ttry {\n\t\tawait chmod(dest, src.mode);\n\t} catch {\n\t\t// best-effort (e.g. Windows); content is what matters\n\t}\n\treturn { backupName: name, version };\n}\n\n/**\n * Synchronous backup, used on the edit critical path (tool_call). Doing the copy\n * synchronously guarantees it completes before the hook returns control to the\n * host — so the backup always captures the file's PRE-edit contents, regardless\n * of whether the host awaits the hook before running the tool.\n *\n * `known` reuses a pre-stat from the caller (`null` = known ENOENT) so trackEdit\n * can record lastSeen without a second statSync on the critical path.\n */\nfunction createBackupSync(\n\tsid: string,\n\tfilePath: string,\n\ttracking: string,\n\tversion: number,\n\tknown?: Stats | null,\n): FileBackup {\n\tlet src: Stats;\n\tif (known === null) return { backupName: null, version };\n\tif (known) {\n\t\tsrc = known;\n\t} else {\n\t\ttry {\n\t\t\tsrc = statSync(filePath);\n\t\t} catch (e) {\n\t\t\tif (isENOENT(e)) return { backupName: null, version };\n\t\t\tthrow e;\n\t\t}\n\t}\n\tconst name = backupName(tracking, version);\n\tconst dest = backupPathFor(sid, name);\n\ttry {\n\t\tcopyFileSync(filePath, dest);\n\t} catch (e) {\n\t\tif (!isENOENT(e)) throw e;\n\t\tmkdirSync(dirname(dest), { recursive: true });\n\t\tcopyFileSync(filePath, dest);\n\t}\n\ttry {\n\t\tchmodSync(dest, src.mode);\n\t} catch {\n\t\t// best-effort\n\t}\n\treturn { backupName: name, version };\n}\n\nasync function restoreBackup(sid: string, filePath: string, name: string): Promise<void> {\n\tconst backupPath = backupPathFor(sid, name);\n\tlet back: Stats;\n\ttry {\n\t\tback = await stat(backupPath);\n\t} catch {\n\t\treturn; // backup vanished; leave the file untouched\n\t}\n\ttry {\n\t\tawait copyFile(backupPath, filePath);\n\t} catch (e) {\n\t\tif (!isENOENT(e)) throw e;\n\t\tawait mkdir(dirname(filePath), { recursive: true });\n\t\tawait copyFile(backupPath, filePath);\n\t}\n\ttry {\n\t\tawait chmod(filePath, back.mode);\n\t} catch {\n\t\t// best-effort\n\t}\n}\n\n// ---- per-turn lifecycle ---------------------------------------------------\n\n/**\n * Open the working frame for a turn and re-record every tracked file at its\n * current state (reuse latest backup when unchanged, new version when changed).\n * Sets state.dirty when any file produced a new version.\n */\nexport async function beginTurn(sid: string): Promise<void> {\n\tconst state = getState(sid);\n\tconst cwd = cwdFor(sid);\n\tconst backups: Record<string, FileBackup> = {};\n\tlet dirty = false;\n\n\tawait mapPool(Array.from(state.trackedFiles), IO_CONCURRENCY, async (tracking) => {\n\t\ttry {\n\t\t\tconst filePath = expand(tracking, cwd);\n\t\t\tconst latest = latestBackupOf(state, tracking);\n\t\t\tconst nextVersion = latest ? latest.version + 1 : 1;\n\t\t\tconst st = await statOrNull(filePath);\n\t\t\tif (!st) {\n\t\t\t\t// Already recorded absent in the latest frame -> reuse it. Allocating a\n\t\t\t\t// fresh null version every turn would pin dirty=true forever once a\n\t\t\t\t// tracked file is deleted, defeating the \"skip unchanged turns\" check\n\t\t\t\t// and flushing real checkpoints out of the capped ring.\n\t\t\t\tstate.lastSeen.delete(tracking);\n\t\t\t\tif (latest && latest.backupName === null) {\n\t\t\t\t\tbackups[tracking] = latest;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst absent: FileBackup = { backupName: null, version: nextVersion };\n\t\t\t\tbackups[tracking] = absent;\n\t\t\t\tstate.latestByTracking.set(tracking, absent);\n\t\t\t\tdirty = true;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Worktree identity unchanged since last backup/confirm → reuse without\n\t\t\t// opening the backup blob (still paid one worktree stat above).\n\t\t\tconst seen = state.lastSeen.get(tracking);\n\t\t\tif (latest && latest.backupName !== null && seen && sameSeen(seen, st)) {\n\t\t\t\tbackups[tracking] = latest;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (latest && latest.backupName !== null && !(await originChanged(sid, filePath, latest.backupName, st))) {\n\t\t\t\tbackups[tracking] = latest; // unchanged -> reuse\n\t\t\t\tstate.lastSeen.set(tracking, seenFromStats(st));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst created = await createBackup(sid, filePath, tracking, nextVersion, st);\n\t\t\tbackups[tracking] = created;\n\t\t\tstate.latestByTracking.set(tracking, created);\n\t\t\t// Record the pre-backup worktree identity (copyFile does not change it).\n\t\t\tstate.lastSeen.set(tracking, seenFromStats(st));\n\t\t\tdirty = true;\n\t\t} catch {\n\t\t\t// skip this file; never break the turn\n\t\t}\n\t});\n\n\tstate.pending = { v: 1, userEntryId: \"\", turnId: \"\", prompt: \"\", trackedFileBackups: backups, timestamp: \"\" };\n\tstate.dirty = dirty;\n}\n\n/**\n * Back up a file about to be edited/written, if not already captured this turn.\n * Call from the tool_call hook BEFORE the edit lands. ENOENT target -> null\n * marker (rewind deletes the created file). Synchronous so the backup is on disk\n * before the hook returns (see createBackupSync).\n */\nexport function trackEdit(sid: string, absPath: string): void {\n\tconst state = getState(sid);\n\tconst cwd = cwdFor(sid);\n\tconst tracking = shorten(absPath, cwd);\n\n\tif (!state.pending) {\n\t\tstate.pending = { v: 1, userEntryId: \"\", turnId: \"\", prompt: \"\", trackedFileBackups: {}, timestamp: \"\" };\n\t}\n\tif (state.pending.trackedFileBackups[tracking]) return; // already captured this turn\n\n\tconst latest = latestBackupOf(state, tracking);\n\tconst version = latest ? latest.version + 1 : 1;\n\tconst filePath = expand(tracking, cwd);\n\t// One pre-edit stat: drives the backup and lastSeen (null = new-file marker).\n\tlet preEdit: Stats | null = null;\n\ttry {\n\t\tpreEdit = statSync(filePath);\n\t} catch (e) {\n\t\tif (!isENOENT(e)) throw e;\n\t}\n\tconst backup = createBackupSync(sid, filePath, tracking, version, preEdit);\n\tstate.pending.trackedFileBackups[tracking] = backup;\n\tstate.trackedFiles.add(tracking);\n\tstate.latestByTracking.set(tracking, backup);\n\tif (preEdit) state.lastSeen.set(tracking, seenFromStats(preEdit));\n\telse state.lastSeen.delete(tracking);\n\tstate.dirty = true;\n}\n\n/**\n * Finalize the turn. Returns the snapshot to persist (caller appendEntry's it),\n * or null when nothing changed this turn. Pushes finalized frames into the\n * in-memory ring (capped at MAX_SNAPSHOTS).\n */\nexport function endTurn(\n\tsid: string,\n\tuserEntryId: string,\n\tturnId: string,\n\tprompt: string,\n\ttimestamp: string,\n\tmaxSnapshots = MAX_SNAPSHOTS,\n): FileHistorySnapshot | null {\n\tconst state = getState(sid);\n\tconst pending = state.pending;\n\tstate.pending = null;\n\tif (!pending || !state.dirty) {\n\t\tstate.dirty = false;\n\t\treturn null;\n\t}\n\tstate.dirty = false;\n\tconst frame: FileHistorySnapshot = { ...pending, userEntryId, turnId, prompt, timestamp };\n\tstate.snapshots.push(frame);\n\tif (state.snapshots.length > maxSnapshots) {\n\t\tconst dropped = state.snapshots.slice(0, state.snapshots.length - maxSnapshots);\n\t\tstate.snapshots = state.snapshots.slice(-maxSnapshots);\n\t\tvoid pruneDroppedBlobs(sid, dropped, state.snapshots);\n\t}\n\tstate.seq++;\n\treturn frame;\n}\n\n/**\n * Best-effort deletion of backup blobs referenced ONLY by frames dropped from\n * the capped ring. Backups are reused across frames (an unchanged file keeps\n * pointing at the same version), so a blob is unlinked only when no retained\n * frame still references it. Without this, the cap trims the in-memory index\n * while the blob files accumulate for the whole session — gc.ts only reclaims\n * whole session directories.\n */\nasync function pruneDroppedBlobs(\n\tsid: string,\n\tdropped: FileHistorySnapshot[],\n\tretained: FileHistorySnapshot[],\n): Promise<void> {\n\tconst live = new Set<string>();\n\tfor (const snap of retained) {\n\t\tfor (const b of Object.values(snap.trackedFileBackups)) {\n\t\t\tif (b.backupName) live.add(b.backupName);\n\t\t}\n\t}\n\tconst doomed = new Set<string>();\n\tfor (const snap of dropped) {\n\t\tfor (const b of Object.values(snap.trackedFileBackups)) {\n\t\t\tif (b.backupName && !live.has(b.backupName)) doomed.add(b.backupName);\n\t\t}\n\t}\n\tif (doomed.size === 0) return;\n\tawait Promise.allSettled(Array.from(doomed, (name) => unlink(backupPathFor(sid, name))));\n}\n\n// ---- rewind ---------------------------------------------------------------\n\n/**\n * Absolute paths that restoring to `target` would change on disk (empty =\n * nothing to do). Same walk applySnapshot performs, without writing — the\n * caller can both count and preview the files from one pass. Concurrent with\n * IO_CONCURRENCY; result order matches trackedFiles insertion order.\n */\nexport async function collectChanges(sid: string, target: FileHistorySnapshot): Promise<string[]> {\n\tconst state = getState(sid);\n\tconst cwd = cwdFor(sid);\n\tconst trackings = Array.from(state.trackedFiles);\n\tconst results = await mapPool(trackings, IO_CONCURRENCY, async (tracking) => {\n\t\ttry {\n\t\t\tconst filePath = expand(tracking, cwd);\n\t\t\tconst name = backupNameForTarget(state, target, tracking);\n\t\t\tif (name === undefined) return null;\n\t\t\tif (name === null) {\n\t\t\t\treturn (await statOrNull(filePath)) ? filePath : null;\n\t\t\t}\n\t\t\treturn (await originChanged(sid, filePath, name)) ? filePath : null;\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t});\n\treturn results.filter((p): p is string => p !== null);\n}\n\nexport interface CoarseDiffStats {\n\t/** Absolute paths that would change (same as collectChanges). */\n\tpaths: string[];\n\t/**\n\t * Coarse line insertions when restoring (lines present in backup, not in\n\t * current). Bag-of-lines, not a true Myers diff — confirm UI only.\n\t */\n\tinsertions: number;\n\t/** Coarse line deletions when restoring (lines present in current, not in backup). */\n\tdeletions: number;\n}\n\n/**\n * Coarse +N/−M line stats for a restore confirm dialog. Only loads text for\n * paths already known to differ (from collectChanges). Oversized files still\n * appear in `paths` but contribute 0 to line totals. No extra dependency.\n */\nexport async function collectChangeDiffStats(\n\tsid: string,\n\ttarget: FileHistorySnapshot,\n\tchangedPaths: readonly string[],\n): Promise<CoarseDiffStats> {\n\tif (changedPaths.length === 0) {\n\t\treturn { paths: [], insertions: 0, deletions: 0 };\n\t}\n\tconst state = getState(sid);\n\tconst cwd = cwdFor(sid);\n\t// Reverse map abs path → tracking key for the known changed set.\n\tconst trackingByAbs = new Map<string, string>();\n\tfor (const tracking of state.trackedFiles) {\n\t\ttrackingByAbs.set(expand(tracking, cwd), tracking);\n\t}\n\n\tconst results = await mapPool([...changedPaths], IO_CONCURRENCY, async (filePath) => {\n\t\ttry {\n\t\t\tconst tracking = trackingByAbs.get(filePath);\n\t\t\tif (!tracking) return { insertions: 0, deletions: 0 };\n\t\t\tconst name = backupNameForTarget(state, target, tracking);\n\t\t\tif (name === undefined) return { insertions: 0, deletions: 0 };\n\t\t\treturn await coarseLineDelta(sid, filePath, name);\n\t\t} catch {\n\t\t\treturn { insertions: 0, deletions: 0 };\n\t\t}\n\t});\n\n\tlet insertions = 0;\n\tlet deletions = 0;\n\tfor (const r of results) {\n\t\tinsertions += r.insertions;\n\t\tdeletions += r.deletions;\n\t}\n\treturn { paths: [...changedPaths], insertions, deletions };\n}\n\n/**\n * Bag-of-lines delta for current worktree → backup target (restore direction).\n * insertions = lines that appear after restore; deletions = lines removed.\n */\nasync function coarseLineDelta(\n\tsid: string,\n\tfilePath: string,\n\tbackupName: string | null,\n): Promise<{ insertions: number; deletions: number }> {\n\tconst currentText = await readTextCapped(filePath, MAX_DIFF_BYTES);\n\tif (backupName === null) {\n\t\t// Snapshot: file did not exist → restore deletes it.\n\t\tif (currentText === null) return { insertions: 0, deletions: 0 };\n\t\treturn { insertions: 0, deletions: countLines(currentText) };\n\t}\n\tconst backupText = await readTextCapped(backupPathFor(sid, backupName), MAX_DIFF_BYTES);\n\tif (currentText === null && backupText === null) return { insertions: 0, deletions: 0 };\n\tif (currentText === null) return { insertions: countLines(backupText ?? \"\"), deletions: 0 };\n\tif (backupText === null) return { insertions: 0, deletions: countLines(currentText) };\n\treturn bagOfLinesDelta(currentText, backupText);\n}\n\n/** null = missing or oversize/unreadable (skip line contrib). */\nasync function readTextCapped(filePath: string, maxBytes: number): Promise<string | null> {\n\ttry {\n\t\tconst st = await statOrNull(filePath);\n\t\tif (!st) return null;\n\t\tif (st.size > maxBytes) return null;\n\t\tconst buf = await readFile(filePath);\n\t\t// Skip obvious binary (NUL in the first 8K).\n\t\tconst sample = buf.subarray(0, Math.min(buf.length, 8192));\n\t\tif (sample.includes(0)) return null;\n\t\treturn buf.toString(\"utf8\");\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction countLines(text: string): number {\n\tif (text.length === 0) return 0;\n\tlet n = 1;\n\tfor (let i = 0; i < text.length; i++) {\n\t\tif (text.charCodeAt(i) === 10 /* \\n */) n++;\n\t}\n\t// Trailing newline does not add an extra empty \"line\" for display counts.\n\tif (text.endsWith(\"\\n\")) n--;\n\treturn Math.max(n, 0);\n}\n\n/**\n * Multiset frequency delta: from → to.\n * deletions = lines over-represented in `from`; insertions = over-represented in `to`.\n */\nfunction bagOfLinesDelta(from: string, to: string): { insertions: number; deletions: number } {\n\tconst fromCounts = lineFrequency(from);\n\tconst toCounts = lineFrequency(to);\n\tlet insertions = 0;\n\tlet deletions = 0;\n\tconst keys = new Set([...fromCounts.keys(), ...toCounts.keys()]);\n\tfor (const key of keys) {\n\t\tconst a = fromCounts.get(key) ?? 0;\n\t\tconst b = toCounts.get(key) ?? 0;\n\t\tif (b > a) insertions += b - a;\n\t\telse if (a > b) deletions += a - b;\n\t}\n\treturn { insertions, deletions };\n}\n\nfunction lineFrequency(text: string): Map<string, number> {\n\tconst map = new Map<string, number>();\n\t// Preserve empty file as zero lines; otherwise split including last empty.\n\tif (text.length === 0) return map;\n\tconst lines = text.split(\"\\n\");\n\tif (lines.length > 0 && lines[lines.length - 1] === \"\") lines.pop();\n\tfor (const line of lines) {\n\t\tmap.set(line, (map.get(line) ?? 0) + 1);\n\t}\n\treturn map;\n}\n\n/**\n * Restore the work tree to `target`. Returns the list of changed file paths.\n * Pass `onlyPaths` (from a prior collectChanges) to skip a second originChanged\n * pass and only touch those absolute paths.\n */\nexport async function applySnapshot(\n\tsid: string,\n\ttarget: FileHistorySnapshot,\n\topts?: ApplySnapshotOptions,\n): Promise<string[]> {\n\tconst state = getState(sid);\n\tconst cwd = cwdFor(sid);\n\tconst only = opts?.onlyPaths;\n\tconst trackings = Array.from(state.trackedFiles).filter((tracking) => {\n\t\tif (!only) return true;\n\t\treturn only.has(expand(tracking, cwd));\n\t});\n\n\tconst results = await mapPool(trackings, IO_CONCURRENCY, async (tracking) => {\n\t\ttry {\n\t\t\tconst filePath = expand(tracking, cwd);\n\t\t\tconst name = backupNameForTarget(state, target, tracking);\n\t\t\tif (name === undefined) return null; // can't resolve -> leave file alone\n\t\t\tif (name === null) {\n\t\t\t\ttry {\n\t\t\t\t\tawait unlink(filePath);\n\t\t\t\t\t// Worktree no longer matches any recorded identity.\n\t\t\t\t\tstate.lastSeen.delete(tracking);\n\t\t\t\t\treturn filePath;\n\t\t\t\t} catch (e) {\n\t\t\t\t\tif (!isENOENT(e)) throw e;\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// onlyPaths already proven different at confirm time — skip re-compare.\n\t\t\tif (only || (await originChanged(sid, filePath, name))) {\n\t\t\t\tawait restoreBackup(sid, filePath, name);\n\t\t\t\t// Drop stale lastSeen: worktree now matches the target blob, not the\n\t\t\t\t// latest backup identity beginTurn compares against.\n\t\t\t\tstate.lastSeen.delete(tracking);\n\t\t\t\treturn filePath;\n\t\t\t}\n\t\t\treturn null;\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t});\n\treturn results.filter((p): p is string => p !== null);\n}\n\n// ---- persistence rebuild + resume migration -------------------------------\n\n/** Rebuild in-memory state from snapshots persisted in the session JSONL. */\nexport function restoreStateFromSnapshots(\n\tsid: string,\n\tcwd: string,\n\tsnapshots: FileHistorySnapshot[],\n\tmaxSnapshots = MAX_SNAPSHOTS,\n): void {\n\tcwds.set(sid, cwd);\n\t// Apply the same cap on reload so a long session's JSONL can't reinflate the\n\t// in-memory ring past the limit. trackedFiles is rebuilt from the retained\n\t// frames only (older frames are unreachable for rewind anyway); blobs only\n\t// those frames referenced are pruned best-effort, mirroring endTurn.\n\tconst retained = snapshots.length > maxSnapshots ? snapshots.slice(-maxSnapshots) : snapshots;\n\tif (retained.length < snapshots.length) {\n\t\tvoid pruneDroppedBlobs(sid, snapshots.slice(0, snapshots.length - retained.length), retained);\n\t}\n\tconst trackedFiles = new Set<string>();\n\tfor (const snap of retained) {\n\t\tfor (const key of Object.keys(snap.trackedFileBackups)) trackedFiles.add(key);\n\t}\n\tstates.set(sid, {\n\t\tsnapshots: [...retained],\n\t\ttrackedFiles,\n\t\tlatestByTracking: rebuildLatestIndex(retained),\n\t\t// lastSeen is process-local; after reload we re-establish it on the first\n\t\t// beginTurn via originChanged / createBackup.\n\t\tlastSeen: new Map(),\n\t\tpending: null,\n\t\tdirty: false,\n\t\tseq: retained.length,\n\t});\n}\n\n/**\n * Hard-link this session's backup blobs from a previous session's directory\n * (resume/fork carries the conversation + its snapshot index, but the blobs live\n * under the old session id). Falls back to copy. No-op when ids match.\n */\nexport async function migrateBackupsFromSession(\n\tprevSid: string,\n\tsid: string,\n\tsnapshots: FileHistorySnapshot[],\n): Promise<void> {\n\tif (!prevSid || prevSid === sid) return;\n\tconst destDir = backupsDir(sid);\n\tawait mkdir(destDir, { recursive: true });\n\tawait Promise.allSettled(\n\t\tsnapshots.flatMap((snap) =>\n\t\t\tObject.values(snap.trackedFileBackups)\n\t\t\t\t.filter((b): b is FileBackup & { backupName: string } => b.backupName !== null)\n\t\t\t\t.map(async ({ backupName: name }) => {\n\t\t\t\t\tconst from = join(backupsDir(prevSid), name);\n\t\t\t\t\tconst to = join(destDir, name);\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait link(from, to);\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tconst code = (e as { code?: string }).code;\n\t\t\t\t\t\tif (code === \"EEXIST\") return;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tawait copyFile(from, to);\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t// best-effort; a missing blob just means that version can't restore\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t),\n\t);\n}\n"]}