@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
@@ -76,8 +76,8 @@
76
76
 
77
77
  // Create nodes
78
78
  for (const entry of entries) {
79
- nodeMap.set(entry.id, {
80
- entry,
79
+ nodeMap.set(entry.id, {
80
+ entry,
81
81
  children: [],
82
82
  label: labelMap.get(entry.id)
83
83
  });
@@ -200,7 +200,7 @@
200
200
  const stack = [];
201
201
 
202
202
  // Add roots (prioritize branch containing active leaf)
203
- const orderedRoots = [...roots].sort((a, b) =>
203
+ const orderedRoots = [...roots].sort((a, b) =>
204
204
  Number(containsActive.get(b)) - Number(containsActive.get(a))
205
205
  );
206
206
  for (let i = orderedRoots.length - 1; i >= 0; i--) {
@@ -217,7 +217,7 @@
217
217
  const multipleChildren = children.length > 1;
218
218
 
219
219
  // Order children (active branch first)
220
- const orderedChildren = [...children].sort((a, b) =>
220
+ const orderedChildren = [...children].sort((a, b) =>
221
221
  Number(containsActive.get(b)) - Number(containsActive.get(a))
222
222
  );
223
223
 
@@ -313,6 +313,22 @@
313
313
  return '';
314
314
  }
315
315
 
316
+ /**
317
+ * Parse a skill block from message text.
318
+ * Returns null if the text doesn't contain a skill block.
319
+ * Matches the format: <skill name="..." location="...">\n...\n</skill>\n\nuser message
320
+ */
321
+ function parseSkillBlock(text) {
322
+ const match = text.match(/^<skill name="([^"]+)" location="([^"]+)">\n([\s\S]*?)\n<\/skill>(?:\n\n([\s\S]+))?$/);
323
+ if (!match) return null;
324
+ return {
325
+ name: match[1],
326
+ location: match[2],
327
+ content: match[3],
328
+ userMessage: match[4]?.trim() || undefined,
329
+ };
330
+ }
331
+
316
332
  function getSearchableText(entry, label) {
317
333
  const parts = [];
318
334
  if (label) parts.push(label);
@@ -613,7 +629,16 @@
613
629
  case 'message': {
614
630
  const msg = entry.message;
615
631
  if (msg.role === 'user') {
616
- const content = truncate(normalize(extractContent(msg.content)));
632
+ const rawContent = extractContent(msg.content);
633
+ const skillBlock = parseSkillBlock(rawContent);
634
+ if (skillBlock) {
635
+ let treeHtml = labelHtml + `<span class="tree-role-skill">skill:</span> ${escapeHtml(skillBlock.name)}`;
636
+ if (skillBlock.userMessage) {
637
+ treeHtml += ` · <span class="tree-role-user">user:</span> ${escapeHtml(truncate(normalize(skillBlock.userMessage)))}`;
638
+ }
639
+ return treeHtml;
640
+ }
641
+ const content = truncate(normalize(rawContent));
617
642
  return labelHtml + `<span class="tree-role-user">user:</span> ${escapeHtml(content)}`;
618
643
  }
619
644
  if (msg.role === 'assistant') {
@@ -634,13 +659,13 @@
634
659
  if (toolCall) {
635
660
  return labelHtml + `<span class="tree-role-tool">${escapeHtml(formatToolCall(toolCall.name, toolCall.arguments))}</span>`;
636
661
  }
637
- return labelHtml + `<span class="tree-role-tool">[${msg.toolName || 'tool'}]</span>`;
662
+ return labelHtml + `<span class="tree-role-tool">[${escapeHtml(msg.toolName || 'tool')}]</span>`;
638
663
  }
639
664
  if (msg.role === 'bashExecution') {
640
665
  const cmd = truncate(normalize(msg.command || ''));
641
666
  return labelHtml + `<span class="tree-role-tool">[bash]:</span> ${escapeHtml(cmd)}`;
642
667
  }
643
- return labelHtml + `<span class="tree-muted">[${msg.role}]</span>`;
668
+ return labelHtml + `<span class="tree-muted">[${escapeHtml(msg.role)}]</span>`;
644
669
  }
645
670
  case 'compaction':
646
671
  return labelHtml + `<span class="tree-compaction">[compaction: ${Math.round(entry.tokensBefore/1000)}k tokens]</span>`;
@@ -653,11 +678,11 @@
653
678
  return labelHtml + `<span class="tree-custom">[${escapeHtml(entry.customType)}]:</span> ${escapeHtml(truncate(normalize(content)))}`;
654
679
  }
655
680
  case 'model_change':
656
- return labelHtml + `<span class="tree-muted">[model: ${entry.modelId}]</span>`;
681
+ return labelHtml + `<span class="tree-muted">[model: ${escapeHtml(entry.modelId)}]</span>`;
657
682
  case 'thinking_level_change':
658
- return labelHtml + `<span class="tree-muted">[thinking: ${entry.thinkingLevel}]</span>`;
683
+ return labelHtml + `<span class="tree-muted">[thinking: ${escapeHtml(entry.thinkingLevel)}]</span>`;
659
684
  default:
660
- return labelHtml + `<span class="tree-muted">[${entry.type}]</span>`;
685
+ return labelHtml + `<span class="tree-muted">[${escapeHtml(entry.type)}]</span>`;
661
686
  }
662
687
  }
663
688
 
@@ -709,6 +734,7 @@
709
734
  div.appendChild(content);
710
735
  // Navigate to the newest leaf through this node, but scroll to the clicked node
711
736
  div.addEventListener('click', () => {
737
+ if (window.getSelection().toString()) return;
712
738
  const leafId = findNewestLeaf(entry.id);
713
739
  navigateTo(leafId, 'target', entry.id);
714
740
  });
@@ -827,7 +853,7 @@
827
853
  previewHighlighted = escapeHtml(previewCode);
828
854
  }
829
855
 
830
- return `<div class="tool-output expandable" onclick="this.classList.toggle('expanded')">
856
+ return `<div class="tool-output expandable" onclick="if(window.getSelection().toString())return;this.classList.toggle('expanded')">
831
857
  <div class="output-preview"><pre><code class="hljs">${previewHighlighted}</code></pre>
832
858
  <div class="expand-hint">... (${remaining} more lines)</div></div>
833
859
  <div class="output-full"><pre><code class="hljs">${highlighted}</code></pre></div></div>`;
@@ -838,7 +864,7 @@
838
864
 
839
865
  // Plain text output
840
866
  if (remaining > 0) {
841
- let out = '<div class="tool-output expandable" onclick="this.classList.toggle(\'expanded\')">';
867
+ let out = '<div class="tool-output expandable" onclick="if(window.getSelection().toString())return;this.classList.toggle(\'expanded\')">';
842
868
  out += '<div class="output-preview">';
843
869
  for (const line of displayLines) {
844
870
  out += `<div>${escapeHtml(replaceTabs(line))}</div>`;
@@ -879,8 +905,8 @@
879
905
  const renderResultImages = () => {
880
906
  const images = getResultImages();
881
907
  if (images.length === 0) return '';
882
- return '<div class="tool-images">' +
883
- images.map(img => `<img src="data:${img.mimeType};base64,${img.data}" class="tool-image" />`).join('') +
908
+ return '<div class="tool-images">' +
909
+ images.map(img => `<img src="data:${escapeHtml(img.mimeType || 'image/png')};base64,${escapeHtml(img.data || '')}" class="tool-image" />`).join('') +
884
910
  '</div>';
885
911
  };
886
912
 
@@ -963,31 +989,44 @@
963
989
  }
964
990
  break;
965
991
  }
992
+ case 'ls': {
993
+ const dirPath = str(args.path);
994
+ const limit = args.limit;
995
+
996
+ let pathHtml = dirPath === null ? invalidArg : escapeHtml(shortenPath(dirPath || '.'));
997
+ if (limit !== undefined) {
998
+ pathHtml += ` <span class="line-count">(limit ${escapeHtml(String(limit))})</span>`;
999
+ }
1000
+
1001
+ html += `<div class="tool-header"><span class="tool-name">ls</span> <span class="tool-path">${pathHtml}</span></div>`;
1002
+ if (result) {
1003
+ const output = getResultText().trim();
1004
+ if (output) html += formatExpandableOutput(output, 20);
1005
+ }
1006
+ break;
1007
+ }
966
1008
  default: {
967
1009
  // Check for pre-rendered custom tool HTML
968
1010
  const rendered = renderedTools?.[call.id];
969
- if (rendered?.callHtml || rendered?.resultHtml) {
1011
+ if (rendered?.callHtml || rendered?.resultHtmlCollapsed || rendered?.resultHtmlExpanded) {
970
1012
  // Custom tool with pre-rendered HTML from TUI renderer
971
1013
  if (rendered.callHtml) {
972
1014
  html += `<div class="tool-header ansi-rendered">${rendered.callHtml}</div>`;
973
1015
  } else {
974
1016
  html += `<div class="tool-header"><span class="tool-name">${escapeHtml(name)}</span></div>`;
975
1017
  }
976
-
977
- if (rendered.resultHtml) {
978
- // Apply same truncation as built-in tools (10 lines)
979
- const lines = rendered.resultHtml.split('\n');
980
- if (lines.length > 10) {
981
- const preview = lines.slice(0, 10).join('\n');
982
- html += `<div class="tool-output expandable ansi-rendered" onclick="this.classList.toggle('expanded')">
983
- <div class="output-preview">${preview}<div class="expand-hint">... (${lines.length - 10} more lines)</div></div>
984
- <div class="output-full">${rendered.resultHtml}</div>
985
- </div>`;
986
- } else {
987
- html += `<div class="tool-output ansi-rendered">${rendered.resultHtml}</div>`;
988
- }
1018
+
1019
+ if (rendered.resultHtmlCollapsed && rendered.resultHtmlExpanded && rendered.resultHtmlCollapsed !== rendered.resultHtmlExpanded) {
1020
+ // Both collapsed and expanded differ - render expandable section
1021
+ html += `<div class="tool-output expandable ansi-rendered" onclick="if(window.getSelection().toString())return;this.classList.toggle('expanded')">
1022
+ <div class="output-preview">${rendered.resultHtmlCollapsed}</div>
1023
+ <div class="output-full">${rendered.resultHtmlExpanded}</div>
1024
+ </div>`;
1025
+ } else if (rendered.resultHtmlExpanded) {
1026
+ // Only expanded exists (or collapsed is identical) - show directly
1027
+ html += `<div class="tool-output ansi-rendered">${rendered.resultHtmlExpanded}</div>`;
989
1028
  } else if (result) {
990
- // Fallback to JSON for result if no pre-rendered HTML
1029
+ // No pre-rendered result HTML - fallback to JSON
991
1030
  const output = getResultText();
992
1031
  if (output) html += formatExpandableOutput(output, 10);
993
1032
  }
@@ -1042,21 +1081,21 @@
1042
1081
  // Check for injected base URL (used when loaded in iframe via srcdoc)
1043
1082
  const baseUrlMeta = document.querySelector('meta[name="pi-share-base-url"]');
1044
1083
  const baseUrl = baseUrlMeta ? baseUrlMeta.content : window.location.href.split('?')[0];
1045
-
1084
+
1046
1085
  const url = new URL(window.location.href);
1047
1086
  // Find the gist ID (first query param without value, e.g., ?abc123)
1048
1087
  const gistId = Array.from(url.searchParams.keys()).find(k => !url.searchParams.get(k));
1049
-
1088
+
1050
1089
  // Build the share URL
1051
1090
  const params = new URLSearchParams();
1052
1091
  params.set('leafId', currentLeafId);
1053
1092
  params.set('targetId', entryId);
1054
-
1093
+
1055
1094
  // If we have an injected base URL (iframe context), use it directly
1056
1095
  if (baseUrlMeta) {
1057
1096
  return `${baseUrl}&${params.toString()}`;
1058
1097
  }
1059
-
1098
+
1060
1099
  // Otherwise build from current location (direct file access)
1061
1100
  url.search = gistId ? `?${gistId}&${params.toString()}` : `?${params.toString()}`;
1062
1101
  return url.toString();
@@ -1076,7 +1115,7 @@
1076
1115
  } catch (err) {
1077
1116
  // Clipboard API failed, try fallback
1078
1117
  }
1079
-
1118
+
1080
1119
  // Fallback for HTTP or when Clipboard API is unavailable
1081
1120
  if (!success) {
1082
1121
  try {
@@ -1092,7 +1131,7 @@
1092
1131
  console.error('Failed to copy:', err);
1093
1132
  }
1094
1133
  }
1095
-
1134
+
1096
1135
  if (success && button) {
1097
1136
  const originalHtml = button.innerHTML;
1098
1137
  button.innerHTML = '✓';
@@ -1108,7 +1147,7 @@
1108
1147
  * Render the copy-link button HTML for a message.
1109
1148
  */
1110
1149
  function renderCopyLinkButton(entryId) {
1111
- return `<button class="copy-link-btn" data-entry-id="${entryId}" title="Copy link to this message">
1150
+ return `<button class="copy-link-btn" data-entry-id="${escapeHtml(entryId)}" title="Copy link to this message">
1112
1151
  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
1113
1152
  <path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/>
1114
1153
  <path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/>
@@ -1119,29 +1158,65 @@
1119
1158
  function renderEntry(entry) {
1120
1159
  const ts = formatTimestamp(entry.timestamp);
1121
1160
  const tsHtml = ts ? `<div class="message-timestamp">${ts}</div>` : '';
1122
- const entryId = `entry-${entry.id}`;
1161
+ const entryDomId = `entry-${escapeHtml(entry.id)}`;
1123
1162
  const copyBtnHtml = renderCopyLinkButton(entry.id);
1124
1163
 
1125
1164
  if (entry.type === 'message') {
1126
1165
  const msg = entry.message;
1127
1166
 
1128
1167
  if (msg.role === 'user') {
1129
- let html = `<div class="user-message" id="${entryId}">${copyBtnHtml}${tsHtml}`;
1130
1168
  const content = msg.content;
1169
+ const text = typeof content === 'string' ? content :
1170
+ content.filter(c => c.type === 'text').map(c => c.text).join('\n');
1171
+ const skillBlock = parseSkillBlock(text);
1172
+
1173
+ if (skillBlock) {
1174
+ // Collect images from content array
1175
+ const images = Array.isArray(content) ? content.filter(c => c.type === 'image') : [];
1176
+ const hasUserContent = skillBlock.userMessage || images.length > 0;
1177
+ let html = `<div class="skill-user-entry" id="${entryDomId}">${copyBtnHtml}${tsHtml}`;
1178
+
1179
+ // Skill invocation (collapsed by default, click to expand)
1180
+ html += `<div class="skill-invocation" onclick="if(window.getSelection().toString())return;this.classList.toggle('expanded')">
1181
+ <div class="skill-invocation-label">[skill] ${escapeHtml(skillBlock.name)}</div>
1182
+ <div class="skill-invocation-collapsed">${escapeHtml(skillBlock.name)} (click to expand)</div>
1183
+ <div class="skill-invocation-content markdown-content">${safeMarkedParse(skillBlock.content)}</div>
1184
+ </div>`;
1185
+
1186
+ // User message (separate block if present)
1187
+ if (hasUserContent) {
1188
+ html += '<div class="user-message">';
1189
+ if (images.length > 0) {
1190
+ html += '<div class="message-images">';
1191
+ for (const img of images) {
1192
+ html += `<img src="data:${escapeHtml(img.mimeType || 'image/png')};base64,${escapeHtml(img.data || '')}" class="message-image" />`;
1193
+ }
1194
+ html += '</div>';
1195
+ }
1196
+ if (skillBlock.userMessage) {
1197
+ html += `<div class="markdown-content">${safeMarkedParse(skillBlock.userMessage)}</div>`;
1198
+ }
1199
+ html += '</div>';
1200
+ }
1201
+
1202
+ html += '</div>';
1203
+ return html;
1204
+ }
1205
+
1206
+ // No skill block - normal user message
1207
+ let html = `<div class="user-message" id="${entryDomId}">${copyBtnHtml}${tsHtml}`;
1131
1208
 
1132
1209
  if (Array.isArray(content)) {
1133
1210
  const images = content.filter(c => c.type === 'image');
1134
1211
  if (images.length > 0) {
1135
1212
  html += '<div class="message-images">';
1136
1213
  for (const img of images) {
1137
- html += `<img src="data:${img.mimeType};base64,${img.data}" class="message-image" />`;
1214
+ html += `<img src="data:${escapeHtml(img.mimeType || 'image/png')};base64,${escapeHtml(img.data || '')}" class="message-image" />`;
1138
1215
  }
1139
1216
  html += '</div>';
1140
1217
  }
1141
1218
  }
1142
1219
 
1143
- const text = typeof content === 'string' ? content :
1144
- content.filter(c => c.type === 'text').map(c => c.text).join('\n');
1145
1220
  if (text.trim()) {
1146
1221
  html += `<div class="markdown-content">${safeMarkedParse(text)}</div>`;
1147
1222
  }
@@ -1150,7 +1225,7 @@
1150
1225
  }
1151
1226
 
1152
1227
  if (msg.role === 'assistant') {
1153
- let html = `<div class="assistant-message" id="${entryId}">${copyBtnHtml}${tsHtml}`;
1228
+ let html = `<div class="assistant-message" id="${entryDomId}">${copyBtnHtml}${tsHtml}`;
1154
1229
 
1155
1230
  for (const block of msg.content) {
1156
1231
  if (block.type === 'text' && block.text.trim()) {
@@ -1181,7 +1256,7 @@
1181
1256
 
1182
1257
  if (msg.role === 'bashExecution') {
1183
1258
  const isError = msg.cancelled || (msg.exitCode !== 0 && msg.exitCode !== null);
1184
- let html = `<div class="tool-execution ${isError ? 'error' : 'success'}" id="${entryId}">${tsHtml}`;
1259
+ let html = `<div class="tool-execution ${isError ? 'error' : 'success'}" id="${entryDomId}">${tsHtml}`;
1185
1260
  html += `<div class="tool-command">$ ${escapeHtml(msg.command)}</div>`;
1186
1261
  if (msg.output) html += formatExpandableOutput(msg.output, 10);
1187
1262
  if (msg.cancelled) {
@@ -1197,11 +1272,11 @@
1197
1272
  }
1198
1273
 
1199
1274
  if (entry.type === 'model_change') {
1200
- return `<div class="model-change" id="${entryId}">${tsHtml}Switched to model: <span class="model-name">${escapeHtml(entry.provider)}/${escapeHtml(entry.modelId)}</span></div>`;
1275
+ return `<div class="model-change" id="${entryDomId}">${tsHtml}Switched to model: <span class="model-name">${escapeHtml(entry.provider)}/${escapeHtml(entry.modelId)}</span></div>`;
1201
1276
  }
1202
1277
 
1203
1278
  if (entry.type === 'compaction') {
1204
- return `<div class="compaction" id="${entryId}" onclick="this.classList.toggle('expanded')">
1279
+ return `<div class="compaction" id="${entryDomId}" onclick="if(window.getSelection().toString())return;this.classList.toggle('expanded')">
1205
1280
  <div class="compaction-label">[compaction]</div>
1206
1281
  <div class="compaction-collapsed">Compacted from ${entry.tokensBefore.toLocaleString()} tokens</div>
1207
1282
  <div class="compaction-content"><strong>Compacted from ${entry.tokensBefore.toLocaleString()} tokens</strong>\n\n${escapeHtml(entry.summary)}</div>
@@ -1209,14 +1284,14 @@
1209
1284
  }
1210
1285
 
1211
1286
  if (entry.type === 'branch_summary') {
1212
- return `<div class="branch-summary" id="${entryId}">${tsHtml}
1287
+ return `<div class="branch-summary" id="${entryDomId}">${tsHtml}
1213
1288
  <div class="branch-summary-header">Branch Summary</div>
1214
1289
  <div class="markdown-content">${safeMarkedParse(entry.summary)}</div>
1215
1290
  </div>`;
1216
1291
  }
1217
1292
 
1218
1293
  if (entry.type === 'custom_message' && entry.display) {
1219
- return `<div class="hook-message" id="${entryId}">${tsHtml}
1294
+ return `<div class="hook-message" id="${entryDomId}">${tsHtml}
1220
1295
  <div class="hook-type">[${escapeHtml(entry.customType)}]</div>
1221
1296
  <div class="markdown-content">${safeMarkedParse(typeof entry.content === 'string' ? entry.content : JSON.stringify(entry.content))}</div>
1222
1297
  </div>`;
@@ -1293,12 +1368,16 @@
1293
1368
  <div class="header">
1294
1369
  <h1>Session: ${escapeHtml(header?.id || 'unknown')}</h1>
1295
1370
  <div class="help-bar">
1296
- <span>Ctrl+T toggle thinking · Ctrl+O toggle tools</span>
1297
- <button class="download-json-btn" onclick="downloadSessionJson()" title="Download session as JSONL">↓ JSONL</button>
1371
+ <span class="help-hint">T toggle thinking · O toggle tools</span>
1372
+ <div class="help-actions">
1373
+ <button type="button" class="header-toggle-btn" data-action="toggle-thinking" title="Toggle thinking (T)">Toggle thinking</button>
1374
+ <button type="button" class="header-toggle-btn" data-action="toggle-tools" title="Toggle tools (O)">Toggle tools</button>
1375
+ <button type="button" class="download-json-btn" onclick="downloadSessionJson()" title="Download session as JSONL">↓ JSONL</button>
1376
+ </div>
1298
1377
  </div>
1299
1378
  <div class="header-info">
1300
1379
  <div class="info-item"><span class="info-label">Date:</span><span class="info-value">${header?.timestamp ? new Date(header.timestamp).toLocaleString() : 'unknown'}</span></div>
1301
- <div class="info-item"><span class="info-label">Models:</span><span class="info-value">${globalStats.models.join(', ') || 'unknown'}</span></div>
1380
+ <div class="info-item"><span class="info-label">Models:</span><span class="info-value">${escapeHtml(globalStats.models.join(', ') || 'unknown')}</span></div>
1302
1381
  <div class="info-item"><span class="info-label">Messages:</span><span class="info-value">${msgParts.join(', ') || '0'}</span></div>
1303
1382
  <div class="info-item"><span class="info-label">Tool Calls:</span><span class="info-value">${globalStats.toolCalls}</span></div>
1304
1383
  <div class="info-item"><span class="info-label">Tokens:</span><span class="info-value">${tokenParts.join(' ') || '0'}</span></div>
@@ -1313,7 +1392,7 @@
1313
1392
  if (lines.length > previewLines) {
1314
1393
  const preview = lines.slice(0, previewLines).join('\n');
1315
1394
  const remaining = lines.length - previewLines;
1316
- html += `<div class="system-prompt expandable" onclick="this.classList.toggle('expanded')">
1395
+ html += `<div class="system-prompt expandable" onclick="if(window.getSelection().toString())return;this.classList.toggle('expanded')">
1317
1396
  <div class="system-prompt-header">System Prompt</div>
1318
1397
  <div class="system-prompt-preview">${escapeHtml(preview)}</div>
1319
1398
  <div class="system-prompt-expand-hint">... (${remaining} more lines, click to expand)</div>
@@ -1350,7 +1429,7 @@
1350
1429
  }
1351
1430
  paramsHtml += `</div>`;
1352
1431
  }
1353
- return `<div class="tool-item" onclick="this.classList.toggle('params-expanded')"><span class="tool-item-name">${escapeHtml(t.name)}</span> - <span class="tool-item-desc">${escapeHtml(t.description)}</span> <span class="tool-params-hint"></span><div class="tool-params-content">${paramsHtml}</div></div>`;
1432
+ return `<div class="tool-item" onclick="if(window.getSelection().toString())return;this.classList.toggle('params-expanded')"><span class="tool-item-name">${escapeHtml(t.name)}</span> - <span class="tool-item-desc">${escapeHtml(t.description)}</span> <span class="tool-params-hint"></span><div class="tool-params-content">${paramsHtml}</div></div>`;
1354
1433
  }).join('')}
1355
1434
  </div>
1356
1435
  </div>`;
@@ -1395,6 +1474,7 @@
1395
1474
  renderTree();
1396
1475
 
1397
1476
  document.getElementById('header-container').innerHTML = renderHeader();
1477
+ attachHeaderHandlers();
1398
1478
 
1399
1479
  // Build messages using cached DOM nodes
1400
1480
  const messagesEl = document.getElementById('messages');
@@ -1445,16 +1525,59 @@
1445
1525
  // INITIALIZATION
1446
1526
  // ============================================================
1447
1527
 
1448
- // Escape HTML tags in text (but not code blocks)
1449
- function escapeHtmlTags(text) {
1450
- return text.replace(/<(?=[a-zA-Z\/])/g, '&lt;');
1451
- }
1528
+ // Configure marked with syntax highlighting and TUI-compatible HTML handling
1529
+ const strictStrikethroughRegex = /^(~~)(?=[^\s~])((?:\\.|[^\\])*?(?:\\.|[^\s~\\]))\1(?=[^~]|$)/;
1452
1530
 
1453
- // Configure marked with syntax highlighting and HTML escaping for text
1454
1531
  marked.use({
1455
1532
  breaks: true,
1456
1533
  gfm: true,
1534
+ tokenizer: {
1535
+ // Treat HTML-like input as plain text so tags are shown verbatim,
1536
+ // matching the TUI markdown renderer.
1537
+ html() {
1538
+ return undefined;
1539
+ },
1540
+ tag() {
1541
+ return undefined;
1542
+ },
1543
+ del(src) {
1544
+ const match = strictStrikethroughRegex.exec(src);
1545
+ if (!match) return undefined;
1546
+ return {
1547
+ type: 'del',
1548
+ raw: match[0],
1549
+ text: match[2],
1550
+ tokens: this.lexer.inlineTokens(match[2])
1551
+ };
1552
+ }
1553
+ },
1457
1554
  renderer: {
1555
+ // Sanitize link URLs to prevent javascript:/vbscript:/data: XSS
1556
+ link(token) {
1557
+ const href = (token.href || '').trim();
1558
+ if (/^\s*(javascript|vbscript|data):/i.test(href)) {
1559
+ return this.parser.parseInline(token.tokens);
1560
+ }
1561
+ let out = '<a href="' + escapeHtml(href) + '"';
1562
+ if (token.title) {
1563
+ out += ' title="' + escapeHtml(token.title) + '"';
1564
+ }
1565
+ out += '>' + this.parser.parseInline(token.tokens) + '</a>';
1566
+ return out;
1567
+ },
1568
+ // Sanitize image src URLs
1569
+ image(token) {
1570
+ const href = (token.href || '').trim();
1571
+ if (/^\s*(javascript|vbscript|data):/i.test(href)) {
1572
+ return escapeHtml(token.text || '');
1573
+ }
1574
+ let out = '<img src="' + escapeHtml(href) + '" alt="' + escapeHtml(token.text || '') + '"';
1575
+ if (token.title) {
1576
+ out += ' title="' + escapeHtml(token.title) + '"';
1577
+ }
1578
+ out += '>';
1579
+ return out;
1580
+ },
1458
1581
  // Code blocks: syntax highlight, no HTML escaping
1459
1582
  code(token) {
1460
1583
  const code = token.text;
@@ -1476,10 +1599,6 @@
1476
1599
  }
1477
1600
  return `<pre><code class="hljs">${highlighted}</code></pre>`;
1478
1601
  },
1479
- // Text content: escape HTML tags
1480
- text(token) {
1481
- return escapeHtmlTags(escapeHtml(token.text));
1482
- },
1483
1602
  // Inline code: escape HTML
1484
1603
  codespan(token) {
1485
1604
  return `<code>${escapeHtml(token.text)}</code>`;
@@ -1513,6 +1632,113 @@
1513
1632
  const sidebar = document.getElementById('sidebar');
1514
1633
  const overlay = document.getElementById('sidebar-overlay');
1515
1634
  const hamburger = document.getElementById('hamburger');
1635
+ const sidebarResizer = document.getElementById('sidebar-resizer');
1636
+ const SIDEBAR_WIDTH_STORAGE_KEY = 'pi-share:v1:sidebar-width';
1637
+ const MIN_CONTENT_WIDTH = 320;
1638
+
1639
+ function isMobileLayout() {
1640
+ return window.matchMedia('(max-width: 900px)').matches;
1641
+ }
1642
+
1643
+ function getSidebarBounds() {
1644
+ const rootStyles = getComputedStyle(document.documentElement);
1645
+ const minWidth = parseFloat(rootStyles.getPropertyValue('--sidebar-min-width')) || 240;
1646
+ const maxWidth = parseFloat(rootStyles.getPropertyValue('--sidebar-max-width')) || 720;
1647
+ const viewportMaxWidth = window.innerWidth - MIN_CONTENT_WIDTH;
1648
+ return {
1649
+ minWidth,
1650
+ maxWidth: Math.max(minWidth, Math.min(maxWidth, viewportMaxWidth))
1651
+ };
1652
+ }
1653
+
1654
+ function clampSidebarWidth(width) {
1655
+ const { minWidth, maxWidth } = getSidebarBounds();
1656
+ return Math.max(minWidth, Math.min(maxWidth, width));
1657
+ }
1658
+
1659
+ function applySidebarWidth(width) {
1660
+ document.documentElement.style.setProperty('--sidebar-width', `${Math.round(clampSidebarWidth(width))}px`);
1661
+ }
1662
+
1663
+ function loadSidebarWidth() {
1664
+ try {
1665
+ const raw = localStorage.getItem(SIDEBAR_WIDTH_STORAGE_KEY);
1666
+ if (raw === null) return null;
1667
+ const width = Number(raw);
1668
+ return Number.isFinite(width) ? width : null;
1669
+ } catch {
1670
+ return null;
1671
+ }
1672
+ }
1673
+
1674
+ function saveSidebarWidth(width) {
1675
+ try {
1676
+ localStorage.setItem(SIDEBAR_WIDTH_STORAGE_KEY, String(Math.round(clampSidebarWidth(width))));
1677
+ } catch {
1678
+ // Ignore storage failures (e.g. private browsing restrictions)
1679
+ }
1680
+ }
1681
+
1682
+ function setupSidebarResize() {
1683
+ const savedWidth = loadSidebarWidth();
1684
+ if (savedWidth !== null) {
1685
+ applySidebarWidth(savedWidth);
1686
+ }
1687
+
1688
+ if (!sidebarResizer) return;
1689
+
1690
+ let cleanupDrag = null;
1691
+
1692
+ const stopDrag = (pointerId) => {
1693
+ if (cleanupDrag) {
1694
+ cleanupDrag(pointerId);
1695
+ cleanupDrag = null;
1696
+ }
1697
+ };
1698
+
1699
+ sidebarResizer.addEventListener('pointerdown', (e) => {
1700
+ if (isMobileLayout()) return;
1701
+
1702
+ e.preventDefault();
1703
+ const startX = e.clientX;
1704
+ const startWidth = sidebar.getBoundingClientRect().width;
1705
+ document.body.classList.add('sidebar-resizing');
1706
+ sidebarResizer.setPointerCapture?.(e.pointerId);
1707
+
1708
+ const onPointerMove = (event) => {
1709
+ applySidebarWidth(startWidth + (event.clientX - startX));
1710
+ };
1711
+
1712
+ cleanupDrag = (pointerIdToRelease) => {
1713
+ document.body.classList.remove('sidebar-resizing');
1714
+ sidebarResizer.releasePointerCapture?.(pointerIdToRelease);
1715
+ window.removeEventListener('pointermove', onPointerMove);
1716
+ window.removeEventListener('pointerup', onPointerUp);
1717
+ window.removeEventListener('pointercancel', onPointerCancel);
1718
+ saveSidebarWidth(sidebar.getBoundingClientRect().width);
1719
+ };
1720
+
1721
+ const onPointerUp = (event) => stopDrag(event.pointerId);
1722
+ const onPointerCancel = (event) => stopDrag(event.pointerId);
1723
+
1724
+ window.addEventListener('pointermove', onPointerMove);
1725
+ window.addEventListener('pointerup', onPointerUp);
1726
+ window.addEventListener('pointercancel', onPointerCancel);
1727
+ });
1728
+
1729
+ sidebarResizer.addEventListener('dblclick', () => {
1730
+ if (isMobileLayout()) return;
1731
+ applySidebarWidth(400);
1732
+ saveSidebarWidth(400);
1733
+ });
1734
+
1735
+ window.addEventListener('resize', () => {
1736
+ if (isMobileLayout()) return;
1737
+ applySidebarWidth(sidebar.getBoundingClientRect().width);
1738
+ });
1739
+ }
1740
+
1741
+ setupSidebarResize();
1516
1742
 
1517
1743
  hamburger.addEventListener('click', () => {
1518
1744
  sidebar.classList.add('open');
@@ -1551,6 +1777,23 @@
1551
1777
  document.querySelectorAll('.compaction').forEach(el => {
1552
1778
  el.classList.toggle('expanded', toolOutputsExpanded);
1553
1779
  });
1780
+ document.querySelectorAll('.skill-invocation').forEach(el => {
1781
+ el.classList.toggle('expanded', toolOutputsExpanded);
1782
+ });
1783
+ };
1784
+
1785
+ const attachHeaderHandlers = () => {
1786
+ document.querySelector('[data-action="toggle-thinking"]')?.addEventListener('click', toggleThinking);
1787
+ document.querySelector('[data-action="toggle-tools"]')?.addEventListener('click', toggleToolOutputs);
1788
+ };
1789
+
1790
+ const isEditableTarget = (element) => {
1791
+ if (!element) return false;
1792
+ const tagName = element.tagName;
1793
+ if (tagName === 'INPUT' || tagName === 'TEXTAREA' || tagName === 'SELECT' || tagName === 'BUTTON') {
1794
+ return true;
1795
+ }
1796
+ return element.isContentEditable || Boolean(element.closest?.('[contenteditable="true"]'));
1554
1797
  };
1555
1798
 
1556
1799
  // Keyboard shortcuts
@@ -1560,11 +1803,16 @@
1560
1803
  searchQuery = '';
1561
1804
  navigateTo(leafId, 'bottom');
1562
1805
  }
1563
- if (e.ctrlKey && e.key === 't') {
1806
+
1807
+ if (isEditableTarget(document.activeElement)) {
1808
+ return;
1809
+ }
1810
+
1811
+ const key = e.key.toLowerCase();
1812
+ if (key === 't') {
1564
1813
  e.preventDefault();
1565
1814
  toggleThinking();
1566
- }
1567
- if (e.ctrlKey && e.key === 'o') {
1815
+ } else if (key === 'o') {
1568
1816
  e.preventDefault();
1569
1817
  toggleToolOutputs();
1570
1818
  }