@phi-code-admin/phi-code 0.74.2 → 0.75.0

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 (656) hide show
  1. package/CHANGELOG.md +1186 -4
  2. package/README.md +478 -379
  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 +9 -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 +13 -0
  12. package/dist/bun/restore-sandbox-env.d.ts.map +1 -0
  13. package/dist/bun/restore-sandbox-env.js +32 -0
  14. package/dist/bun/restore-sandbox-env.js.map +1 -0
  15. package/dist/cli/args.d.ts +12 -7
  16. package/dist/cli/args.d.ts.map +1 -1
  17. package/dist/cli/args.js +87 -45
  18. package/dist/cli/args.js.map +1 -1
  19. package/dist/cli/config-selector.d.ts.map +1 -1
  20. package/dist/cli/config-selector.js.map +1 -1
  21. package/dist/cli/file-processor.d.ts.map +1 -1
  22. package/dist/cli/file-processor.js +4 -0
  23. package/dist/cli/file-processor.js.map +1 -1
  24. package/dist/cli/initial-message.d.ts +18 -0
  25. package/dist/cli/initial-message.d.ts.map +1 -0
  26. package/dist/cli/initial-message.js +22 -0
  27. package/dist/cli/initial-message.js.map +1 -0
  28. package/dist/cli/list-models.d.ts.map +1 -1
  29. package/dist/cli/list-models.js +7 -1
  30. package/dist/cli/list-models.js.map +1 -1
  31. package/dist/cli/session-picker.d.ts.map +1 -1
  32. package/dist/cli/session-picker.js +2 -1
  33. package/dist/cli/session-picker.js.map +1 -1
  34. package/dist/cli.d.ts.map +1 -1
  35. package/dist/cli.js +9 -5
  36. package/dist/cli.js.map +1 -1
  37. package/dist/config.d.ts +24 -0
  38. package/dist/config.d.ts.map +1 -1
  39. package/dist/config.js +226 -30
  40. package/dist/config.js.map +1 -1
  41. package/dist/core/agent-session-runtime.d.ts +117 -0
  42. package/dist/core/agent-session-runtime.d.ts.map +1 -0
  43. package/dist/core/agent-session-runtime.js +300 -0
  44. package/dist/core/agent-session-runtime.js.map +1 -0
  45. package/dist/core/agent-session-services.d.ts +86 -0
  46. package/dist/core/agent-session-services.d.ts.map +1 -0
  47. package/dist/core/agent-session-services.js +117 -0
  48. package/dist/core/agent-session-services.js.map +1 -0
  49. package/dist/core/agent-session.d.ts +63 -82
  50. package/dist/core/agent-session.d.ts.map +1 -1
  51. package/dist/core/agent-session.js +674 -628
  52. package/dist/core/agent-session.js.map +1 -1
  53. package/dist/core/api-key-store.d.ts +87 -0
  54. package/dist/core/api-key-store.d.ts.map +1 -0
  55. package/dist/core/api-key-store.js +168 -0
  56. package/dist/core/api-key-store.js.map +1 -0
  57. package/dist/core/auth-guidance.d.ts +5 -0
  58. package/dist/core/auth-guidance.d.ts.map +1 -0
  59. package/dist/core/auth-guidance.js +21 -0
  60. package/dist/core/auth-guidance.js.map +1 -0
  61. package/dist/core/auth-storage.d.ts +12 -5
  62. package/dist/core/auth-storage.d.ts.map +1 -1
  63. package/dist/core/auth-storage.js +34 -8
  64. package/dist/core/auth-storage.js.map +1 -1
  65. package/dist/core/bash-executor.d.ts +0 -15
  66. package/dist/core/bash-executor.d.ts.map +1 -1
  67. package/dist/core/bash-executor.js +28 -129
  68. package/dist/core/bash-executor.js.map +1 -1
  69. package/dist/core/compaction/branch-summarization.d.ts +2 -0
  70. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  71. package/dist/core/compaction/branch-summarization.js +3 -2
  72. package/dist/core/compaction/branch-summarization.js.map +1 -1
  73. package/dist/core/compaction/compaction.d.ts +4 -4
  74. package/dist/core/compaction/compaction.d.ts.map +1 -1
  75. package/dist/core/compaction/compaction.js +32 -27
  76. package/dist/core/compaction/compaction.js.map +1 -1
  77. package/dist/core/compaction/index.d.ts.map +1 -1
  78. package/dist/core/compaction/utils.d.ts.map +1 -1
  79. package/dist/core/compaction/utils.js.map +1 -1
  80. package/dist/core/config-watcher.d.ts +47 -0
  81. package/dist/core/config-watcher.d.ts.map +1 -0
  82. package/dist/core/config-watcher.js +135 -0
  83. package/dist/core/config-watcher.js.map +1 -0
  84. package/dist/core/default-models.json +80 -0
  85. package/dist/core/defaults.d.ts.map +1 -1
  86. package/dist/core/diagnostics.d.ts.map +1 -1
  87. package/dist/core/event-bus.d.ts.map +1 -1
  88. package/dist/core/event-bus.js.map +1 -1
  89. package/dist/core/exec.d.ts.map +1 -1
  90. package/dist/core/exec.js +7 -3
  91. package/dist/core/exec.js.map +1 -1
  92. package/dist/core/export-html/ansi-to-html.d.ts.map +1 -1
  93. package/dist/core/export-html/ansi-to-html.js +1 -1
  94. package/dist/core/export-html/ansi-to-html.js.map +1 -1
  95. package/dist/core/export-html/index.d.ts +7 -4
  96. package/dist/core/export-html/index.d.ts.map +1 -1
  97. package/dist/core/export-html/index.js +15 -13
  98. package/dist/core/export-html/index.js.map +1 -1
  99. package/dist/core/export-html/template.css +112 -17
  100. package/dist/core/export-html/template.html +1 -0
  101. package/dist/core/export-html/template.js +312 -64
  102. package/dist/core/export-html/tool-renderer.d.ts +9 -10
  103. package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
  104. package/dist/core/export-html/tool-renderer.js +61 -16
  105. package/dist/core/export-html/tool-renderer.js.map +1 -1
  106. package/dist/core/extensions/index.d.ts +5 -4
  107. package/dist/core/extensions/index.d.ts.map +1 -1
  108. package/dist/core/extensions/index.js +2 -2
  109. package/dist/core/extensions/index.js.map +1 -1
  110. package/dist/core/extensions/loader.d.ts +0 -1
  111. package/dist/core/extensions/loader.d.ts.map +1 -1
  112. package/dist/core/extensions/loader.js +98 -18
  113. package/dist/core/extensions/loader.js.map +1 -1
  114. package/dist/core/extensions/runner.d.ts +27 -14
  115. package/dist/core/extensions/runner.d.ts.map +1 -1
  116. package/dist/core/extensions/runner.js +299 -115
  117. package/dist/core/extensions/runner.js.map +1 -1
  118. package/dist/core/extensions/types.d.ts +200 -44
  119. package/dist/core/extensions/types.d.ts.map +1 -1
  120. package/dist/core/extensions/types.js +10 -0
  121. package/dist/core/extensions/types.js.map +1 -1
  122. package/dist/core/extensions/wrapper.d.ts +4 -11
  123. package/dist/core/extensions/wrapper.d.ts.map +1 -1
  124. package/dist/core/extensions/wrapper.js +7 -87
  125. package/dist/core/extensions/wrapper.js.map +1 -1
  126. package/dist/core/footer-data-provider.d.ts +22 -2
  127. package/dist/core/footer-data-provider.d.ts.map +1 -1
  128. package/dist/core/footer-data-provider.js +225 -49
  129. package/dist/core/footer-data-provider.js.map +1 -1
  130. package/dist/core/index.d.ts +5 -2
  131. package/dist/core/index.d.ts.map +1 -1
  132. package/dist/core/index.js +5 -2
  133. package/dist/core/index.js.map +1 -1
  134. package/dist/core/keybindings.d.ts +348 -50
  135. package/dist/core/keybindings.d.ts.map +1 -1
  136. package/dist/core/keybindings.js +276 -132
  137. package/dist/core/keybindings.js.map +1 -1
  138. package/dist/core/messages.d.ts.map +1 -1
  139. package/dist/core/messages.js.map +1 -1
  140. package/dist/core/model-registry.d.ts +41 -5
  141. package/dist/core/model-registry.d.ts.map +1 -1
  142. package/dist/core/model-registry.js +316 -136
  143. package/dist/core/model-registry.js.map +1 -1
  144. package/dist/core/model-resolver.d.ts +6 -0
  145. package/dist/core/model-resolver.d.ts.map +1 -1
  146. package/dist/core/model-resolver.js +70 -37
  147. package/dist/core/model-resolver.js.map +1 -1
  148. package/dist/core/output-guard.d.ts +6 -0
  149. package/dist/core/output-guard.d.ts.map +1 -0
  150. package/dist/core/output-guard.js +59 -0
  151. package/dist/core/output-guard.js.map +1 -0
  152. package/dist/core/package-manager.d.ts +49 -7
  153. package/dist/core/package-manager.d.ts.map +1 -1
  154. package/dist/core/package-manager.js +655 -122
  155. package/dist/core/package-manager.js.map +1 -1
  156. package/dist/core/prompt-templates.d.ts +12 -10
  157. package/dist/core/prompt-templates.d.ts.map +1 -1
  158. package/dist/core/prompt-templates.js +37 -38
  159. package/dist/core/prompt-templates.js.map +1 -1
  160. package/dist/core/provider-display-names.d.ts +2 -0
  161. package/dist/core/provider-display-names.d.ts.map +1 -0
  162. package/dist/core/provider-display-names.js +33 -0
  163. package/dist/core/provider-display-names.js.map +1 -0
  164. package/dist/core/resolve-config-value.d.ts +6 -0
  165. package/dist/core/resolve-config-value.d.ts.map +1 -1
  166. package/dist/core/resolve-config-value.js +75 -8
  167. package/dist/core/resolve-config-value.js.map +1 -1
  168. package/dist/core/resource-loader.d.ts +18 -8
  169. package/dist/core/resource-loader.d.ts.map +1 -1
  170. package/dist/core/resource-loader.js +217 -123
  171. package/dist/core/resource-loader.js.map +1 -1
  172. package/dist/core/sdk.d.ts +25 -8
  173. package/dist/core/sdk.d.ts.map +1 -1
  174. package/dist/core/sdk.js +84 -37
  175. package/dist/core/sdk.js.map +1 -1
  176. package/dist/core/session-cwd.d.ts +19 -0
  177. package/dist/core/session-cwd.d.ts.map +1 -0
  178. package/dist/core/session-cwd.js +38 -0
  179. package/dist/core/session-cwd.js.map +1 -0
  180. package/dist/core/session-manager.d.ts +11 -1
  181. package/dist/core/session-manager.d.ts.map +1 -1
  182. package/dist/core/session-manager.js +42 -27
  183. package/dist/core/session-manager.js.map +1 -1
  184. package/dist/core/settings-manager.d.ts +34 -5
  185. package/dist/core/settings-manager.d.ts.map +1 -1
  186. package/dist/core/settings-manager.js +113 -13
  187. package/dist/core/settings-manager.js.map +1 -1
  188. package/dist/core/skills.d.ts +13 -11
  189. package/dist/core/skills.d.ts.map +1 -1
  190. package/dist/core/skills.js +59 -19
  191. package/dist/core/skills.js.map +1 -1
  192. package/dist/core/slash-commands.d.ts +2 -3
  193. package/dist/core/slash-commands.d.ts.map +1 -1
  194. package/dist/core/slash-commands.js +9 -6
  195. package/dist/core/slash-commands.js.map +1 -1
  196. package/dist/core/source-info.d.ts +18 -0
  197. package/dist/core/source-info.d.ts.map +1 -0
  198. package/dist/core/source-info.js +19 -0
  199. package/dist/core/source-info.js.map +1 -0
  200. package/dist/core/system-prompt.d.ts +3 -3
  201. package/dist/core/system-prompt.d.ts.map +1 -1
  202. package/dist/core/system-prompt.js +16 -55
  203. package/dist/core/system-prompt.js.map +1 -1
  204. package/dist/core/telemetry.d.ts +3 -0
  205. package/dist/core/telemetry.d.ts.map +1 -0
  206. package/dist/core/telemetry.js +9 -0
  207. package/dist/core/telemetry.js.map +1 -0
  208. package/dist/core/timings.d.ts +1 -0
  209. package/dist/core/timings.d.ts.map +1 -1
  210. package/dist/core/timings.js +6 -0
  211. package/dist/core/timings.js.map +1 -1
  212. package/dist/core/tools/bash.d.ts +27 -14
  213. package/dist/core/tools/bash.d.ts.map +1 -1
  214. package/dist/core/tools/bash.js +301 -208
  215. package/dist/core/tools/bash.js.map +1 -1
  216. package/dist/core/tools/edit-diff.d.ts +23 -1
  217. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  218. package/dist/core/tools/edit-diff.js +154 -59
  219. package/dist/core/tools/edit-diff.js.map +1 -1
  220. package/dist/core/tools/edit.d.ts +22 -12
  221. package/dist/core/tools/edit.d.ts.map +1 -1
  222. package/dist/core/tools/edit.js +243 -65
  223. package/dist/core/tools/edit.js.map +1 -1
  224. package/dist/core/tools/file-mutation-queue.d.ts +6 -0
  225. package/dist/core/tools/file-mutation-queue.d.ts.map +1 -0
  226. package/dist/core/tools/file-mutation-queue.js +37 -0
  227. package/dist/core/tools/file-mutation-queue.js.map +1 -0
  228. package/dist/core/tools/find.d.ts +10 -14
  229. package/dist/core/tools/find.d.ts.map +1 -1
  230. package/dist/core/tools/find.js +202 -110
  231. package/dist/core/tools/find.js.map +1 -1
  232. package/dist/core/tools/grep.d.ts +14 -22
  233. package/dist/core/tools/grep.d.ts.map +1 -1
  234. package/dist/core/tools/grep.js +100 -35
  235. package/dist/core/tools/grep.js.map +1 -1
  236. package/dist/core/tools/index.d.ts +27 -60
  237. package/dist/core/tools/index.d.ts.map +1 -1
  238. package/dist/core/tools/index.js +96 -45
  239. package/dist/core/tools/index.js.map +1 -1
  240. package/dist/core/tools/ls.d.ts +8 -11
  241. package/dist/core/tools/ls.d.ts.map +1 -1
  242. package/dist/core/tools/ls.js +66 -15
  243. package/dist/core/tools/ls.js.map +1 -1
  244. package/dist/core/tools/output-accumulator.d.ts +50 -0
  245. package/dist/core/tools/output-accumulator.d.ts.map +1 -0
  246. package/dist/core/tools/output-accumulator.js +178 -0
  247. package/dist/core/tools/output-accumulator.js.map +1 -0
  248. package/dist/core/tools/path-utils.d.ts.map +1 -1
  249. package/dist/core/tools/path-utils.js +1 -1
  250. package/dist/core/tools/path-utils.js.map +1 -1
  251. package/dist/core/tools/read.d.ts +9 -13
  252. package/dist/core/tools/read.d.ts.map +1 -1
  253. package/dist/core/tools/read.js +175 -52
  254. package/dist/core/tools/read.js.map +1 -1
  255. package/dist/core/tools/render-utils.d.ts +21 -0
  256. package/dist/core/tools/render-utils.d.ts.map +1 -0
  257. package/dist/core/tools/render-utils.js +49 -0
  258. package/dist/core/tools/render-utils.js.map +1 -0
  259. package/dist/core/tools/tool-definition-wrapper.d.ts +14 -0
  260. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -0
  261. package/dist/core/tools/tool-definition-wrapper.js +34 -0
  262. package/dist/core/tools/tool-definition-wrapper.js.map +1 -0
  263. package/dist/core/tools/truncate.d.ts.map +1 -1
  264. package/dist/core/tools/truncate.js.map +1 -1
  265. package/dist/core/tools/write.d.ts +8 -11
  266. package/dist/core/tools/write.d.ts.map +1 -1
  267. package/dist/core/tools/write.js +167 -32
  268. package/dist/core/tools/write.js.map +1 -1
  269. package/dist/index.d.ts +12 -9
  270. package/dist/index.d.ts.map +1 -1
  271. package/dist/index.js +12 -10
  272. package/dist/index.js.map +1 -1
  273. package/dist/main.d.ts +5 -1
  274. package/dist/main.d.ts.map +1 -1
  275. package/dist/main.js +326 -404
  276. package/dist/main.js.map +1 -1
  277. package/dist/migrations.d.ts +2 -2
  278. package/dist/migrations.d.ts.map +1 -1
  279. package/dist/migrations.js +24 -4
  280. package/dist/migrations.js.map +1 -1
  281. package/dist/modes/index.d.ts.map +1 -1
  282. package/dist/modes/interactive/components/armin.d.ts.map +1 -1
  283. package/dist/modes/interactive/components/armin.js +10 -6
  284. package/dist/modes/interactive/components/armin.js.map +1 -1
  285. package/dist/modes/interactive/components/assistant-message.d.ts +5 -1
  286. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  287. package/dist/modes/interactive/components/assistant-message.js +32 -3
  288. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  289. package/dist/modes/interactive/components/bash-execution.d.ts +0 -1
  290. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  291. package/dist/modes/interactive/components/bash-execution.js +31 -12
  292. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  293. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
  294. package/dist/modes/interactive/components/bordered-loader.js +7 -1
  295. package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
  296. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  297. package/dist/modes/interactive/components/branch-summary-message.js +5 -3
  298. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  299. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  300. package/dist/modes/interactive/components/compaction-summary-message.js +5 -3
  301. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  302. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  303. package/dist/modes/interactive/components/config-selector.js +49 -16
  304. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  305. package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -1
  306. package/dist/modes/interactive/components/countdown-timer.js +5 -0
  307. package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
  308. package/dist/modes/interactive/components/custom-editor.d.ts +3 -3
  309. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  310. package/dist/modes/interactive/components/custom-editor.js +14 -7
  311. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  312. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  313. package/dist/modes/interactive/components/custom-message.js +6 -1
  314. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  315. package/dist/modes/interactive/components/daxnuts.d.ts.map +1 -1
  316. package/dist/modes/interactive/components/daxnuts.js +8 -6
  317. package/dist/modes/interactive/components/daxnuts.js.map +1 -1
  318. package/dist/modes/interactive/components/diff.d.ts.map +1 -1
  319. package/dist/modes/interactive/components/diff.js.map +1 -1
  320. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  321. package/dist/modes/interactive/components/dynamic-border.js +1 -0
  322. package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  323. package/dist/modes/interactive/components/earendil-announcement.d.ts +5 -0
  324. package/dist/modes/interactive/components/earendil-announcement.d.ts.map +1 -0
  325. package/dist/modes/interactive/components/earendil-announcement.js +40 -0
  326. package/dist/modes/interactive/components/earendil-announcement.js.map +1 -0
  327. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  328. package/dist/modes/interactive/components/extension-editor.js +16 -10
  329. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  330. package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  331. package/dist/modes/interactive/components/extension-input.js +13 -7
  332. package/dist/modes/interactive/components/extension-input.js.map +1 -1
  333. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  334. package/dist/modes/interactive/components/extension-selector.js +18 -11
  335. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  336. package/dist/modes/interactive/components/footer.d.ts +1 -0
  337. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  338. package/dist/modes/interactive/components/footer.js +7 -2
  339. package/dist/modes/interactive/components/footer.js.map +1 -1
  340. package/dist/modes/interactive/components/index.d.ts +1 -1
  341. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  342. package/dist/modes/interactive/components/index.js +1 -1
  343. package/dist/modes/interactive/components/index.js.map +1 -1
  344. package/dist/modes/interactive/components/keybinding-hints.d.ts +8 -36
  345. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  346. package/dist/modes/interactive/components/keybinding-hints.js +23 -48
  347. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  348. package/dist/modes/interactive/components/login-dialog.d.ts +5 -1
  349. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  350. package/dist/modes/interactive/components/login-dialog.js +35 -14
  351. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  352. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  353. package/dist/modes/interactive/components/model-selector.js +41 -22
  354. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  355. package/dist/modes/interactive/components/oauth-selector.d.ts +18 -6
  356. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  357. package/dist/modes/interactive/components/oauth-selector.js +104 -31
  358. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  359. package/dist/modes/interactive/components/scoped-models-selector.d.ts +5 -12
  360. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  361. package/dist/modes/interactive/components/scoped-models-selector.js +61 -42
  362. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  363. package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
  364. package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
  365. package/dist/modes/interactive/components/session-selector.d.ts +2 -1
  366. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  367. package/dist/modes/interactive/components/session-selector.js +109 -73
  368. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  369. package/dist/modes/interactive/components/settings-selector.d.ts +9 -0
  370. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  371. package/dist/modes/interactive/components/settings-selector.js +84 -4
  372. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  373. package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
  374. package/dist/modes/interactive/components/show-images-selector.js +6 -1
  375. package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
  376. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  377. package/dist/modes/interactive/components/skill-invocation-message.js +5 -3
  378. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  379. package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
  380. package/dist/modes/interactive/components/theme-selector.js +7 -1
  381. package/dist/modes/interactive/components/theme-selector.js.map +1 -1
  382. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  383. package/dist/modes/interactive/components/thinking-selector.js +6 -1
  384. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  385. package/dist/modes/interactive/components/tool-execution.d.ts +20 -34
  386. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  387. package/dist/modes/interactive/components/tool-execution.js +158 -636
  388. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  389. package/dist/modes/interactive/components/tree-selector.d.ts +21 -2
  390. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  391. package/dist/modes/interactive/components/tree-selector.js +224 -52
  392. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  393. package/dist/modes/interactive/components/user-message-selector.d.ts +2 -2
  394. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
  395. package/dist/modes/interactive/components/user-message-selector.js +20 -16
  396. package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
  397. package/dist/modes/interactive/components/user-message.d.ts +1 -0
  398. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  399. package/dist/modes/interactive/components/user-message.js +8 -6
  400. package/dist/modes/interactive/components/user-message.js.map +1 -1
  401. package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -1
  402. package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
  403. package/dist/modes/interactive/interactive-mode.d.ts +67 -39
  404. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  405. package/dist/modes/interactive/interactive-mode.js +1556 -680
  406. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  407. package/dist/modes/interactive/theme/dark.json +1 -1
  408. package/dist/modes/interactive/theme/light.json +1 -1
  409. package/dist/modes/interactive/theme/theme.d.ts +3 -0
  410. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  411. package/dist/modes/interactive/theme/theme.js +101 -72
  412. package/dist/modes/interactive/theme/theme.js.map +1 -1
  413. package/dist/modes/print-mode.d.ts +2 -2
  414. package/dist/modes/print-mode.d.ts.map +1 -1
  415. package/dist/modes/print-mode.js +107 -77
  416. package/dist/modes/print-mode.js.map +1 -1
  417. package/dist/modes/rpc/jsonl.d.ts +17 -0
  418. package/dist/modes/rpc/jsonl.d.ts.map +1 -0
  419. package/dist/modes/rpc/jsonl.js +49 -0
  420. package/dist/modes/rpc/jsonl.js.map +1 -0
  421. package/dist/modes/rpc/rpc-client.d.ts +8 -1
  422. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  423. package/dist/modes/rpc/rpc-client.js +22 -16
  424. package/dist/modes/rpc/rpc-client.js.map +1 -1
  425. package/dist/modes/rpc/rpc-mode.d.ts +2 -2
  426. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  427. package/dist/modes/rpc/rpc-mode.js +184 -94
  428. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  429. package/dist/modes/rpc/rpc-types.d.ts +14 -4
  430. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  431. package/dist/modes/rpc/rpc-types.js.map +1 -1
  432. package/dist/package-manager-cli.d.ts +4 -0
  433. package/dist/package-manager-cli.d.ts.map +1 -0
  434. package/dist/package-manager-cli.js +460 -0
  435. package/dist/package-manager-cli.js.map +1 -0
  436. package/dist/utils/changelog.d.ts.map +1 -1
  437. package/dist/utils/changelog.js.map +1 -1
  438. package/dist/utils/child-process.d.ts +12 -0
  439. package/dist/utils/child-process.d.ts.map +1 -0
  440. package/dist/utils/child-process.js +86 -0
  441. package/dist/utils/child-process.js.map +1 -0
  442. package/dist/utils/clipboard-image.d.ts.map +1 -1
  443. package/dist/utils/clipboard-image.js +94 -11
  444. package/dist/utils/clipboard-image.js.map +1 -1
  445. package/dist/utils/clipboard-native.d.ts +1 -0
  446. package/dist/utils/clipboard-native.d.ts.map +1 -1
  447. package/dist/utils/clipboard-native.js.map +1 -1
  448. package/dist/utils/clipboard.d.ts +1 -1
  449. package/dist/utils/clipboard.d.ts.map +1 -1
  450. package/dist/utils/clipboard.js +96 -46
  451. package/dist/utils/clipboard.js.map +1 -1
  452. package/dist/utils/exif-orientation.d.ts +5 -0
  453. package/dist/utils/exif-orientation.d.ts.map +1 -0
  454. package/dist/utils/exif-orientation.js +158 -0
  455. package/dist/utils/exif-orientation.js.map +1 -0
  456. package/dist/utils/frontmatter.d.ts.map +1 -1
  457. package/dist/utils/frontmatter.js.map +1 -1
  458. package/dist/utils/fs-watch.d.ts +5 -0
  459. package/dist/utils/fs-watch.d.ts.map +1 -0
  460. package/dist/utils/fs-watch.js +25 -0
  461. package/dist/utils/fs-watch.js.map +1 -0
  462. package/dist/utils/git.d.ts.map +1 -1
  463. package/dist/utils/git.js.map +1 -1
  464. package/dist/utils/image-convert.d.ts.map +1 -1
  465. package/dist/utils/image-convert.js +5 -1
  466. package/dist/utils/image-convert.js.map +1 -1
  467. package/dist/utils/image-resize.d.ts +5 -5
  468. package/dist/utils/image-resize.d.ts.map +1 -1
  469. package/dist/utils/image-resize.js +51 -95
  470. package/dist/utils/image-resize.js.map +1 -1
  471. package/dist/utils/mime.d.ts.map +1 -1
  472. package/dist/utils/mime.js.map +1 -1
  473. package/dist/utils/paths.d.ts +16 -0
  474. package/dist/utils/paths.d.ts.map +1 -0
  475. package/dist/utils/paths.js +50 -0
  476. package/dist/utils/paths.js.map +1 -0
  477. package/dist/utils/photon.d.ts.map +1 -1
  478. package/dist/utils/photon.js.map +1 -1
  479. package/dist/utils/pi-user-agent.d.ts +2 -0
  480. package/dist/utils/pi-user-agent.d.ts.map +1 -0
  481. package/dist/utils/pi-user-agent.js +5 -0
  482. package/dist/utils/pi-user-agent.js.map +1 -0
  483. package/dist/utils/shell.d.ts +10 -6
  484. package/dist/utils/shell.d.ts.map +1 -1
  485. package/dist/utils/shell.js +29 -25
  486. package/dist/utils/shell.js.map +1 -1
  487. package/dist/utils/sleep.d.ts.map +1 -1
  488. package/dist/utils/sleep.js.map +1 -1
  489. package/dist/utils/tools-manager.d.ts.map +1 -1
  490. package/dist/utils/tools-manager.js +11 -6
  491. package/dist/utils/tools-manager.js.map +1 -1
  492. package/dist/utils/version-check.d.ts +14 -0
  493. package/dist/utils/version-check.d.ts.map +1 -0
  494. package/dist/utils/version-check.js +77 -0
  495. package/dist/utils/version-check.js.map +1 -0
  496. package/docs/compaction.md +394 -0
  497. package/docs/custom-provider.md +646 -0
  498. package/docs/development.md +71 -0
  499. package/docs/docs.json +148 -0
  500. package/docs/extensions.md +2596 -0
  501. package/docs/images/doom-extension.png +0 -0
  502. package/docs/images/exy.png +0 -0
  503. package/docs/images/interactive-mode.png +0 -0
  504. package/docs/images/tree-view.png +0 -0
  505. package/docs/index.md +70 -0
  506. package/docs/json.md +82 -0
  507. package/docs/keybindings.md +197 -0
  508. package/docs/models.md +474 -0
  509. package/docs/packages.md +223 -0
  510. package/docs/prompt-templates.md +88 -0
  511. package/docs/providers.md +243 -0
  512. package/docs/quickstart.md +142 -0
  513. package/docs/rpc.md +1407 -0
  514. package/docs/sdk.md +1149 -0
  515. package/docs/session-format.md +412 -0
  516. package/docs/sessions.md +137 -0
  517. package/docs/settings.md +279 -0
  518. package/docs/shell-aliases.md +13 -0
  519. package/docs/skills.md +232 -0
  520. package/docs/terminal-setup.md +106 -0
  521. package/docs/termux.md +127 -0
  522. package/docs/themes.md +295 -0
  523. package/docs/tmux.md +61 -0
  524. package/docs/tui.md +918 -0
  525. package/docs/usage.md +277 -0
  526. package/docs/windows.md +17 -0
  527. package/examples/README.md +25 -0
  528. package/examples/extensions/README.md +208 -0
  529. package/examples/extensions/auto-commit-on-exit.ts +49 -0
  530. package/examples/extensions/bash-spawn-hook.ts +30 -0
  531. package/examples/extensions/bookmark.ts +50 -0
  532. package/examples/extensions/border-status-editor.ts +150 -0
  533. package/examples/extensions/built-in-tool-renderer.ts +249 -0
  534. package/examples/extensions/claude-rules.ts +86 -0
  535. package/examples/extensions/commands.ts +72 -0
  536. package/examples/extensions/confirm-destructive.ts +59 -0
  537. package/examples/extensions/custom-compaction.ts +127 -0
  538. package/examples/extensions/custom-footer.ts +64 -0
  539. package/examples/extensions/custom-header.ts +73 -0
  540. package/examples/extensions/custom-provider-anthropic/index.ts +604 -0
  541. package/examples/extensions/custom-provider-anthropic/package-lock.json +24 -0
  542. package/examples/extensions/custom-provider-anthropic/package.json +19 -0
  543. package/examples/extensions/custom-provider-gitlab-duo/index.ts +349 -0
  544. package/examples/extensions/custom-provider-gitlab-duo/package.json +16 -0
  545. package/examples/extensions/custom-provider-gitlab-duo/test.ts +82 -0
  546. package/examples/extensions/dirty-repo-guard.ts +56 -0
  547. package/examples/extensions/doom-overlay/README.md +46 -0
  548. package/examples/extensions/doom-overlay/doom/build/doom.js +21 -0
  549. package/examples/extensions/doom-overlay/doom/build/doom.wasm +0 -0
  550. package/examples/extensions/doom-overlay/doom/build.sh +152 -0
  551. package/examples/extensions/doom-overlay/doom/doomgeneric_pi.c +72 -0
  552. package/examples/extensions/doom-overlay/doom-component.ts +132 -0
  553. package/examples/extensions/doom-overlay/doom-engine.ts +173 -0
  554. package/examples/extensions/doom-overlay/doom-keys.ts +104 -0
  555. package/examples/extensions/doom-overlay/index.ts +74 -0
  556. package/examples/extensions/doom-overlay/wad-finder.ts +51 -0
  557. package/examples/extensions/dynamic-resources/SKILL.md +8 -0
  558. package/examples/extensions/dynamic-resources/dynamic.json +79 -0
  559. package/examples/extensions/dynamic-resources/dynamic.md +5 -0
  560. package/examples/extensions/dynamic-resources/index.ts +15 -0
  561. package/examples/extensions/dynamic-tools.ts +74 -0
  562. package/examples/extensions/event-bus.ts +43 -0
  563. package/examples/extensions/file-trigger.ts +41 -0
  564. package/examples/extensions/git-checkpoint.ts +53 -0
  565. package/examples/extensions/github-issue-autocomplete.ts +185 -0
  566. package/examples/extensions/handoff.ts +191 -0
  567. package/examples/extensions/hello.ts +26 -0
  568. package/examples/extensions/hidden-thinking-label.ts +53 -0
  569. package/examples/extensions/inline-bash.ts +94 -0
  570. package/examples/extensions/input-transform.ts +43 -0
  571. package/examples/extensions/interactive-shell.ts +196 -0
  572. package/examples/extensions/mac-system-theme.ts +47 -0
  573. package/examples/extensions/message-renderer.ts +59 -0
  574. package/examples/extensions/minimal-mode.ts +426 -0
  575. package/examples/extensions/modal-editor.ts +85 -0
  576. package/examples/extensions/model-status.ts +31 -0
  577. package/examples/extensions/notify.ts +55 -0
  578. package/examples/extensions/overlay-qa-tests.ts +1348 -0
  579. package/examples/extensions/overlay-test.ts +150 -0
  580. package/examples/extensions/permission-gate.ts +34 -0
  581. package/examples/extensions/pirate.ts +47 -0
  582. package/examples/extensions/plan-mode/README.md +65 -0
  583. package/examples/extensions/plan-mode/index.ts +340 -0
  584. package/examples/extensions/plan-mode/utils.ts +168 -0
  585. package/examples/extensions/preset.ts +430 -0
  586. package/examples/extensions/prompt-customizer.ts +97 -0
  587. package/examples/extensions/protected-paths.ts +30 -0
  588. package/examples/extensions/provider-payload.ts +18 -0
  589. package/examples/extensions/qna.ts +122 -0
  590. package/examples/extensions/question.ts +264 -0
  591. package/examples/extensions/questionnaire.ts +427 -0
  592. package/examples/extensions/rainbow-editor.ts +88 -0
  593. package/examples/extensions/reload-runtime.ts +37 -0
  594. package/examples/extensions/rpc-demo.ts +118 -0
  595. package/examples/extensions/sandbox/index.ts +321 -0
  596. package/examples/extensions/sandbox/package-lock.json +92 -0
  597. package/examples/extensions/sandbox/package.json +19 -0
  598. package/examples/extensions/send-user-message.ts +97 -0
  599. package/examples/extensions/session-name.ts +27 -0
  600. package/examples/extensions/shutdown-command.ts +63 -0
  601. package/examples/extensions/snake.ts +343 -0
  602. package/examples/extensions/space-invaders.ts +560 -0
  603. package/examples/extensions/ssh.ts +220 -0
  604. package/examples/extensions/status-line.ts +32 -0
  605. package/examples/extensions/structured-output.ts +65 -0
  606. package/examples/extensions/subagent/README.md +172 -0
  607. package/examples/extensions/subagent/agents/planner.md +37 -0
  608. package/examples/extensions/subagent/agents/reviewer.md +35 -0
  609. package/examples/extensions/subagent/agents/scout.md +50 -0
  610. package/examples/extensions/subagent/agents/worker.md +24 -0
  611. package/examples/extensions/subagent/agents.ts +126 -0
  612. package/examples/extensions/subagent/index.ts +987 -0
  613. package/examples/extensions/subagent/prompts/implement-and-review.md +10 -0
  614. package/examples/extensions/subagent/prompts/implement.md +10 -0
  615. package/examples/extensions/subagent/prompts/scout-and-plan.md +9 -0
  616. package/examples/extensions/summarize.ts +206 -0
  617. package/examples/extensions/system-prompt-header.ts +17 -0
  618. package/examples/extensions/tic-tac-toe.ts +1008 -0
  619. package/examples/extensions/timed-confirm.ts +70 -0
  620. package/examples/extensions/titlebar-spinner.ts +58 -0
  621. package/examples/extensions/todo.ts +297 -0
  622. package/examples/extensions/tool-override.ts +144 -0
  623. package/examples/extensions/tools.ts +141 -0
  624. package/examples/extensions/trigger-compact.ts +50 -0
  625. package/examples/extensions/truncated-tool.ts +195 -0
  626. package/examples/extensions/widget-placement.ts +9 -0
  627. package/examples/extensions/with-deps/index.ts +32 -0
  628. package/examples/extensions/with-deps/package-lock.json +31 -0
  629. package/examples/extensions/with-deps/package.json +22 -0
  630. package/examples/extensions/working-indicator.ts +123 -0
  631. package/examples/extensions/working-message-test.ts +25 -0
  632. package/examples/rpc-extension-ui.ts +632 -0
  633. package/examples/sdk/01-minimal.ts +22 -0
  634. package/examples/sdk/02-custom-model.ts +49 -0
  635. package/examples/sdk/03-custom-prompt.ts +62 -0
  636. package/examples/sdk/04-skills.ts +55 -0
  637. package/examples/sdk/05-tools.ts +44 -0
  638. package/examples/sdk/06-extensions.ts +90 -0
  639. package/examples/sdk/07-context-files.ts +42 -0
  640. package/examples/sdk/08-prompt-templates.ts +51 -0
  641. package/examples/sdk/09-api-keys-and-oauth.ts +48 -0
  642. package/examples/sdk/10-settings.ts +53 -0
  643. package/examples/sdk/11-sessions.ts +48 -0
  644. package/examples/sdk/12-full-control.ts +73 -0
  645. package/examples/sdk/13-session-runtime.ts +67 -0
  646. package/examples/sdk/README.md +147 -0
  647. package/extensions/phi/init.ts +15 -1
  648. package/extensions/phi/keys.ts +186 -0
  649. package/extensions/phi/providers/alibaba.ts +126 -0
  650. package/extensions/phi/providers/opencode-go.ts +204 -0
  651. package/extensions/phi/setup.ts +692 -0
  652. package/extensions/phi/smart-router.ts +8 -0
  653. package/extensions/phi/web-search.ts +432 -186
  654. package/package.json +111 -106
  655. package/scripts/copy-assets.sh +0 -0
  656. package/scripts/migrate-sessions.sh +0 -0
@@ -1,18 +1,27 @@
1
- import { Container, getEditorKeybindings, Input, matchesKey, Spacer, Text, TruncatedText, truncateToWidth, } from "phi-code-tui";
1
+ import { Container, getKeybindings, Input, Spacer, Text, TruncatedText, truncateToWidth, } from "phi-code-tui";
2
2
  import { theme } from "../theme/theme.js";
3
3
  import { DynamicBorder } from "./dynamic-border.js";
4
- import { keyHint } from "./keybinding-hints.js";
4
+ import { keyHint, keyText } from "./keybinding-hints.js";
5
5
  class TreeList {
6
+ flatNodes = [];
7
+ filteredNodes = [];
8
+ selectedIndex = 0;
9
+ currentLeafId;
10
+ maxVisibleLines;
11
+ filterMode = "default";
12
+ searchQuery = "";
13
+ toolCallMap = new Map();
14
+ multipleRoots = false;
15
+ showLabelTimestamps = false;
16
+ activePathIds = new Set();
17
+ visibleParentMap = new Map();
18
+ visibleChildrenMap = new Map();
19
+ lastSelectedId = null;
20
+ foldedNodes = new Set();
21
+ onSelect;
22
+ onCancel;
23
+ onLabelEdit;
6
24
  constructor(tree, currentLeafId, maxVisibleLines, initialSelectedId, initialFilterMode) {
7
- this.flatNodes = [];
8
- this.filteredNodes = [];
9
- this.selectedIndex = 0;
10
- this.filterMode = "default";
11
- this.searchQuery = "";
12
- this.toolCallMap = new Map();
13
- this.multipleRoots = false;
14
- this.activePathIds = new Set();
15
- this.lastSelectedId = null;
16
25
  this.currentLeafId = currentLeafId;
17
26
  this.maxVisibleLines = maxVisibleLines;
18
27
  this.filterMode = initialFilterMode ?? "default";
@@ -213,7 +222,8 @@ class TreeList {
213
222
  const isSettingsEntry = entry.type === "label" ||
214
223
  entry.type === "custom" ||
215
224
  entry.type === "model_change" ||
216
- entry.type === "thinking_level_change";
225
+ entry.type === "thinking_level_change" ||
226
+ entry.type === "session_info";
217
227
  switch (this.filterMode) {
218
228
  case "user-only":
219
229
  // Just user messages
@@ -245,6 +255,17 @@ class TreeList {
245
255
  }
246
256
  return true;
247
257
  });
258
+ // Filter out descendants of folded nodes.
259
+ if (this.foldedNodes.size > 0) {
260
+ const skipSet = new Set();
261
+ for (const flatNode of this.flatNodes) {
262
+ const { id, parentId } = flatNode.node.entry;
263
+ if (parentId != null && (this.foldedNodes.has(parentId) || skipSet.has(parentId))) {
264
+ skipSet.add(id);
265
+ }
266
+ }
267
+ this.filteredNodes = this.filteredNodes.filter((flatNode) => !skipSet.has(flatNode.node.entry.id));
268
+ }
248
269
  // Recalculate visual structure (indent, connectors, gutters) based on visible tree
249
270
  this.recalculateVisualStructure();
250
271
  // Try to preserve cursor on the same node, or find nearest visible ancestor
@@ -369,6 +390,9 @@ class TreeList {
369
390
  ]);
370
391
  }
371
392
  }
393
+ // Store visible tree maps for ancestor/descendant lookups in navigation
394
+ this.visibleParentMap = visibleParent;
395
+ this.visibleChildrenMap = visibleChildren;
372
396
  }
373
397
  /** Get searchable text content from a node */
374
398
  getSearchableText(node) {
@@ -407,6 +431,11 @@ class TreeList {
407
431
  case "branch_summary":
408
432
  parts.push("branch summary", entry.summary);
409
433
  break;
434
+ case "session_info":
435
+ parts.push("title");
436
+ if (entry.name)
437
+ parts.push(entry.name);
438
+ break;
410
439
  case "model_change":
411
440
  parts.push("model", entry.modelId);
412
441
  break;
@@ -429,33 +458,41 @@ class TreeList {
429
458
  getSelectedNode() {
430
459
  return this.filteredNodes[this.selectedIndex]?.node;
431
460
  }
432
- updateNodeLabel(entryId, label) {
461
+ updateNodeLabel(entryId, label, labelTimestamp) {
433
462
  for (const flatNode of this.flatNodes) {
434
463
  if (flatNode.node.entry.id === entryId) {
435
464
  flatNode.node.label = label;
465
+ flatNode.node.labelTimestamp = label ? (labelTimestamp ?? new Date().toISOString()) : undefined;
436
466
  break;
437
467
  }
438
468
  }
439
469
  }
440
- getFilterLabel() {
470
+ getStatusLabels() {
471
+ let labels = "";
441
472
  switch (this.filterMode) {
442
473
  case "no-tools":
443
- return " [no-tools]";
474
+ labels += " [no-tools]";
475
+ break;
444
476
  case "user-only":
445
- return " [user]";
477
+ labels += " [user]";
478
+ break;
446
479
  case "labeled-only":
447
- return " [labeled]";
480
+ labels += " [labeled]";
481
+ break;
448
482
  case "all":
449
- return " [all]";
450
- default:
451
- return "";
483
+ labels += " [all]";
484
+ break;
485
+ }
486
+ if (this.showLabelTimestamps) {
487
+ labels += " [+label time]";
452
488
  }
489
+ return labels;
453
490
  }
454
491
  render(width) {
455
492
  const lines = [];
456
493
  if (this.filteredNodes.length === 0) {
457
494
  lines.push(truncateToWidth(theme.fg("muted", " No entries found"), width));
458
- lines.push(truncateToWidth(theme.fg("muted", ` (0/0)${this.getFilterLabel()}`), width));
495
+ lines.push(truncateToWidth(theme.fg("muted", ` (0/0)${this.getStatusLabels()}`), width));
459
496
  return lines;
460
497
  }
461
498
  const startIndex = Math.max(0, Math.min(this.selectedIndex - Math.floor(this.maxVisibleLines / 2), this.filteredNodes.length - this.maxVisibleLines));
@@ -475,6 +512,7 @@ class TreeList {
475
512
  // Build prefix char by char, placing gutters and connector at their positions
476
513
  const totalChars = displayIndent * 3;
477
514
  const prefixChars = [];
515
+ const isFolded = this.foldedNodes.has(entry.id);
478
516
  for (let i = 0; i < totalChars; i++) {
479
517
  const level = Math.floor(i / 3);
480
518
  const posInLevel = i % 3;
@@ -489,12 +527,13 @@ class TreeList {
489
527
  }
490
528
  }
491
529
  else if (connector && level === connectorPosition) {
492
- // Connector at this level
530
+ // Connector at this level, with fold indicator
493
531
  if (posInLevel === 0) {
494
532
  prefixChars.push(flatNode.isLast ? "└" : "├");
495
533
  }
496
534
  else if (posInLevel === 1) {
497
- prefixChars.push("─");
535
+ const foldable = this.isFoldable(entry.id);
536
+ prefixChars.push(isFolded ? "⊞" : foldable ? "⊟" : "─");
498
537
  }
499
538
  else {
500
539
  prefixChars.push(" ");
@@ -505,18 +544,24 @@ class TreeList {
505
544
  }
506
545
  }
507
546
  const prefix = prefixChars.join("");
547
+ // Fold marker for nodes without connectors (roots)
548
+ const showsFoldInConnector = flatNode.showConnector && !flatNode.isVirtualRootChild;
549
+ const foldMarker = isFolded && !showsFoldInConnector ? theme.fg("accent", "⊞ ") : "";
508
550
  // Active path marker - shown right before the entry text
509
551
  const isOnActivePath = this.activePathIds.has(entry.id);
510
552
  const pathMarker = isOnActivePath ? theme.fg("accent", "• ") : "";
511
553
  const label = flatNode.node.label ? theme.fg("warning", `[${flatNode.node.label}] `) : "";
554
+ const labelTimestamp = this.showLabelTimestamps && flatNode.node.label && flatNode.node.labelTimestamp
555
+ ? theme.fg("muted", `${this.formatLabelTimestamp(flatNode.node.labelTimestamp)} `)
556
+ : "";
512
557
  const content = this.getEntryDisplayText(flatNode.node, isSelected);
513
- let line = cursor + theme.fg("dim", prefix) + pathMarker + label + content;
558
+ let line = cursor + theme.fg("dim", prefix) + foldMarker + pathMarker + label + labelTimestamp + content;
514
559
  if (isSelected) {
515
560
  line = theme.bg("selectedBg", line);
516
561
  }
517
562
  lines.push(truncateToWidth(line, width));
518
563
  }
519
- lines.push(truncateToWidth(theme.fg("muted", ` (${this.selectedIndex + 1}/${this.filteredNodes.length})${this.getFilterLabel()}`), width));
564
+ lines.push(truncateToWidth(theme.fg("muted", ` (${this.selectedIndex + 1}/${this.filteredNodes.length})${this.getStatusLabels()}`), width));
520
565
  return lines;
521
566
  }
522
567
  getEntryDisplayText(node, isSelected) {
@@ -598,11 +643,35 @@ class TreeList {
598
643
  case "label":
599
644
  result = theme.fg("dim", `[label: ${entry.label ?? "(cleared)"}]`);
600
645
  break;
646
+ case "session_info":
647
+ result = entry.name
648
+ ? [theme.fg("dim", "[title: "), theme.fg("dim", entry.name), theme.fg("dim", "]")].join("")
649
+ : [theme.fg("dim", "[title: "), theme.italic(theme.fg("dim", "empty")), theme.fg("dim", "]")].join("");
650
+ break;
601
651
  default:
602
652
  result = "";
603
653
  }
604
654
  return isSelected ? theme.bold(result) : result;
605
655
  }
656
+ formatLabelTimestamp(timestamp) {
657
+ const date = new Date(timestamp);
658
+ const now = new Date();
659
+ const hours = date.getHours().toString().padStart(2, "0");
660
+ const minutes = date.getMinutes().toString().padStart(2, "0");
661
+ const time = `${hours}:${minutes}`;
662
+ if (date.getFullYear() === now.getFullYear() &&
663
+ date.getMonth() === now.getMonth() &&
664
+ date.getDate() === now.getDate()) {
665
+ return time;
666
+ }
667
+ const month = date.getMonth() + 1;
668
+ const day = date.getDate();
669
+ if (date.getFullYear() === now.getFullYear()) {
670
+ return `${month}/${day} ${time}`;
671
+ }
672
+ const year = date.getFullYear().toString().slice(-2);
673
+ return `${year}/${month}/${day} ${time}`;
674
+ }
606
675
  extractContent(content) {
607
676
  const maxLen = 200;
608
677
  if (typeof content === "string")
@@ -692,87 +761,119 @@ class TreeList {
692
761
  }
693
762
  }
694
763
  handleInput(keyData) {
695
- const kb = getEditorKeybindings();
696
- if (kb.matches(keyData, "selectUp")) {
764
+ const kb = getKeybindings();
765
+ if (kb.matches(keyData, "tui.select.up")) {
697
766
  this.selectedIndex = this.selectedIndex === 0 ? this.filteredNodes.length - 1 : this.selectedIndex - 1;
698
767
  }
699
- else if (kb.matches(keyData, "selectDown")) {
768
+ else if (kb.matches(keyData, "tui.select.down")) {
700
769
  this.selectedIndex = this.selectedIndex === this.filteredNodes.length - 1 ? 0 : this.selectedIndex + 1;
701
770
  }
702
- else if (kb.matches(keyData, "cursorLeft")) {
771
+ else if (kb.matches(keyData, "app.tree.foldOrUp")) {
772
+ const currentId = this.filteredNodes[this.selectedIndex]?.node.entry.id;
773
+ if (currentId && this.isFoldable(currentId) && !this.foldedNodes.has(currentId)) {
774
+ this.foldedNodes.add(currentId);
775
+ this.applyFilter();
776
+ }
777
+ else {
778
+ this.selectedIndex = this.findBranchSegmentStart("up");
779
+ }
780
+ }
781
+ else if (kb.matches(keyData, "app.tree.unfoldOrDown")) {
782
+ const currentId = this.filteredNodes[this.selectedIndex]?.node.entry.id;
783
+ if (currentId && this.foldedNodes.has(currentId)) {
784
+ this.foldedNodes.delete(currentId);
785
+ this.applyFilter();
786
+ }
787
+ else {
788
+ this.selectedIndex = this.findBranchSegmentStart("down");
789
+ }
790
+ }
791
+ else if (kb.matches(keyData, "tui.editor.cursorLeft") || kb.matches(keyData, "tui.select.pageUp")) {
703
792
  // Page up
704
793
  this.selectedIndex = Math.max(0, this.selectedIndex - this.maxVisibleLines);
705
794
  }
706
- else if (kb.matches(keyData, "cursorRight")) {
795
+ else if (kb.matches(keyData, "tui.editor.cursorRight") || kb.matches(keyData, "tui.select.pageDown")) {
707
796
  // Page down
708
797
  this.selectedIndex = Math.min(this.filteredNodes.length - 1, this.selectedIndex + this.maxVisibleLines);
709
798
  }
710
- else if (kb.matches(keyData, "selectConfirm")) {
799
+ else if (kb.matches(keyData, "tui.select.confirm")) {
711
800
  const selected = this.filteredNodes[this.selectedIndex];
712
801
  if (selected && this.onSelect) {
713
802
  this.onSelect(selected.node.entry.id);
714
803
  }
715
804
  }
716
- else if (kb.matches(keyData, "selectCancel")) {
805
+ else if (kb.matches(keyData, "tui.select.cancel")) {
717
806
  if (this.searchQuery) {
718
807
  this.searchQuery = "";
808
+ this.foldedNodes.clear();
719
809
  this.applyFilter();
720
810
  }
721
811
  else {
722
812
  this.onCancel?.();
723
813
  }
724
814
  }
725
- else if (matchesKey(keyData, "ctrl+d")) {
815
+ else if (kb.matches(keyData, "app.tree.filter.default")) {
726
816
  // Direct filter: default
727
817
  this.filterMode = "default";
818
+ this.foldedNodes.clear();
728
819
  this.applyFilter();
729
820
  }
730
- else if (matchesKey(keyData, "ctrl+t")) {
821
+ else if (kb.matches(keyData, "app.tree.filter.noTools")) {
731
822
  // Toggle filter: no-tools ↔ default
732
823
  this.filterMode = this.filterMode === "no-tools" ? "default" : "no-tools";
824
+ this.foldedNodes.clear();
733
825
  this.applyFilter();
734
826
  }
735
- else if (matchesKey(keyData, "ctrl+u")) {
827
+ else if (kb.matches(keyData, "app.tree.filter.userOnly")) {
736
828
  // Toggle filter: user-only ↔ default
737
829
  this.filterMode = this.filterMode === "user-only" ? "default" : "user-only";
830
+ this.foldedNodes.clear();
738
831
  this.applyFilter();
739
832
  }
740
- else if (matchesKey(keyData, "ctrl+l")) {
833
+ else if (kb.matches(keyData, "app.tree.filter.labeledOnly")) {
741
834
  // Toggle filter: labeled-only ↔ default
742
835
  this.filterMode = this.filterMode === "labeled-only" ? "default" : "labeled-only";
836
+ this.foldedNodes.clear();
743
837
  this.applyFilter();
744
838
  }
745
- else if (matchesKey(keyData, "ctrl+a")) {
839
+ else if (kb.matches(keyData, "app.tree.filter.all")) {
746
840
  // Toggle filter: all ↔ default
747
841
  this.filterMode = this.filterMode === "all" ? "default" : "all";
842
+ this.foldedNodes.clear();
748
843
  this.applyFilter();
749
844
  }
750
- else if (matchesKey(keyData, "shift+ctrl+o")) {
845
+ else if (kb.matches(keyData, "app.tree.filter.cycleBackward")) {
751
846
  // Cycle filter backwards
752
847
  const modes = ["default", "no-tools", "user-only", "labeled-only", "all"];
753
848
  const currentIndex = modes.indexOf(this.filterMode);
754
849
  this.filterMode = modes[(currentIndex - 1 + modes.length) % modes.length];
850
+ this.foldedNodes.clear();
755
851
  this.applyFilter();
756
852
  }
757
- else if (matchesKey(keyData, "ctrl+o")) {
853
+ else if (kb.matches(keyData, "app.tree.filter.cycleForward")) {
758
854
  // Cycle filter forwards: default → no-tools → user-only → labeled-only → all → default
759
855
  const modes = ["default", "no-tools", "user-only", "labeled-only", "all"];
760
856
  const currentIndex = modes.indexOf(this.filterMode);
761
857
  this.filterMode = modes[(currentIndex + 1) % modes.length];
858
+ this.foldedNodes.clear();
762
859
  this.applyFilter();
763
860
  }
764
- else if (kb.matches(keyData, "deleteCharBackward")) {
861
+ else if (kb.matches(keyData, "tui.editor.deleteCharBackward")) {
765
862
  if (this.searchQuery.length > 0) {
766
863
  this.searchQuery = this.searchQuery.slice(0, -1);
864
+ this.foldedNodes.clear();
767
865
  this.applyFilter();
768
866
  }
769
867
  }
770
- else if (matchesKey(keyData, "shift+l")) {
868
+ else if (kb.matches(keyData, "app.tree.editLabel")) {
771
869
  const selected = this.filteredNodes[this.selectedIndex];
772
870
  if (selected && this.onLabelEdit) {
773
871
  this.onLabelEdit(selected.node.entry.id, selected.node.label);
774
872
  }
775
873
  }
874
+ else if (kb.matches(keyData, "app.tree.toggleLabelTimestamp")) {
875
+ this.showLabelTimestamps = !this.showLabelTimestamps;
876
+ }
776
877
  else {
777
878
  const hasControlChars = [...keyData].some((ch) => {
778
879
  const code = ch.charCodeAt(0);
@@ -780,13 +881,68 @@ class TreeList {
780
881
  });
781
882
  if (!hasControlChars && keyData.length > 0) {
782
883
  this.searchQuery += keyData;
884
+ this.foldedNodes.clear();
783
885
  this.applyFilter();
784
886
  }
785
887
  }
786
888
  }
889
+ /**
890
+ * Whether a node can be folded. A node is foldable if it has visible children
891
+ * and is either a root (no visible parent) or a segment start (visible parent
892
+ * has multiple visible children).
893
+ */
894
+ isFoldable(entryId) {
895
+ const children = this.visibleChildrenMap.get(entryId);
896
+ if (!children || children.length === 0)
897
+ return false;
898
+ const parentId = this.visibleParentMap.get(entryId);
899
+ if (parentId === null || parentId === undefined)
900
+ return true;
901
+ const siblings = this.visibleChildrenMap.get(parentId);
902
+ return siblings !== undefined && siblings.length > 1;
903
+ }
904
+ /**
905
+ * Find the index of the next branch segment start in the given direction.
906
+ * A segment start is the first child of a branch point.
907
+ *
908
+ * "up" walks the visible parent chain; "down" walks visible children
909
+ * (always following the first child).
910
+ */
911
+ findBranchSegmentStart(direction) {
912
+ const selectedId = this.filteredNodes[this.selectedIndex]?.node.entry.id;
913
+ if (!selectedId)
914
+ return this.selectedIndex;
915
+ const indexByEntryId = new Map(this.filteredNodes.map((node, i) => [node.node.entry.id, i]));
916
+ let currentId = selectedId;
917
+ if (direction === "down") {
918
+ while (true) {
919
+ const children = this.visibleChildrenMap.get(currentId) ?? [];
920
+ if (children.length === 0)
921
+ return indexByEntryId.get(currentId);
922
+ if (children.length > 1)
923
+ return indexByEntryId.get(children[0]);
924
+ currentId = children[0];
925
+ }
926
+ }
927
+ // direction === "up"
928
+ while (true) {
929
+ const parentId = this.visibleParentMap.get(currentId) ?? null;
930
+ if (parentId === null)
931
+ return indexByEntryId.get(currentId);
932
+ const children = this.visibleChildrenMap.get(parentId) ?? [];
933
+ if (children.length > 1) {
934
+ const segmentStart = indexByEntryId.get(currentId);
935
+ if (segmentStart < this.selectedIndex) {
936
+ return segmentStart;
937
+ }
938
+ }
939
+ currentId = parentId;
940
+ }
941
+ }
787
942
  }
788
943
  /** Component that displays the current search query */
789
944
  class SearchLine {
945
+ treeList;
790
946
  constructor(treeList) {
791
947
  this.treeList = treeList;
792
948
  }
@@ -802,6 +958,12 @@ class SearchLine {
802
958
  }
803
959
  /** Label input component shown when editing a label */
804
960
  class LabelInput {
961
+ input;
962
+ entryId;
963
+ onSubmit;
964
+ onCancel;
965
+ // Focusable implementation - propagate to input for IME cursor positioning
966
+ _focused = false;
805
967
  get focused() {
806
968
  return this._focused;
807
969
  }
@@ -810,8 +972,6 @@ class LabelInput {
810
972
  this.input.focused = value;
811
973
  }
812
974
  constructor(entryId, currentLabel) {
813
- // Focusable implementation - propagate to input for IME cursor positioning
814
- this._focused = false;
815
975
  this.entryId = entryId;
816
976
  this.input = new Input();
817
977
  if (currentLabel) {
@@ -825,16 +985,16 @@ class LabelInput {
825
985
  const availableWidth = width - indent.length;
826
986
  lines.push(truncateToWidth(`${indent}${theme.fg("muted", "Label (empty to remove):")}`, width));
827
987
  lines.push(...this.input.render(availableWidth).map((line) => truncateToWidth(`${indent}${line}`, width)));
828
- lines.push(truncateToWidth(`${indent}${keyHint("selectConfirm", "save")} ${keyHint("selectCancel", "cancel")}`, width));
988
+ lines.push(truncateToWidth(`${indent}${keyHint("tui.select.confirm", "save")} ${keyHint("tui.select.cancel", "cancel")}`, width));
829
989
  return lines;
830
990
  }
831
991
  handleInput(keyData) {
832
- const kb = getEditorKeybindings();
833
- if (kb.matches(keyData, "selectConfirm")) {
992
+ const kb = getKeybindings();
993
+ if (kb.matches(keyData, "tui.select.confirm")) {
834
994
  const value = this.input.getValue().trim();
835
995
  this.onSubmit?.(this.entryId, value || undefined);
836
996
  }
837
- else if (kb.matches(keyData, "selectCancel")) {
997
+ else if (kb.matches(keyData, "tui.select.cancel")) {
838
998
  this.onCancel?.();
839
999
  }
840
1000
  else {
@@ -846,6 +1006,13 @@ class LabelInput {
846
1006
  * Component that renders a session tree selector for navigation
847
1007
  */
848
1008
  export class TreeSelectorComponent extends Container {
1009
+ treeList;
1010
+ labelInput = null;
1011
+ labelInputContainer;
1012
+ treeContainer;
1013
+ onLabelChangeCallback;
1014
+ // Focusable implementation - propagate to labelInput when active for IME cursor positioning
1015
+ _focused = false;
849
1016
  get focused() {
850
1017
  return this._focused;
851
1018
  }
@@ -858,9 +1025,6 @@ export class TreeSelectorComponent extends Container {
858
1025
  }
859
1026
  constructor(tree, currentLeafId, terminalHeight, onSelect, onCancel, onLabelChange, initialSelectedId, initialFilterMode) {
860
1027
  super();
861
- this.labelInput = null;
862
- // Focusable implementation - propagate to labelInput when active for IME cursor positioning
863
- this._focused = false;
864
1028
  this.onLabelChangeCallback = onLabelChange;
865
1029
  const maxVisibleLines = Math.max(5, Math.floor(terminalHeight / 2));
866
1030
  this.treeList = new TreeList(tree, currentLeafId, maxVisibleLines, initialSelectedId, initialFilterMode);
@@ -873,8 +1037,16 @@ export class TreeSelectorComponent extends Container {
873
1037
  this.addChild(new Spacer(1));
874
1038
  this.addChild(new DynamicBorder());
875
1039
  this.addChild(new Text(theme.bold(" Session Tree"), 1, 0));
876
- this.addChild(new TruncatedText(theme.fg("muted", " ↑/↓: move. ←/→: page. Shift+L: label. ") +
877
- theme.fg("muted", "^D/^T/^U/^L/^A: filters (^O/⇧^O cycle)"), 0, 0));
1040
+ const filterKeys = [
1041
+ keyText("app.tree.filter.default"),
1042
+ keyText("app.tree.filter.noTools"),
1043
+ keyText("app.tree.filter.userOnly"),
1044
+ keyText("app.tree.filter.labeledOnly"),
1045
+ keyText("app.tree.filter.all"),
1046
+ ].join("/");
1047
+ const cycleKeys = `${keyText("app.tree.filter.cycleForward")}/${keyText("app.tree.filter.cycleBackward")}`;
1048
+ const branchKeys = `${keyText("app.tree.foldOrUp")}/${keyText("app.tree.unfoldOrDown")}`;
1049
+ this.addChild(new TruncatedText(theme.fg("muted", ` ↑/↓: move. ←/→: page. ${branchKeys}: fold/branch. ${keyText("app.tree.editLabel")}: label. ${filterKeys}: filters (${cycleKeys} cycle). ${keyText("app.tree.toggleLabelTimestamp")}: label time`), 0, 0));
878
1050
  this.addChild(new SearchLine(this.treeList));
879
1051
  this.addChild(new DynamicBorder());
880
1052
  this.addChild(new Spacer(1));