meetsoma 0.3.2 → 0.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (516) hide show
  1. package/CHANGELOG.md +26 -194
  2. package/dist/thin-cli.js +1587 -392
  3. package/package.json +12 -59
  4. package/bin/gum +0 -0
  5. package/dist/bun/cli.d.ts +0 -3
  6. package/dist/bun/cli.d.ts.map +0 -1
  7. package/dist/bun/cli.js +0 -7
  8. package/dist/bun/cli.js.map +0 -1
  9. package/dist/bun/register-bedrock.d.ts +0 -2
  10. package/dist/bun/register-bedrock.d.ts.map +0 -1
  11. package/dist/bun/register-bedrock.js +0 -4
  12. package/dist/bun/register-bedrock.js.map +0 -1
  13. package/dist/cli/args.d.ts +0 -49
  14. package/dist/cli/args.d.ts.map +0 -1
  15. package/dist/cli/args.js +0 -304
  16. package/dist/cli/args.js.map +0 -1
  17. package/dist/cli/config-selector.d.ts +0 -14
  18. package/dist/cli/config-selector.d.ts.map +0 -1
  19. package/dist/cli/config-selector.js +0 -31
  20. package/dist/cli/config-selector.js.map +0 -1
  21. package/dist/cli/file-processor.d.ts +0 -15
  22. package/dist/cli/file-processor.d.ts.map +0 -1
  23. package/dist/cli/file-processor.js +0 -83
  24. package/dist/cli/file-processor.js.map +0 -1
  25. package/dist/cli/initial-message.d.ts +0 -18
  26. package/dist/cli/initial-message.d.ts.map +0 -1
  27. package/dist/cli/initial-message.js +0 -22
  28. package/dist/cli/initial-message.js.map +0 -1
  29. package/dist/cli/list-models.d.ts +0 -9
  30. package/dist/cli/list-models.d.ts.map +0 -1
  31. package/dist/cli/list-models.js +0 -92
  32. package/dist/cli/list-models.js.map +0 -1
  33. package/dist/cli/session-picker.d.ts +0 -9
  34. package/dist/cli/session-picker.d.ts.map +0 -1
  35. package/dist/cli/session-picker.js +0 -35
  36. package/dist/cli/session-picker.js.map +0 -1
  37. package/dist/cli.d.ts +0 -3
  38. package/dist/cli.d.ts.map +0 -1
  39. package/dist/cli.js +0 -601
  40. package/dist/cli.js.map +0 -1
  41. package/dist/config.d.ts +0 -68
  42. package/dist/config.d.ts.map +0 -1
  43. package/dist/config.js +0 -203
  44. package/dist/config.js.map +0 -1
  45. package/dist/core/agent-session-runtime.d.ts +0 -134
  46. package/dist/core/agent-session-runtime.d.ts.map +0 -1
  47. package/dist/core/agent-session-runtime.js +0 -264
  48. package/dist/core/agent-session-runtime.js.map +0 -1
  49. package/dist/core/agent-session.d.ts +0 -585
  50. package/dist/core/agent-session.d.ts.map +0 -1
  51. package/dist/core/agent-session.js +0 -2497
  52. package/dist/core/agent-session.js.map +0 -1
  53. package/dist/core/auth-storage.d.ts +0 -132
  54. package/dist/core/auth-storage.d.ts.map +0 -1
  55. package/dist/core/auth-storage.js +0 -422
  56. package/dist/core/auth-storage.js.map +0 -1
  57. package/dist/core/bash-executor.d.ts +0 -46
  58. package/dist/core/bash-executor.d.ts.map +0 -1
  59. package/dist/core/bash-executor.js +0 -113
  60. package/dist/core/bash-executor.js.map +0 -1
  61. package/dist/core/compaction/branch-summarization.d.ts +0 -88
  62. package/dist/core/compaction/branch-summarization.d.ts.map +0 -1
  63. package/dist/core/compaction/branch-summarization.js +0 -243
  64. package/dist/core/compaction/branch-summarization.js.map +0 -1
  65. package/dist/core/compaction/compaction.d.ts +0 -121
  66. package/dist/core/compaction/compaction.d.ts.map +0 -1
  67. package/dist/core/compaction/compaction.js +0 -613
  68. package/dist/core/compaction/compaction.js.map +0 -1
  69. package/dist/core/compaction/index.d.ts +0 -7
  70. package/dist/core/compaction/index.d.ts.map +0 -1
  71. package/dist/core/compaction/index.js +0 -7
  72. package/dist/core/compaction/index.js.map +0 -1
  73. package/dist/core/compaction/utils.d.ts +0 -38
  74. package/dist/core/compaction/utils.d.ts.map +0 -1
  75. package/dist/core/compaction/utils.js +0 -153
  76. package/dist/core/compaction/utils.js.map +0 -1
  77. package/dist/core/defaults.d.ts +0 -3
  78. package/dist/core/defaults.d.ts.map +0 -1
  79. package/dist/core/defaults.js +0 -2
  80. package/dist/core/defaults.js.map +0 -1
  81. package/dist/core/diagnostics.d.ts +0 -15
  82. package/dist/core/diagnostics.d.ts.map +0 -1
  83. package/dist/core/diagnostics.js +0 -2
  84. package/dist/core/diagnostics.js.map +0 -1
  85. package/dist/core/event-bus.d.ts +0 -9
  86. package/dist/core/event-bus.d.ts.map +0 -1
  87. package/dist/core/event-bus.js +0 -25
  88. package/dist/core/event-bus.js.map +0 -1
  89. package/dist/core/exec.d.ts +0 -29
  90. package/dist/core/exec.d.ts.map +0 -1
  91. package/dist/core/exec.js +0 -75
  92. package/dist/core/exec.js.map +0 -1
  93. package/dist/core/export-html/ansi-to-html.d.ts +0 -22
  94. package/dist/core/export-html/ansi-to-html.d.ts.map +0 -1
  95. package/dist/core/export-html/ansi-to-html.js +0 -249
  96. package/dist/core/export-html/ansi-to-html.js.map +0 -1
  97. package/dist/core/export-html/index.d.ts +0 -37
  98. package/dist/core/export-html/index.d.ts.map +0 -1
  99. package/dist/core/export-html/index.js +0 -224
  100. package/dist/core/export-html/index.js.map +0 -1
  101. package/dist/core/export-html/template.css +0 -1001
  102. package/dist/core/export-html/template.html +0 -55
  103. package/dist/core/export-html/template.js +0 -1690
  104. package/dist/core/export-html/tool-renderer.d.ts +0 -40
  105. package/dist/core/export-html/tool-renderer.d.ts.map +0 -1
  106. package/dist/core/export-html/tool-renderer.js +0 -95
  107. package/dist/core/export-html/tool-renderer.js.map +0 -1
  108. package/dist/core/export-html/vendor/highlight.min.js +0 -1213
  109. package/dist/core/export-html/vendor/marked.min.js +0 -6
  110. package/dist/core/extensions/index.d.ts +0 -12
  111. package/dist/core/extensions/index.d.ts.map +0 -1
  112. package/dist/core/extensions/index.js +0 -9
  113. package/dist/core/extensions/index.js.map +0 -1
  114. package/dist/core/extensions/loader.d.ts +0 -25
  115. package/dist/core/extensions/loader.d.ts.map +0 -1
  116. package/dist/core/extensions/loader.js +0 -436
  117. package/dist/core/extensions/loader.js.map +0 -1
  118. package/dist/core/extensions/runner.d.ts +0 -148
  119. package/dist/core/extensions/runner.d.ts.map +0 -1
  120. package/dist/core/extensions/runner.js +0 -700
  121. package/dist/core/extensions/runner.js.map +0 -1
  122. package/dist/core/extensions/types.d.ts +0 -1076
  123. package/dist/core/extensions/types.d.ts.map +0 -1
  124. package/dist/core/extensions/types.js +0 -35
  125. package/dist/core/extensions/types.js.map +0 -1
  126. package/dist/core/extensions/wrapper.d.ts +0 -20
  127. package/dist/core/extensions/wrapper.d.ts.map +0 -1
  128. package/dist/core/extensions/wrapper.js +0 -22
  129. package/dist/core/extensions/wrapper.js.map +0 -1
  130. package/dist/core/footer-data-provider.d.ts +0 -48
  131. package/dist/core/footer-data-provider.d.ts.map +0 -1
  132. package/dist/core/footer-data-provider.js +0 -314
  133. package/dist/core/footer-data-provider.js.map +0 -1
  134. package/dist/core/index.d.ts +0 -11
  135. package/dist/core/index.d.ts.map +0 -1
  136. package/dist/core/index.js +0 -11
  137. package/dist/core/index.js.map +0 -1
  138. package/dist/core/keybindings.d.ts +0 -285
  139. package/dist/core/keybindings.d.ts.map +0 -1
  140. package/dist/core/keybindings.js +0 -251
  141. package/dist/core/keybindings.js.map +0 -1
  142. package/dist/core/messages.d.ts +0 -77
  143. package/dist/core/messages.d.ts.map +0 -1
  144. package/dist/core/messages.js +0 -123
  145. package/dist/core/messages.js.map +0 -1
  146. package/dist/core/model-registry.d.ts +0 -132
  147. package/dist/core/model-registry.d.ts.map +0 -1
  148. package/dist/core/model-registry.js +0 -583
  149. package/dist/core/model-registry.js.map +0 -1
  150. package/dist/core/model-resolver.d.ts +0 -110
  151. package/dist/core/model-resolver.d.ts.map +0 -1
  152. package/dist/core/model-resolver.js +0 -486
  153. package/dist/core/model-resolver.js.map +0 -1
  154. package/dist/core/output-guard.d.ts +0 -6
  155. package/dist/core/output-guard.d.ts.map +0 -1
  156. package/dist/core/output-guard.js +0 -59
  157. package/dist/core/output-guard.js.map +0 -1
  158. package/dist/core/package-manager.d.ts +0 -172
  159. package/dist/core/package-manager.d.ts.map +0 -1
  160. package/dist/core/package-manager.js +0 -1783
  161. package/dist/core/package-manager.js.map +0 -1
  162. package/dist/core/prompt-templates.d.ts +0 -51
  163. package/dist/core/prompt-templates.d.ts.map +0 -1
  164. package/dist/core/prompt-templates.js +0 -249
  165. package/dist/core/prompt-templates.js.map +0 -1
  166. package/dist/core/resolve-config-value.d.ts +0 -23
  167. package/dist/core/resolve-config-value.d.ts.map +0 -1
  168. package/dist/core/resolve-config-value.js +0 -126
  169. package/dist/core/resolve-config-value.js.map +0 -1
  170. package/dist/core/resource-loader.d.ts +0 -185
  171. package/dist/core/resource-loader.d.ts.map +0 -1
  172. package/dist/core/resource-loader.js +0 -698
  173. package/dist/core/resource-loader.js.map +0 -1
  174. package/dist/core/sdk.d.ts +0 -93
  175. package/dist/core/sdk.d.ts.map +0 -1
  176. package/dist/core/sdk.js +0 -236
  177. package/dist/core/sdk.js.map +0 -1
  178. package/dist/core/session-manager.d.ts +0 -332
  179. package/dist/core/session-manager.d.ts.map +0 -1
  180. package/dist/core/session-manager.js +0 -1104
  181. package/dist/core/session-manager.js.map +0 -1
  182. package/dist/core/settings-manager.d.ts +0 -237
  183. package/dist/core/settings-manager.d.ts.map +0 -1
  184. package/dist/core/settings-manager.js +0 -702
  185. package/dist/core/settings-manager.js.map +0 -1
  186. package/dist/core/skills.d.ts +0 -60
  187. package/dist/core/skills.d.ts.map +0 -1
  188. package/dist/core/skills.js +0 -409
  189. package/dist/core/skills.js.map +0 -1
  190. package/dist/core/slash-commands.d.ts +0 -14
  191. package/dist/core/slash-commands.d.ts.map +0 -1
  192. package/dist/core/slash-commands.js +0 -23
  193. package/dist/core/slash-commands.js.map +0 -1
  194. package/dist/core/source-info.d.ts +0 -18
  195. package/dist/core/source-info.d.ts.map +0 -1
  196. package/dist/core/source-info.js +0 -19
  197. package/dist/core/source-info.js.map +0 -1
  198. package/dist/core/system-prompt.d.ts +0 -28
  199. package/dist/core/system-prompt.d.ts.map +0 -1
  200. package/dist/core/system-prompt.js +0 -116
  201. package/dist/core/system-prompt.js.map +0 -1
  202. package/dist/core/timings.d.ts +0 -8
  203. package/dist/core/timings.d.ts.map +0 -1
  204. package/dist/core/timings.js +0 -31
  205. package/dist/core/timings.js.map +0 -1
  206. package/dist/core/tools/bash.d.ts +0 -73
  207. package/dist/core/tools/bash.d.ts.map +0 -1
  208. package/dist/core/tools/bash.js +0 -342
  209. package/dist/core/tools/bash.js.map +0 -1
  210. package/dist/core/tools/edit-diff.d.ts +0 -85
  211. package/dist/core/tools/edit-diff.d.ts.map +0 -1
  212. package/dist/core/tools/edit-diff.js +0 -337
  213. package/dist/core/tools/edit-diff.js.map +0 -1
  214. package/dist/core/tools/edit.d.ts +0 -53
  215. package/dist/core/tools/edit.d.ts.map +0 -1
  216. package/dist/core/tools/edit.js +0 -196
  217. package/dist/core/tools/edit.js.map +0 -1
  218. package/dist/core/tools/file-mutation-queue.d.ts +0 -6
  219. package/dist/core/tools/file-mutation-queue.d.ts.map +0 -1
  220. package/dist/core/tools/file-mutation-queue.js +0 -37
  221. package/dist/core/tools/file-mutation-queue.js.map +0 -1
  222. package/dist/core/tools/find.d.ts +0 -46
  223. package/dist/core/tools/find.d.ts.map +0 -1
  224. package/dist/core/tools/find.js +0 -258
  225. package/dist/core/tools/find.js.map +0 -1
  226. package/dist/core/tools/grep.d.ts +0 -56
  227. package/dist/core/tools/grep.d.ts.map +0 -1
  228. package/dist/core/tools/grep.js +0 -293
  229. package/dist/core/tools/grep.js.map +0 -1
  230. package/dist/core/tools/index.d.ts +0 -115
  231. package/dist/core/tools/index.d.ts.map +0 -1
  232. package/dist/core/tools/index.js +0 -86
  233. package/dist/core/tools/index.js.map +0 -1
  234. package/dist/core/tools/ls.d.ts +0 -46
  235. package/dist/core/tools/ls.d.ts.map +0 -1
  236. package/dist/core/tools/ls.js +0 -172
  237. package/dist/core/tools/ls.js.map +0 -1
  238. package/dist/core/tools/path-utils.d.ts +0 -8
  239. package/dist/core/tools/path-utils.d.ts.map +0 -1
  240. package/dist/core/tools/path-utils.js +0 -81
  241. package/dist/core/tools/path-utils.js.map +0 -1
  242. package/dist/core/tools/read.d.ts +0 -46
  243. package/dist/core/tools/read.d.ts.map +0 -1
  244. package/dist/core/tools/read.js +0 -225
  245. package/dist/core/tools/read.js.map +0 -1
  246. package/dist/core/tools/render-utils.d.ts +0 -21
  247. package/dist/core/tools/render-utils.d.ts.map +0 -1
  248. package/dist/core/tools/render-utils.js +0 -49
  249. package/dist/core/tools/render-utils.js.map +0 -1
  250. package/dist/core/tools/tool-definition-wrapper.d.ts +0 -14
  251. package/dist/core/tools/tool-definition-wrapper.d.ts.map +0 -1
  252. package/dist/core/tools/tool-definition-wrapper.js +0 -32
  253. package/dist/core/tools/tool-definition-wrapper.js.map +0 -1
  254. package/dist/core/tools/truncate.d.ts +0 -70
  255. package/dist/core/tools/truncate.d.ts.map +0 -1
  256. package/dist/core/tools/truncate.js +0 -205
  257. package/dist/core/tools/truncate.js.map +0 -1
  258. package/dist/core/tools/write.d.ts +0 -35
  259. package/dist/core/tools/write.d.ts.map +0 -1
  260. package/dist/core/tools/write.js +0 -216
  261. package/dist/core/tools/write.js.map +0 -1
  262. package/dist/index.d.ts +0 -28
  263. package/dist/index.d.ts.map +0 -1
  264. package/dist/index.js +0 -43
  265. package/dist/index.js.map +0 -1
  266. package/dist/lib/config.js +0 -22
  267. package/dist/lib/detect.js +0 -94
  268. package/dist/lib/display.js +0 -182
  269. package/dist/main.d.ts +0 -8
  270. package/dist/main.d.ts.map +0 -1
  271. package/dist/main.js +0 -806
  272. package/dist/main.js.map +0 -1
  273. package/dist/migrations.d.ts +0 -33
  274. package/dist/migrations.d.ts.map +0 -1
  275. package/dist/migrations.js +0 -261
  276. package/dist/migrations.js.map +0 -1
  277. package/dist/modes/index.d.ts +0 -9
  278. package/dist/modes/index.d.ts.map +0 -1
  279. package/dist/modes/index.js +0 -8
  280. package/dist/modes/index.js.map +0 -1
  281. package/dist/modes/interactive/components/armin.d.ts +0 -34
  282. package/dist/modes/interactive/components/armin.d.ts.map +0 -1
  283. package/dist/modes/interactive/components/armin.js +0 -333
  284. package/dist/modes/interactive/components/armin.js.map +0 -1
  285. package/dist/modes/interactive/components/assistant-message.d.ts +0 -18
  286. package/dist/modes/interactive/components/assistant-message.d.ts.map +0 -1
  287. package/dist/modes/interactive/components/assistant-message.js +0 -107
  288. package/dist/modes/interactive/components/assistant-message.js.map +0 -1
  289. package/dist/modes/interactive/components/bash-execution.d.ts +0 -34
  290. package/dist/modes/interactive/components/bash-execution.d.ts.map +0 -1
  291. package/dist/modes/interactive/components/bash-execution.js +0 -175
  292. package/dist/modes/interactive/components/bash-execution.js.map +0 -1
  293. package/dist/modes/interactive/components/bordered-loader.d.ts +0 -16
  294. package/dist/modes/interactive/components/bordered-loader.d.ts.map +0 -1
  295. package/dist/modes/interactive/components/bordered-loader.js +0 -51
  296. package/dist/modes/interactive/components/bordered-loader.js.map +0 -1
  297. package/dist/modes/interactive/components/branch-summary-message.d.ts +0 -16
  298. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +0 -1
  299. package/dist/modes/interactive/components/branch-summary-message.js +0 -44
  300. package/dist/modes/interactive/components/branch-summary-message.js.map +0 -1
  301. package/dist/modes/interactive/components/compaction-summary-message.d.ts +0 -16
  302. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +0 -1
  303. package/dist/modes/interactive/components/compaction-summary-message.js +0 -45
  304. package/dist/modes/interactive/components/compaction-summary-message.js.map +0 -1
  305. package/dist/modes/interactive/components/config-selector.d.ts +0 -71
  306. package/dist/modes/interactive/components/config-selector.d.ts.map +0 -1
  307. package/dist/modes/interactive/components/config-selector.js +0 -479
  308. package/dist/modes/interactive/components/config-selector.js.map +0 -1
  309. package/dist/modes/interactive/components/countdown-timer.d.ts +0 -14
  310. package/dist/modes/interactive/components/countdown-timer.d.ts.map +0 -1
  311. package/dist/modes/interactive/components/countdown-timer.js +0 -33
  312. package/dist/modes/interactive/components/countdown-timer.js.map +0 -1
  313. package/dist/modes/interactive/components/custom-editor.d.ts +0 -21
  314. package/dist/modes/interactive/components/custom-editor.d.ts.map +0 -1
  315. package/dist/modes/interactive/components/custom-editor.js +0 -70
  316. package/dist/modes/interactive/components/custom-editor.js.map +0 -1
  317. package/dist/modes/interactive/components/custom-message.d.ts +0 -20
  318. package/dist/modes/interactive/components/custom-message.d.ts.map +0 -1
  319. package/dist/modes/interactive/components/custom-message.js +0 -79
  320. package/dist/modes/interactive/components/custom-message.js.map +0 -1
  321. package/dist/modes/interactive/components/daxnuts.d.ts +0 -23
  322. package/dist/modes/interactive/components/daxnuts.d.ts.map +0 -1
  323. package/dist/modes/interactive/components/daxnuts.js +0 -140
  324. package/dist/modes/interactive/components/daxnuts.js.map +0 -1
  325. package/dist/modes/interactive/components/diff.d.ts +0 -12
  326. package/dist/modes/interactive/components/diff.d.ts.map +0 -1
  327. package/dist/modes/interactive/components/diff.js +0 -133
  328. package/dist/modes/interactive/components/diff.js.map +0 -1
  329. package/dist/modes/interactive/components/dynamic-border.d.ts +0 -15
  330. package/dist/modes/interactive/components/dynamic-border.d.ts.map +0 -1
  331. package/dist/modes/interactive/components/dynamic-border.js +0 -21
  332. package/dist/modes/interactive/components/dynamic-border.js.map +0 -1
  333. package/dist/modes/interactive/components/extension-editor.d.ts +0 -20
  334. package/dist/modes/interactive/components/extension-editor.d.ts.map +0 -1
  335. package/dist/modes/interactive/components/extension-editor.js +0 -111
  336. package/dist/modes/interactive/components/extension-editor.js.map +0 -1
  337. package/dist/modes/interactive/components/extension-input.d.ts +0 -23
  338. package/dist/modes/interactive/components/extension-input.d.ts.map +0 -1
  339. package/dist/modes/interactive/components/extension-input.js +0 -61
  340. package/dist/modes/interactive/components/extension-input.js.map +0 -1
  341. package/dist/modes/interactive/components/extension-selector.d.ts +0 -24
  342. package/dist/modes/interactive/components/extension-selector.d.ts.map +0 -1
  343. package/dist/modes/interactive/components/extension-selector.js +0 -78
  344. package/dist/modes/interactive/components/extension-selector.js.map +0 -1
  345. package/dist/modes/interactive/components/footer.d.ts +0 -27
  346. package/dist/modes/interactive/components/footer.d.ts.map +0 -1
  347. package/dist/modes/interactive/components/footer.js +0 -201
  348. package/dist/modes/interactive/components/footer.js.map +0 -1
  349. package/dist/modes/interactive/components/index.d.ts +0 -32
  350. package/dist/modes/interactive/components/index.d.ts.map +0 -1
  351. package/dist/modes/interactive/components/index.js +0 -33
  352. package/dist/modes/interactive/components/index.js.map +0 -1
  353. package/dist/modes/interactive/components/keybinding-hints.d.ts +0 -8
  354. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +0 -1
  355. package/dist/modes/interactive/components/keybinding-hints.js +0 -22
  356. package/dist/modes/interactive/components/keybinding-hints.js.map +0 -1
  357. package/dist/modes/interactive/components/login-dialog.d.ts +0 -42
  358. package/dist/modes/interactive/components/login-dialog.d.ts.map +0 -1
  359. package/dist/modes/interactive/components/login-dialog.js +0 -145
  360. package/dist/modes/interactive/components/login-dialog.js.map +0 -1
  361. package/dist/modes/interactive/components/model-selector.d.ts +0 -47
  362. package/dist/modes/interactive/components/model-selector.d.ts.map +0 -1
  363. package/dist/modes/interactive/components/model-selector.js +0 -275
  364. package/dist/modes/interactive/components/model-selector.js.map +0 -1
  365. package/dist/modes/interactive/components/oauth-selector.d.ts +0 -19
  366. package/dist/modes/interactive/components/oauth-selector.d.ts.map +0 -1
  367. package/dist/modes/interactive/components/oauth-selector.js +0 -97
  368. package/dist/modes/interactive/components/oauth-selector.js.map +0 -1
  369. package/dist/modes/interactive/components/scoped-models-selector.d.ts +0 -49
  370. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +0 -1
  371. package/dist/modes/interactive/components/scoped-models-selector.js +0 -275
  372. package/dist/modes/interactive/components/scoped-models-selector.js.map +0 -1
  373. package/dist/modes/interactive/components/session-selector-search.d.ts +0 -23
  374. package/dist/modes/interactive/components/session-selector-search.d.ts.map +0 -1
  375. package/dist/modes/interactive/components/session-selector-search.js +0 -155
  376. package/dist/modes/interactive/components/session-selector-search.js.map +0 -1
  377. package/dist/modes/interactive/components/session-selector.d.ts +0 -95
  378. package/dist/modes/interactive/components/session-selector.d.ts.map +0 -1
  379. package/dist/modes/interactive/components/session-selector.js +0 -848
  380. package/dist/modes/interactive/components/session-selector.js.map +0 -1
  381. package/dist/modes/interactive/components/settings-selector.d.ts +0 -58
  382. package/dist/modes/interactive/components/settings-selector.d.ts.map +0 -1
  383. package/dist/modes/interactive/components/settings-selector.js +0 -301
  384. package/dist/modes/interactive/components/settings-selector.js.map +0 -1
  385. package/dist/modes/interactive/components/show-images-selector.d.ts +0 -10
  386. package/dist/modes/interactive/components/show-images-selector.d.ts.map +0 -1
  387. package/dist/modes/interactive/components/show-images-selector.js +0 -39
  388. package/dist/modes/interactive/components/show-images-selector.js.map +0 -1
  389. package/dist/modes/interactive/components/skill-invocation-message.d.ts +0 -17
  390. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +0 -1
  391. package/dist/modes/interactive/components/skill-invocation-message.js +0 -47
  392. package/dist/modes/interactive/components/skill-invocation-message.js.map +0 -1
  393. package/dist/modes/interactive/components/theme-selector.d.ts +0 -11
  394. package/dist/modes/interactive/components/theme-selector.d.ts.map +0 -1
  395. package/dist/modes/interactive/components/theme-selector.js +0 -50
  396. package/dist/modes/interactive/components/theme-selector.js.map +0 -1
  397. package/dist/modes/interactive/components/thinking-selector.d.ts +0 -11
  398. package/dist/modes/interactive/components/thinking-selector.d.ts.map +0 -1
  399. package/dist/modes/interactive/components/thinking-selector.js +0 -51
  400. package/dist/modes/interactive/components/thinking-selector.js.map +0 -1
  401. package/dist/modes/interactive/components/tool-execution.d.ts +0 -58
  402. package/dist/modes/interactive/components/tool-execution.d.ts.map +0 -1
  403. package/dist/modes/interactive/components/tool-execution.js +0 -274
  404. package/dist/modes/interactive/components/tool-execution.js.map +0 -1
  405. package/dist/modes/interactive/components/tree-selector.d.ts +0 -89
  406. package/dist/modes/interactive/components/tree-selector.d.ts.map +0 -1
  407. package/dist/modes/interactive/components/tree-selector.js +0 -1084
  408. package/dist/modes/interactive/components/tree-selector.js.map +0 -1
  409. package/dist/modes/interactive/components/user-message-selector.d.ts +0 -30
  410. package/dist/modes/interactive/components/user-message-selector.d.ts.map +0 -1
  411. package/dist/modes/interactive/components/user-message-selector.js +0 -113
  412. package/dist/modes/interactive/components/user-message-selector.js.map +0 -1
  413. package/dist/modes/interactive/components/user-message.d.ts +0 -9
  414. package/dist/modes/interactive/components/user-message.d.ts.map +0 -1
  415. package/dist/modes/interactive/components/user-message.js +0 -28
  416. package/dist/modes/interactive/components/user-message.js.map +0 -1
  417. package/dist/modes/interactive/components/visual-truncate.d.ts +0 -24
  418. package/dist/modes/interactive/components/visual-truncate.d.ts.map +0 -1
  419. package/dist/modes/interactive/components/visual-truncate.js +0 -33
  420. package/dist/modes/interactive/components/visual-truncate.js.map +0 -1
  421. package/dist/modes/interactive/interactive-mode.d.ts +0 -318
  422. package/dist/modes/interactive/interactive-mode.d.ts.map +0 -1
  423. package/dist/modes/interactive/interactive-mode.js +0 -3907
  424. package/dist/modes/interactive/interactive-mode.js.map +0 -1
  425. package/dist/modes/interactive/theme/dark.json +0 -85
  426. package/dist/modes/interactive/theme/light.json +0 -84
  427. package/dist/modes/interactive/theme/theme-schema.json +0 -335
  428. package/dist/modes/interactive/theme/theme.d.ts +0 -81
  429. package/dist/modes/interactive/theme/theme.d.ts.map +0 -1
  430. package/dist/modes/interactive/theme/theme.js +0 -970
  431. package/dist/modes/interactive/theme/theme.js.map +0 -1
  432. package/dist/modes/print-mode.d.ts +0 -28
  433. package/dist/modes/print-mode.d.ts.map +0 -1
  434. package/dist/modes/print-mode.js +0 -108
  435. package/dist/modes/print-mode.js.map +0 -1
  436. package/dist/modes/rpc/jsonl.d.ts +0 -17
  437. package/dist/modes/rpc/jsonl.d.ts.map +0 -1
  438. package/dist/modes/rpc/jsonl.js +0 -49
  439. package/dist/modes/rpc/jsonl.js.map +0 -1
  440. package/dist/modes/rpc/rpc-client.d.ts +0 -217
  441. package/dist/modes/rpc/rpc-client.d.ts.map +0 -1
  442. package/dist/modes/rpc/rpc-client.js +0 -401
  443. package/dist/modes/rpc/rpc-client.js.map +0 -1
  444. package/dist/modes/rpc/rpc-mode.d.ts +0 -20
  445. package/dist/modes/rpc/rpc-mode.d.ts.map +0 -1
  446. package/dist/modes/rpc/rpc-mode.js +0 -542
  447. package/dist/modes/rpc/rpc-mode.js.map +0 -1
  448. package/dist/modes/rpc/rpc-types.d.ts +0 -408
  449. package/dist/modes/rpc/rpc-types.d.ts.map +0 -1
  450. package/dist/modes/rpc/rpc-types.js +0 -8
  451. package/dist/modes/rpc/rpc-types.js.map +0 -1
  452. package/dist/utils/changelog.d.ts +0 -21
  453. package/dist/utils/changelog.d.ts.map +0 -1
  454. package/dist/utils/changelog.js +0 -87
  455. package/dist/utils/changelog.js.map +0 -1
  456. package/dist/utils/child-process.d.ts +0 -11
  457. package/dist/utils/child-process.d.ts.map +0 -1
  458. package/dist/utils/child-process.js +0 -78
  459. package/dist/utils/child-process.js.map +0 -1
  460. package/dist/utils/clipboard-image.d.ts +0 -11
  461. package/dist/utils/clipboard-image.d.ts.map +0 -1
  462. package/dist/utils/clipboard-image.js +0 -245
  463. package/dist/utils/clipboard-image.js.map +0 -1
  464. package/dist/utils/clipboard-native.d.ts +0 -8
  465. package/dist/utils/clipboard-native.d.ts.map +0 -1
  466. package/dist/utils/clipboard-native.js +0 -14
  467. package/dist/utils/clipboard-native.js.map +0 -1
  468. package/dist/utils/clipboard.d.ts +0 -2
  469. package/dist/utils/clipboard.d.ts.map +0 -1
  470. package/dist/utils/clipboard.js +0 -78
  471. package/dist/utils/clipboard.js.map +0 -1
  472. package/dist/utils/exif-orientation.d.ts +0 -5
  473. package/dist/utils/exif-orientation.d.ts.map +0 -1
  474. package/dist/utils/exif-orientation.js +0 -158
  475. package/dist/utils/exif-orientation.js.map +0 -1
  476. package/dist/utils/frontmatter.d.ts +0 -8
  477. package/dist/utils/frontmatter.d.ts.map +0 -1
  478. package/dist/utils/frontmatter.js +0 -26
  479. package/dist/utils/frontmatter.js.map +0 -1
  480. package/dist/utils/git.d.ts +0 -26
  481. package/dist/utils/git.d.ts.map +0 -1
  482. package/dist/utils/git.js +0 -163
  483. package/dist/utils/git.js.map +0 -1
  484. package/dist/utils/image-convert.d.ts +0 -9
  485. package/dist/utils/image-convert.d.ts.map +0 -1
  486. package/dist/utils/image-convert.js +0 -39
  487. package/dist/utils/image-convert.js.map +0 -1
  488. package/dist/utils/image-resize.d.ts +0 -36
  489. package/dist/utils/image-resize.d.ts.map +0 -1
  490. package/dist/utils/image-resize.js +0 -137
  491. package/dist/utils/image-resize.js.map +0 -1
  492. package/dist/utils/mime.d.ts +0 -2
  493. package/dist/utils/mime.d.ts.map +0 -1
  494. package/dist/utils/mime.js +0 -26
  495. package/dist/utils/mime.js.map +0 -1
  496. package/dist/utils/photon.d.ts +0 -21
  497. package/dist/utils/photon.d.ts.map +0 -1
  498. package/dist/utils/photon.js +0 -121
  499. package/dist/utils/photon.js.map +0 -1
  500. package/dist/utils/shell.d.ts +0 -26
  501. package/dist/utils/shell.d.ts.map +0 -1
  502. package/dist/utils/shell.js +0 -186
  503. package/dist/utils/shell.js.map +0 -1
  504. package/dist/utils/sleep.d.ts +0 -5
  505. package/dist/utils/sleep.d.ts.map +0 -1
  506. package/dist/utils/sleep.js +0 -17
  507. package/dist/utils/sleep.js.map +0 -1
  508. package/dist/utils/tools-manager.d.ts +0 -3
  509. package/dist/utils/tools-manager.d.ts.map +0 -1
  510. package/dist/utils/tools-manager.js +0 -252
  511. package/dist/utils/tools-manager.js.map +0 -1
  512. package/dist/welcome/about.js +0 -50
  513. package/dist/welcome/auth.js +0 -126
  514. package/dist/welcome/intro.js +0 -90
  515. package/dist/welcome/qa.js +0 -131
  516. package/scripts/install-gum.sh +0 -141
@@ -1,95 +0,0 @@
1
- import { type Component, Container, type Focusable } from "@mariozechner/pi-tui";
2
- import { KeybindingsManager } from "../../../core/keybindings.js";
3
- import type { SessionInfo, SessionListProgress } from "../../../core/session-manager.js";
4
- import { type NameFilter, type SortMode } from "./session-selector-search.js";
5
- /**
6
- * Custom session list component with multi-line items and search
7
- */
8
- declare class SessionList implements Component, Focusable {
9
- getSelectedSessionPath(): string | undefined;
10
- private allSessions;
11
- private filteredSessions;
12
- private selectedIndex;
13
- private searchInput;
14
- private showCwd;
15
- private sortMode;
16
- private nameFilter;
17
- private keybindings;
18
- private showPath;
19
- private confirmingDeletePath;
20
- private currentSessionFilePath?;
21
- onSelect?: (sessionPath: string) => void;
22
- onCancel?: () => void;
23
- onExit: () => void;
24
- onToggleScope?: () => void;
25
- onToggleSort?: () => void;
26
- onToggleNameFilter?: () => void;
27
- onTogglePath?: (showPath: boolean) => void;
28
- onDeleteConfirmationChange?: (path: string | null) => void;
29
- onDeleteSession?: (sessionPath: string) => Promise<void>;
30
- onRenameSession?: (sessionPath: string) => void;
31
- onError?: (message: string) => void;
32
- private maxVisible;
33
- private _focused;
34
- get focused(): boolean;
35
- set focused(value: boolean);
36
- constructor(sessions: SessionInfo[], showCwd: boolean, sortMode: SortMode, nameFilter: NameFilter, keybindings: KeybindingsManager, currentSessionFilePath?: string);
37
- setSortMode(sortMode: SortMode): void;
38
- setNameFilter(nameFilter: NameFilter): void;
39
- setSessions(sessions: SessionInfo[], showCwd: boolean): void;
40
- private filterSessions;
41
- private setConfirmingDeletePath;
42
- private startDeleteConfirmationForSelectedSession;
43
- invalidate(): void;
44
- render(width: number): string[];
45
- private buildTreePrefix;
46
- handleInput(keyData: string): void;
47
- }
48
- type SessionsLoader = (onProgress?: SessionListProgress) => Promise<SessionInfo[]>;
49
- /**
50
- * Component that renders a session selector
51
- */
52
- export declare class SessionSelectorComponent extends Container implements Focusable {
53
- handleInput(data: string): void;
54
- private canRename;
55
- private sessionList;
56
- private header;
57
- private keybindings;
58
- private scope;
59
- private sortMode;
60
- private nameFilter;
61
- private currentSessions;
62
- private allSessions;
63
- private currentSessionsLoader;
64
- private allSessionsLoader;
65
- private onCancel;
66
- private requestRender;
67
- private renameSession?;
68
- private currentLoading;
69
- private allLoading;
70
- private allLoadSeq;
71
- private mode;
72
- private renameInput;
73
- private renameTargetPath;
74
- private _focused;
75
- get focused(): boolean;
76
- set focused(value: boolean);
77
- private buildBaseLayout;
78
- constructor(currentSessionsLoader: SessionsLoader, allSessionsLoader: SessionsLoader, onSelect: (sessionPath: string) => void, onCancel: () => void, onExit: () => void, requestRender: () => void, options?: {
79
- renameSession?: (sessionPath: string, currentName: string | undefined) => Promise<void>;
80
- showRenameHint?: boolean;
81
- keybindings?: KeybindingsManager;
82
- }, currentSessionFilePath?: string);
83
- private loadCurrentSessions;
84
- private enterRenameMode;
85
- private exitRenameMode;
86
- private confirmRename;
87
- private loadScope;
88
- private toggleSortMode;
89
- private toggleNameFilter;
90
- private refreshSessionsAfterMutation;
91
- private toggleScope;
92
- getSessionList(): SessionList;
93
- }
94
- export {};
95
- //# sourceMappingURL=session-selector.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"session-selector.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/session-selector.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawnSync } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { unlink } from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport {\n\ttype Component,\n\tContainer,\n\ttype Focusable,\n\tgetKeybindings,\n\tInput,\n\tSpacer,\n\tText,\n\ttruncateToWidth,\n\tvisibleWidth,\n} from \"@mariozechner/pi-tui\";\nimport { KeybindingsManager } from \"../../../core/keybindings.js\";\nimport type { SessionInfo, SessionListProgress } from \"../../../core/session-manager.js\";\nimport { theme } from \"../theme/theme.js\";\nimport { DynamicBorder } from \"./dynamic-border.js\";\nimport { keyHint, keyText } from \"./keybinding-hints.js\";\nimport { filterAndSortSessions, hasSessionName, type NameFilter, type SortMode } from \"./session-selector-search.js\";\n\ntype SessionScope = \"current\" | \"all\";\n\nfunction shortenPath(path: string): string {\n\tconst home = os.homedir();\n\tif (!path) return path;\n\tif (path.startsWith(home)) {\n\t\treturn `~${path.slice(home.length)}`;\n\t}\n\treturn path;\n}\n\nfunction formatSessionDate(date: Date): string {\n\tconst now = new Date();\n\tconst diffMs = now.getTime() - date.getTime();\n\tconst diffMins = Math.floor(diffMs / 60000);\n\tconst diffHours = Math.floor(diffMs / 3600000);\n\tconst diffDays = Math.floor(diffMs / 86400000);\n\n\tif (diffMins < 1) return \"now\";\n\tif (diffMins < 60) return `${diffMins}m`;\n\tif (diffHours < 24) return `${diffHours}h`;\n\tif (diffDays < 7) return `${diffDays}d`;\n\tif (diffDays < 30) return `${Math.floor(diffDays / 7)}w`;\n\tif (diffDays < 365) return `${Math.floor(diffDays / 30)}mo`;\n\treturn `${Math.floor(diffDays / 365)}y`;\n}\n\nclass SessionSelectorHeader implements Component {\n\tprivate scope: SessionScope;\n\tprivate sortMode: SortMode;\n\tprivate nameFilter: NameFilter;\n\tprivate requestRender: () => void;\n\tprivate loading = false;\n\tprivate loadProgress: { loaded: number; total: number } | null = null;\n\tprivate showPath = false;\n\tprivate confirmingDeletePath: string | null = null;\n\tprivate statusMessage: { type: \"info\" | \"error\"; message: string } | null = null;\n\tprivate statusTimeout: ReturnType<typeof setTimeout> | null = null;\n\tprivate showRenameHint = false;\n\n\tconstructor(scope: SessionScope, sortMode: SortMode, nameFilter: NameFilter, requestRender: () => void) {\n\t\tthis.scope = scope;\n\t\tthis.sortMode = sortMode;\n\t\tthis.nameFilter = nameFilter;\n\t\tthis.requestRender = requestRender;\n\t}\n\n\tsetScope(scope: SessionScope): void {\n\t\tthis.scope = scope;\n\t}\n\n\tsetSortMode(sortMode: SortMode): void {\n\t\tthis.sortMode = sortMode;\n\t}\n\n\tsetNameFilter(nameFilter: NameFilter): void {\n\t\tthis.nameFilter = nameFilter;\n\t}\n\n\tsetLoading(loading: boolean): void {\n\t\tthis.loading = loading;\n\t\t// Progress is scoped to the current load; clear whenever the loading state is set\n\t\tthis.loadProgress = null;\n\t}\n\n\tsetProgress(loaded: number, total: number): void {\n\t\tthis.loadProgress = { loaded, total };\n\t}\n\n\tsetShowPath(showPath: boolean): void {\n\t\tthis.showPath = showPath;\n\t}\n\n\tsetShowRenameHint(show: boolean): void {\n\t\tthis.showRenameHint = show;\n\t}\n\n\tsetConfirmingDeletePath(path: string | null): void {\n\t\tthis.confirmingDeletePath = path;\n\t}\n\n\tprivate clearStatusTimeout(): void {\n\t\tif (!this.statusTimeout) return;\n\t\tclearTimeout(this.statusTimeout);\n\t\tthis.statusTimeout = null;\n\t}\n\n\tsetStatusMessage(msg: { type: \"info\" | \"error\"; message: string } | null, autoHideMs?: number): void {\n\t\tthis.clearStatusTimeout();\n\t\tthis.statusMessage = msg;\n\t\tif (!msg || !autoHideMs) return;\n\n\t\tthis.statusTimeout = setTimeout(() => {\n\t\t\tthis.statusMessage = null;\n\t\t\tthis.statusTimeout = null;\n\t\t\tthis.requestRender();\n\t\t}, autoHideMs);\n\t}\n\n\tinvalidate(): void {}\n\n\trender(width: number): string[] {\n\t\tconst title = this.scope === \"current\" ? \"Resume Session (Current Folder)\" : \"Resume Session (All)\";\n\t\tconst leftText = theme.bold(title);\n\n\t\tconst sortLabel = this.sortMode === \"threaded\" ? \"Threaded\" : this.sortMode === \"recent\" ? \"Recent\" : \"Fuzzy\";\n\t\tconst sortText = theme.fg(\"muted\", \"Sort: \") + theme.fg(\"accent\", sortLabel);\n\n\t\tconst nameLabel = this.nameFilter === \"all\" ? \"All\" : \"Named\";\n\t\tconst nameText = theme.fg(\"muted\", \"Name: \") + theme.fg(\"accent\", nameLabel);\n\n\t\tlet scopeText: string;\n\t\tif (this.loading) {\n\t\t\tconst progressText = this.loadProgress ? `${this.loadProgress.loaded}/${this.loadProgress.total}` : \"...\";\n\t\t\tscopeText = `${theme.fg(\"muted\", \"○ Current Folder | \")}${theme.fg(\"accent\", `Loading ${progressText}`)}`;\n\t\t} else if (this.scope === \"current\") {\n\t\t\tscopeText = `${theme.fg(\"accent\", \"◉ Current Folder\")}${theme.fg(\"muted\", \" | ○ All\")}`;\n\t\t} else {\n\t\t\tscopeText = `${theme.fg(\"muted\", \"○ Current Folder | \")}${theme.fg(\"accent\", \"◉ All\")}`;\n\t\t}\n\n\t\tconst rightText = truncateToWidth(`${scopeText} ${nameText} ${sortText}`, width, \"\");\n\t\tconst availableLeft = Math.max(0, width - visibleWidth(rightText) - 1);\n\t\tconst left = truncateToWidth(leftText, availableLeft, \"\");\n\t\tconst spacing = Math.max(0, width - visibleWidth(left) - visibleWidth(rightText));\n\n\t\t// Build hint lines - changes based on state (all branches truncate to width)\n\t\tlet hintLine1: string;\n\t\tlet hintLine2: string;\n\t\tif (this.confirmingDeletePath !== null) {\n\t\t\tconst confirmHint = `Delete session? ${keyHint(\"tui.select.confirm\", \"confirm\")} · ${keyHint(\"tui.select.cancel\", \"cancel\")}`;\n\t\t\thintLine1 = theme.fg(\"error\", truncateToWidth(confirmHint, width, \"…\"));\n\t\t\thintLine2 = \"\";\n\t\t} else if (this.statusMessage) {\n\t\t\tconst color = this.statusMessage.type === \"error\" ? \"error\" : \"accent\";\n\t\t\thintLine1 = theme.fg(color, truncateToWidth(this.statusMessage.message, width, \"…\"));\n\t\t\thintLine2 = \"\";\n\t\t} else {\n\t\t\tconst pathState = this.showPath ? \"(on)\" : \"(off)\";\n\t\t\tconst sep = theme.fg(\"muted\", \" · \");\n\t\t\tconst hint1 =\n\t\t\t\tkeyHint(\"tui.input.tab\", \"scope\") + sep + theme.fg(\"muted\", 're:<pattern> regex · \"phrase\" exact');\n\t\t\tconst hint2Parts = [\n\t\t\t\tkeyHint(\"app.session.toggleSort\", \"sort\"),\n\t\t\t\tkeyHint(\"app.session.toggleNamedFilter\", \"named\"),\n\t\t\t\tkeyHint(\"app.session.delete\", \"delete\"),\n\t\t\t\tkeyHint(\"app.session.togglePath\", `path ${pathState}`),\n\t\t\t];\n\t\t\tif (this.showRenameHint) {\n\t\t\t\thint2Parts.push(keyHint(\"app.session.rename\", \"rename\"));\n\t\t\t}\n\t\t\tconst hint2 = hint2Parts.join(sep);\n\t\t\thintLine1 = truncateToWidth(hint1, width, \"…\");\n\t\t\thintLine2 = truncateToWidth(hint2, width, \"…\");\n\t\t}\n\n\t\treturn [`${left}${\" \".repeat(spacing)}${rightText}`, hintLine1, hintLine2];\n\t}\n}\n\n/** A session tree node for hierarchical display */\ninterface SessionTreeNode {\n\tsession: SessionInfo;\n\tchildren: SessionTreeNode[];\n}\n\n/** Flattened node for display with tree structure info */\ninterface FlatSessionNode {\n\tsession: SessionInfo;\n\tdepth: number;\n\tisLast: boolean;\n\t/** For each ancestor level, whether there are more siblings after it */\n\tancestorContinues: boolean[];\n}\n\n/**\n * Build a tree structure from sessions based on parentSessionPath.\n * Returns root nodes sorted by modified date (descending).\n */\nfunction buildSessionTree(sessions: SessionInfo[]): SessionTreeNode[] {\n\tconst byPath = new Map<string, SessionTreeNode>();\n\n\tfor (const session of sessions) {\n\t\tbyPath.set(session.path, { session, children: [] });\n\t}\n\n\tconst roots: SessionTreeNode[] = [];\n\n\tfor (const session of sessions) {\n\t\tconst node = byPath.get(session.path)!;\n\t\tconst parentPath = session.parentSessionPath;\n\n\t\tif (parentPath && byPath.has(parentPath)) {\n\t\t\tbyPath.get(parentPath)!.children.push(node);\n\t\t} else {\n\t\t\troots.push(node);\n\t\t}\n\t}\n\n\t// Sort children and roots by modified date (descending)\n\tconst sortNodes = (nodes: SessionTreeNode[]): void => {\n\t\tnodes.sort((a, b) => b.session.modified.getTime() - a.session.modified.getTime());\n\t\tfor (const node of nodes) {\n\t\t\tsortNodes(node.children);\n\t\t}\n\t};\n\tsortNodes(roots);\n\n\treturn roots;\n}\n\n/**\n * Flatten tree into display list with tree structure metadata.\n */\nfunction flattenSessionTree(roots: SessionTreeNode[]): FlatSessionNode[] {\n\tconst result: FlatSessionNode[] = [];\n\n\tconst walk = (node: SessionTreeNode, depth: number, ancestorContinues: boolean[], isLast: boolean): void => {\n\t\tresult.push({ session: node.session, depth, isLast, ancestorContinues });\n\n\t\tfor (let i = 0; i < node.children.length; i++) {\n\t\t\tconst childIsLast = i === node.children.length - 1;\n\t\t\t// Only show continuation line for non-root ancestors\n\t\t\tconst continues = depth > 0 ? !isLast : false;\n\t\t\twalk(node.children[i]!, depth + 1, [...ancestorContinues, continues], childIsLast);\n\t\t}\n\t};\n\n\tfor (let i = 0; i < roots.length; i++) {\n\t\twalk(roots[i]!, 0, [], i === roots.length - 1);\n\t}\n\n\treturn result;\n}\n\n/**\n * Custom session list component with multi-line items and search\n */\nclass SessionList implements Component, Focusable {\n\tpublic getSelectedSessionPath(): string | undefined {\n\t\tconst selected = this.filteredSessions[this.selectedIndex];\n\t\treturn selected?.session.path;\n\t}\n\tprivate allSessions: SessionInfo[] = [];\n\tprivate filteredSessions: FlatSessionNode[] = [];\n\tprivate selectedIndex: number = 0;\n\tprivate searchInput: Input;\n\tprivate showCwd = false;\n\tprivate sortMode: SortMode = \"threaded\";\n\tprivate nameFilter: NameFilter = \"all\";\n\tprivate keybindings: KeybindingsManager;\n\tprivate showPath = false;\n\tprivate confirmingDeletePath: string | null = null;\n\tprivate currentSessionFilePath?: string;\n\tpublic onSelect?: (sessionPath: string) => void;\n\tpublic onCancel?: () => void;\n\tpublic onExit: () => void = () => {};\n\tpublic onToggleScope?: () => void;\n\tpublic onToggleSort?: () => void;\n\tpublic onToggleNameFilter?: () => void;\n\tpublic onTogglePath?: (showPath: boolean) => void;\n\tpublic onDeleteConfirmationChange?: (path: string | null) => void;\n\tpublic onDeleteSession?: (sessionPath: string) => Promise<void>;\n\tpublic onRenameSession?: (sessionPath: string) => void;\n\tpublic onError?: (message: string) => void;\n\tprivate maxVisible: number = 10; // Max sessions visible (one line each)\n\n\t// Focusable implementation - propagate to searchInput for IME cursor positioning\n\tprivate _focused = false;\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t\tthis.searchInput.focused = value;\n\t}\n\n\tconstructor(\n\t\tsessions: SessionInfo[],\n\t\tshowCwd: boolean,\n\t\tsortMode: SortMode,\n\t\tnameFilter: NameFilter,\n\t\tkeybindings: KeybindingsManager,\n\t\tcurrentSessionFilePath?: string,\n\t) {\n\t\tthis.allSessions = sessions;\n\t\tthis.filteredSessions = [];\n\t\tthis.searchInput = new Input();\n\t\tthis.showCwd = showCwd;\n\t\tthis.sortMode = sortMode;\n\t\tthis.nameFilter = nameFilter;\n\t\tthis.keybindings = keybindings;\n\t\tthis.currentSessionFilePath = currentSessionFilePath;\n\t\tthis.filterSessions(\"\");\n\n\t\t// Handle Enter in search input - select current item\n\t\tthis.searchInput.onSubmit = () => {\n\t\t\tif (this.filteredSessions[this.selectedIndex]) {\n\t\t\t\tconst selected = this.filteredSessions[this.selectedIndex];\n\t\t\t\tif (this.onSelect) {\n\t\t\t\t\tthis.onSelect(selected.session.path);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\n\tsetSortMode(sortMode: SortMode): void {\n\t\tthis.sortMode = sortMode;\n\t\tthis.filterSessions(this.searchInput.getValue());\n\t}\n\n\tsetNameFilter(nameFilter: NameFilter): void {\n\t\tthis.nameFilter = nameFilter;\n\t\tthis.filterSessions(this.searchInput.getValue());\n\t}\n\n\tsetSessions(sessions: SessionInfo[], showCwd: boolean): void {\n\t\tthis.allSessions = sessions;\n\t\tthis.showCwd = showCwd;\n\t\tthis.filterSessions(this.searchInput.getValue());\n\t}\n\n\tprivate filterSessions(query: string): void {\n\t\tconst trimmed = query.trim();\n\t\tconst nameFiltered =\n\t\t\tthis.nameFilter === \"all\" ? this.allSessions : this.allSessions.filter((session) => hasSessionName(session));\n\n\t\tif (this.sortMode === \"threaded\" && !trimmed) {\n\t\t\t// Threaded mode without search: show tree structure\n\t\t\tconst roots = buildSessionTree(nameFiltered);\n\t\t\tthis.filteredSessions = flattenSessionTree(roots);\n\t\t} else {\n\t\t\t// Other modes or with search: flat list\n\t\t\tconst filtered = filterAndSortSessions(nameFiltered, query, this.sortMode, \"all\");\n\t\t\tthis.filteredSessions = filtered.map((session) => ({\n\t\t\t\tsession,\n\t\t\t\tdepth: 0,\n\t\t\t\tisLast: true,\n\t\t\t\tancestorContinues: [],\n\t\t\t}));\n\t\t}\n\t\tthis.selectedIndex = Math.min(this.selectedIndex, Math.max(0, this.filteredSessions.length - 1));\n\t}\n\n\tprivate setConfirmingDeletePath(path: string | null): void {\n\t\tthis.confirmingDeletePath = path;\n\t\tthis.onDeleteConfirmationChange?.(path);\n\t}\n\n\tprivate startDeleteConfirmationForSelectedSession(): void {\n\t\tconst selected = this.filteredSessions[this.selectedIndex];\n\t\tif (!selected) return;\n\n\t\t// Prevent deleting current session\n\t\tif (this.currentSessionFilePath && selected.session.path === this.currentSessionFilePath) {\n\t\t\tthis.onError?.(\"Cannot delete the currently active session\");\n\t\t\treturn;\n\t\t}\n\n\t\tthis.setConfirmingDeletePath(selected.session.path);\n\t}\n\n\tinvalidate(): void {}\n\n\trender(width: number): string[] {\n\t\tconst lines: string[] = [];\n\n\t\t// Render search input\n\t\tlines.push(...this.searchInput.render(width));\n\t\tlines.push(\"\"); // Blank line after search\n\n\t\tif (this.filteredSessions.length === 0) {\n\t\t\tlet emptyMessage: string;\n\t\t\tif (this.nameFilter === \"named\") {\n\t\t\t\tconst toggleKey = keyText(\"app.session.toggleNamedFilter\");\n\t\t\t\tif (this.showCwd) {\n\t\t\t\t\temptyMessage = ` No named sessions found. Press ${toggleKey} to show all.`;\n\t\t\t\t} else {\n\t\t\t\t\temptyMessage = ` No named sessions in current folder. Press ${toggleKey} to show all, or Tab to view all.`;\n\t\t\t\t}\n\t\t\t} else if (this.showCwd) {\n\t\t\t\t// \"All\" scope - no sessions anywhere that match filter\n\t\t\t\temptyMessage = \" No sessions found\";\n\t\t\t} else {\n\t\t\t\t// \"Current folder\" scope - hint to try \"all\"\n\t\t\t\temptyMessage = \" No sessions in current folder. Press Tab to view all.\";\n\t\t\t}\n\t\t\tlines.push(theme.fg(\"muted\", truncateToWidth(emptyMessage, width, \"…\")));\n\t\t\treturn lines;\n\t\t}\n\n\t\t// Calculate visible range with scrolling\n\t\tconst startIndex = Math.max(\n\t\t\t0,\n\t\t\tMath.min(this.selectedIndex - Math.floor(this.maxVisible / 2), this.filteredSessions.length - this.maxVisible),\n\t\t);\n\t\tconst endIndex = Math.min(startIndex + this.maxVisible, this.filteredSessions.length);\n\n\t\t// Render visible sessions (one line each with tree structure)\n\t\tfor (let i = startIndex; i < endIndex; i++) {\n\t\t\tconst node = this.filteredSessions[i]!;\n\t\t\tconst session = node.session;\n\t\t\tconst isSelected = i === this.selectedIndex;\n\t\t\tconst isConfirmingDelete = session.path === this.confirmingDeletePath;\n\t\t\tconst isCurrent = this.currentSessionFilePath === session.path;\n\n\t\t\t// Build tree prefix\n\t\t\tconst prefix = this.buildTreePrefix(node);\n\n\t\t\t// Session display text (name or first message)\n\t\t\tconst hasName = !!session.name;\n\t\t\tconst displayText = session.name ?? session.firstMessage;\n\t\t\tconst normalizedMessage = displayText.replace(/[\\x00-\\x1f\\x7f]/g, \" \").trim();\n\n\t\t\t// Right side: message count and age\n\t\t\tconst age = formatSessionDate(session.modified);\n\t\t\tconst msgCount = String(session.messageCount);\n\t\t\tlet rightPart = `${msgCount} ${age}`;\n\t\t\tif (this.showCwd && session.cwd) {\n\t\t\t\trightPart = `${shortenPath(session.cwd)} ${rightPart}`;\n\t\t\t}\n\t\t\tif (this.showPath) {\n\t\t\t\trightPart = `${shortenPath(session.path)} ${rightPart}`;\n\t\t\t}\n\n\t\t\t// Cursor\n\t\t\tconst cursor = isSelected ? theme.fg(\"accent\", \"› \") : \" \";\n\n\t\t\t// Calculate available width for message\n\t\t\tconst prefixWidth = visibleWidth(prefix);\n\t\t\tconst rightWidth = visibleWidth(rightPart) + 2; // +2 for spacing\n\t\t\tconst availableForMsg = width - 2 - prefixWidth - rightWidth; // -2 for cursor\n\n\t\t\tconst truncatedMsg = truncateToWidth(normalizedMessage, Math.max(10, availableForMsg), \"…\");\n\n\t\t\t// Style message\n\t\t\tlet messageColor: \"error\" | \"warning\" | \"accent\" | null = null;\n\t\t\tif (isConfirmingDelete) {\n\t\t\t\tmessageColor = \"error\";\n\t\t\t} else if (isCurrent) {\n\t\t\t\tmessageColor = \"accent\";\n\t\t\t} else if (hasName) {\n\t\t\t\tmessageColor = \"warning\";\n\t\t\t}\n\t\t\tlet styledMsg = messageColor ? theme.fg(messageColor, truncatedMsg) : truncatedMsg;\n\t\t\tif (isSelected) {\n\t\t\t\tstyledMsg = theme.bold(styledMsg);\n\t\t\t}\n\n\t\t\t// Build line\n\t\t\tconst leftPart = cursor + theme.fg(\"dim\", prefix) + styledMsg;\n\t\t\tconst leftWidth = visibleWidth(leftPart);\n\t\t\tconst spacing = Math.max(1, width - leftWidth - visibleWidth(rightPart));\n\t\t\tconst styledRight = theme.fg(isConfirmingDelete ? \"error\" : \"dim\", rightPart);\n\n\t\t\tlet line = leftPart + \" \".repeat(spacing) + styledRight;\n\t\t\tif (isSelected) {\n\t\t\t\tline = theme.bg(\"selectedBg\", line);\n\t\t\t}\n\t\t\tlines.push(truncateToWidth(line, width));\n\t\t}\n\n\t\t// Add scroll indicator if needed\n\t\tif (startIndex > 0 || endIndex < this.filteredSessions.length) {\n\t\t\tconst scrollText = ` (${this.selectedIndex + 1}/${this.filteredSessions.length})`;\n\t\t\tconst scrollInfo = theme.fg(\"muted\", truncateToWidth(scrollText, width, \"\"));\n\t\t\tlines.push(scrollInfo);\n\t\t}\n\n\t\treturn lines;\n\t}\n\n\tprivate buildTreePrefix(node: FlatSessionNode): string {\n\t\tif (node.depth === 0) {\n\t\t\treturn \"\";\n\t\t}\n\n\t\tconst parts = node.ancestorContinues.map((continues) => (continues ? \"│ \" : \" \"));\n\t\tconst branch = node.isLast ? \"└─ \" : \"├─ \";\n\t\treturn parts.join(\"\") + branch;\n\t}\n\n\thandleInput(keyData: string): void {\n\t\tconst kb = getKeybindings();\n\n\t\t// Handle delete confirmation state first - intercept all keys\n\t\tif (this.confirmingDeletePath !== null) {\n\t\t\tif (kb.matches(keyData, \"tui.select.confirm\")) {\n\t\t\t\tconst pathToDelete = this.confirmingDeletePath;\n\t\t\t\tthis.setConfirmingDeletePath(null);\n\t\t\t\tvoid this.onDeleteSession?.(pathToDelete);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (kb.matches(keyData, \"tui.select.cancel\")) {\n\t\t\t\tthis.setConfirmingDeletePath(null);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Ignore all other keys while confirming\n\t\t\treturn;\n\t\t}\n\n\t\tif (kb.matches(keyData, \"tui.input.tab\")) {\n\t\t\tif (this.onToggleScope) {\n\t\t\t\tthis.onToggleScope();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (kb.matches(keyData, \"app.session.toggleSort\")) {\n\t\t\tthis.onToggleSort?.();\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.keybindings.matches(keyData, \"app.session.toggleNamedFilter\")) {\n\t\t\tthis.onToggleNameFilter?.();\n\t\t\treturn;\n\t\t}\n\n\t\t// Ctrl+P: toggle path display\n\t\tif (kb.matches(keyData, \"app.session.togglePath\")) {\n\t\t\tthis.showPath = !this.showPath;\n\t\t\tthis.onTogglePath?.(this.showPath);\n\t\t\treturn;\n\t\t}\n\n\t\t// Ctrl+D: initiate delete confirmation (useful on terminals that don't distinguish Ctrl+Backspace from Backspace)\n\t\tif (kb.matches(keyData, \"app.session.delete\")) {\n\t\t\tthis.startDeleteConfirmationForSelectedSession();\n\t\t\treturn;\n\t\t}\n\n\t\t// Rename selected session\n\t\tif (kb.matches(keyData, \"app.session.rename\")) {\n\t\t\tconst selected = this.filteredSessions[this.selectedIndex];\n\t\t\tif (selected) {\n\t\t\t\tthis.onRenameSession?.(selected.session.path);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Ctrl+Backspace: non-invasive convenience alias for delete\n\t\t// Only triggers deletion when the query is empty; otherwise it is forwarded to the input\n\t\tif (kb.matches(keyData, \"app.session.deleteNoninvasive\")) {\n\t\t\tif (this.searchInput.getValue().length > 0) {\n\t\t\t\tthis.searchInput.handleInput(keyData);\n\t\t\t\tthis.filterSessions(this.searchInput.getValue());\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.startDeleteConfirmationForSelectedSession();\n\t\t\treturn;\n\t\t}\n\n\t\t// Up arrow\n\t\tif (kb.matches(keyData, \"tui.select.up\")) {\n\t\t\tthis.selectedIndex = Math.max(0, this.selectedIndex - 1);\n\t\t}\n\t\t// Down arrow\n\t\telse if (kb.matches(keyData, \"tui.select.down\")) {\n\t\t\tthis.selectedIndex = Math.min(this.filteredSessions.length - 1, this.selectedIndex + 1);\n\t\t}\n\t\t// Page up - jump up by maxVisible items\n\t\telse if (kb.matches(keyData, \"tui.select.pageUp\")) {\n\t\t\tthis.selectedIndex = Math.max(0, this.selectedIndex - this.maxVisible);\n\t\t}\n\t\t// Page down - jump down by maxVisible items\n\t\telse if (kb.matches(keyData, \"tui.select.pageDown\")) {\n\t\t\tthis.selectedIndex = Math.min(this.filteredSessions.length - 1, this.selectedIndex + this.maxVisible);\n\t\t}\n\t\t// Enter\n\t\telse if (kb.matches(keyData, \"tui.select.confirm\")) {\n\t\t\tconst selected = this.filteredSessions[this.selectedIndex];\n\t\t\tif (selected && this.onSelect) {\n\t\t\t\tthis.onSelect(selected.session.path);\n\t\t\t}\n\t\t}\n\t\t// Escape - cancel\n\t\telse if (kb.matches(keyData, \"tui.select.cancel\")) {\n\t\t\tif (this.onCancel) {\n\t\t\t\tthis.onCancel();\n\t\t\t}\n\t\t}\n\t\t// Pass everything else to search input\n\t\telse {\n\t\t\tthis.searchInput.handleInput(keyData);\n\t\t\tthis.filterSessions(this.searchInput.getValue());\n\t\t}\n\t}\n}\n\ntype SessionsLoader = (onProgress?: SessionListProgress) => Promise<SessionInfo[]>;\n\n/**\n * Delete a session file, trying the `trash` CLI first, then falling back to unlink\n */\nasync function deleteSessionFile(\n\tsessionPath: string,\n): Promise<{ ok: boolean; method: \"trash\" | \"unlink\"; error?: string }> {\n\t// Try `trash` first (if installed)\n\tconst trashArgs = sessionPath.startsWith(\"-\") ? [\"--\", sessionPath] : [sessionPath];\n\tconst trashResult = spawnSync(\"trash\", trashArgs, { encoding: \"utf-8\" });\n\n\tconst getTrashErrorHint = (): string | null => {\n\t\tconst parts: string[] = [];\n\t\tif (trashResult.error) {\n\t\t\tparts.push(trashResult.error.message);\n\t\t}\n\t\tconst stderr = trashResult.stderr?.trim();\n\t\tif (stderr) {\n\t\t\tparts.push(stderr.split(\"\\n\")[0] ?? stderr);\n\t\t}\n\t\tif (parts.length === 0) return null;\n\t\treturn `trash: ${parts.join(\" · \").slice(0, 200)}`;\n\t};\n\n\t// If trash reports success, or the file is gone afterwards, treat it as successful\n\tif (trashResult.status === 0 || !existsSync(sessionPath)) {\n\t\treturn { ok: true, method: \"trash\" };\n\t}\n\n\t// Fallback to permanent deletion\n\ttry {\n\t\tawait unlink(sessionPath);\n\t\treturn { ok: true, method: \"unlink\" };\n\t} catch (err) {\n\t\tconst unlinkError = err instanceof Error ? err.message : String(err);\n\t\tconst trashErrorHint = getTrashErrorHint();\n\t\tconst error = trashErrorHint ? `${unlinkError} (${trashErrorHint})` : unlinkError;\n\t\treturn { ok: false, method: \"unlink\", error };\n\t}\n}\n\n/**\n * Component that renders a session selector\n */\nexport class SessionSelectorComponent extends Container implements Focusable {\n\thandleInput(data: string): void {\n\t\tif (this.mode === \"rename\") {\n\t\t\tconst kb = getKeybindings();\n\t\t\tif (kb.matches(data, \"tui.select.cancel\")) {\n\t\t\t\tthis.exitRenameMode();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.renameInput.handleInput(data);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.sessionList.handleInput(data);\n\t}\n\n\tprivate canRename = true;\n\tprivate sessionList: SessionList;\n\tprivate header: SessionSelectorHeader;\n\tprivate keybindings: KeybindingsManager;\n\tprivate scope: SessionScope = \"current\";\n\tprivate sortMode: SortMode = \"threaded\";\n\tprivate nameFilter: NameFilter = \"all\";\n\tprivate currentSessions: SessionInfo[] | null = null;\n\tprivate allSessions: SessionInfo[] | null = null;\n\tprivate currentSessionsLoader: SessionsLoader;\n\tprivate allSessionsLoader: SessionsLoader;\n\tprivate onCancel: () => void;\n\tprivate requestRender: () => void;\n\tprivate renameSession?: (sessionPath: string, currentName: string | undefined) => Promise<void>;\n\tprivate currentLoading = false;\n\tprivate allLoading = false;\n\tprivate allLoadSeq = 0;\n\n\tprivate mode: \"list\" | \"rename\" = \"list\";\n\tprivate renameInput = new Input();\n\tprivate renameTargetPath: string | null = null;\n\n\t// Focusable implementation - propagate to sessionList for IME cursor positioning\n\tprivate _focused = false;\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t\tthis.sessionList.focused = value;\n\t\tthis.renameInput.focused = value;\n\t\tif (value && this.mode === \"rename\") {\n\t\t\tthis.renameInput.focused = true;\n\t\t}\n\t}\n\n\tprivate buildBaseLayout(content: Component, options?: { showHeader?: boolean }): void {\n\t\tthis.clear();\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new DynamicBorder((s) => theme.fg(\"accent\", s)));\n\t\tthis.addChild(new Spacer(1));\n\t\tif (options?.showHeader ?? true) {\n\t\t\tthis.addChild(this.header);\n\t\t\tthis.addChild(new Spacer(1));\n\t\t}\n\t\tthis.addChild(content);\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new DynamicBorder((s) => theme.fg(\"accent\", s)));\n\t}\n\n\tconstructor(\n\t\tcurrentSessionsLoader: SessionsLoader,\n\t\tallSessionsLoader: SessionsLoader,\n\t\tonSelect: (sessionPath: string) => void,\n\t\tonCancel: () => void,\n\t\tonExit: () => void,\n\t\trequestRender: () => void,\n\t\toptions?: {\n\t\t\trenameSession?: (sessionPath: string, currentName: string | undefined) => Promise<void>;\n\t\t\tshowRenameHint?: boolean;\n\t\t\tkeybindings?: KeybindingsManager;\n\t\t},\n\t\tcurrentSessionFilePath?: string,\n\t) {\n\t\tsuper();\n\t\tthis.keybindings = options?.keybindings ?? KeybindingsManager.create();\n\t\tthis.currentSessionsLoader = currentSessionsLoader;\n\t\tthis.allSessionsLoader = allSessionsLoader;\n\t\tthis.onCancel = onCancel;\n\t\tthis.requestRender = requestRender;\n\t\tthis.header = new SessionSelectorHeader(this.scope, this.sortMode, this.nameFilter, this.requestRender);\n\t\tconst renameSession = options?.renameSession;\n\t\tthis.renameSession = renameSession;\n\t\tthis.canRename = !!renameSession;\n\t\tthis.header.setShowRenameHint(options?.showRenameHint ?? this.canRename);\n\n\t\t// Create session list (starts empty, will be populated after load)\n\t\tthis.sessionList = new SessionList(\n\t\t\t[],\n\t\t\tfalse,\n\t\t\tthis.sortMode,\n\t\t\tthis.nameFilter,\n\t\t\tthis.keybindings,\n\t\t\tcurrentSessionFilePath,\n\t\t);\n\n\t\tthis.buildBaseLayout(this.sessionList);\n\n\t\tthis.renameInput.onSubmit = (value) => {\n\t\t\tvoid this.confirmRename(value);\n\t\t};\n\n\t\t// Ensure header status timeouts are cleared when leaving the selector\n\t\tconst clearStatusMessage = () => this.header.setStatusMessage(null);\n\t\tthis.sessionList.onSelect = (sessionPath) => {\n\t\t\tclearStatusMessage();\n\t\t\tonSelect(sessionPath);\n\t\t};\n\t\tthis.sessionList.onCancel = () => {\n\t\t\tclearStatusMessage();\n\t\t\tonCancel();\n\t\t};\n\t\tthis.sessionList.onExit = () => {\n\t\t\tclearStatusMessage();\n\t\t\tonExit();\n\t\t};\n\t\tthis.sessionList.onToggleScope = () => this.toggleScope();\n\t\tthis.sessionList.onToggleSort = () => this.toggleSortMode();\n\t\tthis.sessionList.onToggleNameFilter = () => this.toggleNameFilter();\n\t\tthis.sessionList.onRenameSession = (sessionPath) => {\n\t\t\tif (!renameSession) return;\n\t\t\tif (this.scope === \"current\" && this.currentLoading) return;\n\t\t\tif (this.scope === \"all\" && this.allLoading) return;\n\n\t\t\tconst sessions = this.scope === \"all\" ? (this.allSessions ?? []) : (this.currentSessions ?? []);\n\t\t\tconst session = sessions.find((s) => s.path === sessionPath);\n\t\t\tthis.enterRenameMode(sessionPath, session?.name);\n\t\t};\n\n\t\t// Sync list events to header\n\t\tthis.sessionList.onTogglePath = (showPath) => {\n\t\t\tthis.header.setShowPath(showPath);\n\t\t\tthis.requestRender();\n\t\t};\n\t\tthis.sessionList.onDeleteConfirmationChange = (path) => {\n\t\t\tthis.header.setConfirmingDeletePath(path);\n\t\t\tthis.requestRender();\n\t\t};\n\t\tthis.sessionList.onError = (msg) => {\n\t\t\tthis.header.setStatusMessage({ type: \"error\", message: msg }, 3000);\n\t\t\tthis.requestRender();\n\t\t};\n\n\t\t// Handle session deletion\n\t\tthis.sessionList.onDeleteSession = async (sessionPath: string) => {\n\t\t\tconst result = await deleteSessionFile(sessionPath);\n\n\t\t\tif (result.ok) {\n\t\t\t\tif (this.currentSessions) {\n\t\t\t\t\tthis.currentSessions = this.currentSessions.filter((s) => s.path !== sessionPath);\n\t\t\t\t}\n\t\t\t\tif (this.allSessions) {\n\t\t\t\t\tthis.allSessions = this.allSessions.filter((s) => s.path !== sessionPath);\n\t\t\t\t}\n\n\t\t\t\tconst sessions = this.scope === \"all\" ? (this.allSessions ?? []) : (this.currentSessions ?? []);\n\t\t\t\tconst showCwd = this.scope === \"all\";\n\t\t\t\tthis.sessionList.setSessions(sessions, showCwd);\n\n\t\t\t\tconst msg = result.method === \"trash\" ? \"Session moved to trash\" : \"Session deleted\";\n\t\t\t\tthis.header.setStatusMessage({ type: \"info\", message: msg }, 2000);\n\t\t\t\tawait this.refreshSessionsAfterMutation();\n\t\t\t} else {\n\t\t\t\tconst errorMessage = result.error ?? \"Unknown error\";\n\t\t\t\tthis.header.setStatusMessage({ type: \"error\", message: `Failed to delete: ${errorMessage}` }, 3000);\n\t\t\t}\n\n\t\t\tthis.requestRender();\n\t\t};\n\n\t\t// Start loading current sessions immediately\n\t\tthis.loadCurrentSessions();\n\t}\n\n\tprivate loadCurrentSessions(): void {\n\t\tvoid this.loadScope(\"current\", \"initial\");\n\t}\n\n\tprivate enterRenameMode(sessionPath: string, currentName: string | undefined): void {\n\t\tthis.mode = \"rename\";\n\t\tthis.renameTargetPath = sessionPath;\n\t\tthis.renameInput.setValue(currentName ?? \"\");\n\t\tthis.renameInput.focused = true;\n\n\t\tconst panel = new Container();\n\t\tpanel.addChild(new Text(theme.bold(\"Rename Session\"), 1, 0));\n\t\tpanel.addChild(new Spacer(1));\n\t\tpanel.addChild(this.renameInput);\n\t\tpanel.addChild(new Spacer(1));\n\t\tpanel.addChild(\n\t\t\tnew Text(\n\t\t\t\ttheme.fg(\"muted\", `${keyText(\"tui.select.confirm\")} to save · ${keyText(\"tui.select.cancel\")} to cancel`),\n\t\t\t\t1,\n\t\t\t\t0,\n\t\t\t),\n\t\t);\n\n\t\tthis.buildBaseLayout(panel, { showHeader: false });\n\t\tthis.requestRender();\n\t}\n\n\tprivate exitRenameMode(): void {\n\t\tthis.mode = \"list\";\n\t\tthis.renameTargetPath = null;\n\n\t\tthis.buildBaseLayout(this.sessionList);\n\n\t\tthis.requestRender();\n\t}\n\n\tprivate async confirmRename(value: string): Promise<void> {\n\t\tconst next = value.trim();\n\t\tif (!next) return;\n\t\tconst target = this.renameTargetPath;\n\t\tif (!target) {\n\t\t\tthis.exitRenameMode();\n\t\t\treturn;\n\t\t}\n\n\t\t// Find current name for callback\n\t\tconst renameSession = this.renameSession;\n\t\tif (!renameSession) {\n\t\t\tthis.exitRenameMode();\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tawait renameSession(target, next);\n\t\t\tawait this.refreshSessionsAfterMutation();\n\t\t} finally {\n\t\t\tthis.exitRenameMode();\n\t\t}\n\t}\n\n\tprivate async loadScope(scope: SessionScope, reason: \"initial\" | \"refresh\" | \"toggle\"): Promise<void> {\n\t\tconst showCwd = scope === \"all\";\n\n\t\t// Mark loading\n\t\tif (scope === \"current\") {\n\t\t\tthis.currentLoading = true;\n\t\t} else {\n\t\t\tthis.allLoading = true;\n\t\t}\n\n\t\tconst seq = scope === \"all\" ? ++this.allLoadSeq : undefined;\n\t\tthis.header.setScope(scope);\n\t\tthis.header.setLoading(true);\n\t\tthis.requestRender();\n\n\t\tconst onProgress = (loaded: number, total: number) => {\n\t\t\tif (scope !== this.scope) return;\n\t\t\tif (seq !== undefined && seq !== this.allLoadSeq) return;\n\t\t\tthis.header.setProgress(loaded, total);\n\t\t\tthis.requestRender();\n\t\t};\n\n\t\ttry {\n\t\t\tconst sessions = await (scope === \"current\"\n\t\t\t\t? this.currentSessionsLoader(onProgress)\n\t\t\t\t: this.allSessionsLoader(onProgress));\n\n\t\t\tif (scope === \"current\") {\n\t\t\t\tthis.currentSessions = sessions;\n\t\t\t\tthis.currentLoading = false;\n\t\t\t} else {\n\t\t\t\tthis.allSessions = sessions;\n\t\t\t\tthis.allLoading = false;\n\t\t\t}\n\n\t\t\tif (scope !== this.scope) return;\n\t\t\tif (seq !== undefined && seq !== this.allLoadSeq) return;\n\n\t\t\tthis.header.setLoading(false);\n\t\t\tthis.sessionList.setSessions(sessions, showCwd);\n\t\t\tthis.requestRender();\n\n\t\t\tif (scope === \"all\" && sessions.length === 0 && (this.currentSessions?.length ?? 0) === 0) {\n\t\t\t\tthis.onCancel();\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tif (scope === \"current\") {\n\t\t\t\tthis.currentLoading = false;\n\t\t\t} else {\n\t\t\t\tthis.allLoading = false;\n\t\t\t}\n\n\t\t\tif (scope !== this.scope) return;\n\t\t\tif (seq !== undefined && seq !== this.allLoadSeq) return;\n\n\t\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\t\tthis.header.setLoading(false);\n\t\t\tthis.header.setStatusMessage({ type: \"error\", message: `Failed to load sessions: ${message}` }, 4000);\n\n\t\t\tif (reason === \"initial\") {\n\t\t\t\tthis.sessionList.setSessions([], showCwd);\n\t\t\t}\n\t\t\tthis.requestRender();\n\t\t}\n\t}\n\n\tprivate toggleSortMode(): void {\n\t\t// Cycle: threaded -> recent -> relevance -> threaded\n\t\tthis.sortMode = this.sortMode === \"threaded\" ? \"recent\" : this.sortMode === \"recent\" ? \"relevance\" : \"threaded\";\n\t\tthis.header.setSortMode(this.sortMode);\n\t\tthis.sessionList.setSortMode(this.sortMode);\n\t\tthis.requestRender();\n\t}\n\n\tprivate toggleNameFilter(): void {\n\t\tthis.nameFilter = this.nameFilter === \"all\" ? \"named\" : \"all\";\n\t\tthis.header.setNameFilter(this.nameFilter);\n\t\tthis.sessionList.setNameFilter(this.nameFilter);\n\t\tthis.requestRender();\n\t}\n\n\tprivate async refreshSessionsAfterMutation(): Promise<void> {\n\t\tawait this.loadScope(this.scope, \"refresh\");\n\t}\n\n\tprivate toggleScope(): void {\n\t\tif (this.scope === \"current\") {\n\t\t\tthis.scope = \"all\";\n\t\t\tthis.header.setScope(this.scope);\n\n\t\t\tif (this.allSessions !== null) {\n\t\t\t\tthis.header.setLoading(false);\n\t\t\t\tthis.sessionList.setSessions(this.allSessions, true);\n\t\t\t\tthis.requestRender();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (!this.allLoading) {\n\t\t\t\tvoid this.loadScope(\"all\", \"toggle\");\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tthis.scope = \"current\";\n\t\tthis.header.setScope(this.scope);\n\t\tthis.header.setLoading(this.currentLoading);\n\t\tthis.sessionList.setSessions(this.currentSessions ?? [], false);\n\t\tthis.requestRender();\n\t}\n\n\tgetSessionList(): SessionList {\n\t\treturn this.sessionList;\n\t}\n}\n"]}