@selesai/code 0.10.2 → 0.12.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 (531) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/dist/cli/credential-print.js +4 -4
  3. package/dist/cli/startup-ui.js +2 -1
  4. package/dist/cli.js +0 -0
  5. package/dist/core/agent-session.d.ts +12 -1
  6. package/dist/core/agent-session.js +77 -9
  7. package/dist/core/compaction/branch-summarization.js +34 -33
  8. package/dist/core/compaction/compaction.d.ts +5 -0
  9. package/dist/core/compaction/compaction.js +100 -85
  10. package/dist/core/compaction/utils.js +2 -2
  11. package/dist/core/export-html/template.css +1066 -1066
  12. package/dist/core/export-html/template.html +55 -55
  13. package/dist/core/export-html/template.js +1864 -1864
  14. package/dist/core/export-html/vendor/highlight.min.js +1212 -1212
  15. package/dist/core/export-html/vendor/marked.min.js +78 -78
  16. package/dist/core/extensions/index.d.ts +1 -1
  17. package/dist/core/extensions/runner.d.ts +5 -0
  18. package/dist/core/extensions/runner.js +48 -1
  19. package/dist/core/extensions/types.d.ts +18 -1
  20. package/dist/core/llama/client.d.ts +6 -0
  21. package/dist/core/llama/client.js +7 -0
  22. package/dist/core/llama/provider.d.ts +3 -1
  23. package/dist/core/llama/provider.js +28 -6
  24. package/dist/core/messages.js +7 -7
  25. package/dist/core/session-manager.js +4 -2
  26. package/dist/core/settings-manager.d.ts +8 -1
  27. package/dist/core/settings-manager.js +17 -0
  28. package/dist/defaults/models.json +32 -9
  29. package/dist/defaults/settings.json +0 -3
  30. package/dist/extensions/auto-session-name.test.ts +157 -0
  31. package/dist/extensions/auto-session-name.ts +96 -0
  32. package/dist/extensions/context-compaction-reminder.test.ts +82 -82
  33. package/dist/extensions/context-compaction-reminder.ts +28 -28
  34. package/dist/extensions/cost-reconcile.test.ts +76 -0
  35. package/dist/extensions/cost-reconcile.ts +278 -0
  36. package/dist/extensions/enable-readonly-tools.test.ts +11 -0
  37. package/dist/extensions/enable-readonly-tools.ts +7 -3
  38. package/dist/extensions/package.json +3 -0
  39. package/dist/extensions/pi-intercom/LICENSE +21 -21
  40. package/dist/extensions/pi-intercom/broker/client.test.ts +83 -83
  41. package/dist/extensions/pi-intercom/broker/framing.test.ts +114 -114
  42. package/dist/extensions/pi-intercom/broker/paths.ts +134 -134
  43. package/dist/extensions/pi-intercom/broker/runtime-claim.test.ts +34 -34
  44. package/dist/extensions/pi-intercom/broker/runtime-claim.ts +21 -21
  45. package/dist/extensions/pi-intercom/cwd.test.ts +40 -40
  46. package/dist/extensions/pi-intercom/cwd.ts +31 -31
  47. package/dist/extensions/pi-intercom/format-context.test.ts +31 -31
  48. package/dist/extensions/pi-intercom/format-context.ts +32 -32
  49. package/dist/extensions/pi-intercom/test/overlay-width.test.ts +66 -66
  50. package/dist/extensions/pi-intercom/ui/compose.ts +143 -143
  51. package/dist/extensions/pi-intercom/ui/session-list.ts +166 -166
  52. package/dist/extensions/pi-rewind-hook/README.md +245 -245
  53. package/dist/extensions/pi-rewind-hook/index.ts +1445 -1445
  54. package/dist/extensions/pi-rewind-hook/package.json +29 -29
  55. package/dist/extensions/pi-subagents/install.mjs +0 -0
  56. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/bun/cli.d.ts +3 -0
  57. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/bun/register-bedrock.d.ts +2 -0
  58. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/bun/restore-sandbox-env.d.ts +17 -0
  59. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/args.d.ts +57 -0
  60. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/config-selector.d.ts +16 -0
  61. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/file-processor.d.ts +15 -0
  62. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/initial-message.d.ts +18 -0
  63. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/list-models.d.ts +9 -0
  64. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/project-trust.d.ts +10 -0
  65. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/session-picker.d.ts +10 -0
  66. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/startup-ui.d.ts +20 -0
  67. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli.d.ts +3 -0
  68. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/config.d.ts +96 -0
  69. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/agent-session-runtime.d.ts +119 -0
  70. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/agent-session-services.d.ts +85 -0
  71. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/agent-session.d.ts +620 -0
  72. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/auth-guidance.d.ts +5 -0
  73. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/auth-storage.d.ts +56 -0
  74. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/bash-executor.d.ts +32 -0
  75. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/cache-stats.d.ts +49 -0
  76. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/branch-summarization.d.ts +93 -0
  77. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/compaction.d.ts +128 -0
  78. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/index.d.ts +7 -0
  79. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/utils.d.ts +38 -0
  80. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/defaults.d.ts +3 -0
  81. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/diagnostics.d.ts +15 -0
  82. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/event-bus.d.ts +9 -0
  83. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/exec.d.ts +29 -0
  84. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/experimental.d.ts +2 -0
  85. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/export-html/ansi-to-html.d.ts +22 -0
  86. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/export-html/index.d.ts +37 -0
  87. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/export-html/tool-renderer.d.ts +34 -0
  88. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/index.d.ts +12 -0
  89. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/loader.d.ts +23 -0
  90. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/runner.d.ts +171 -0
  91. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/types.d.ts +1261 -0
  92. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/wrapper.d.ts +20 -0
  93. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/footer-data-provider.d.ts +54 -0
  94. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/http-dispatcher.d.ts +22 -0
  95. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/index.d.ts +13 -0
  96. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/keybindings.d.ts +358 -0
  97. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/messages.d.ts +77 -0
  98. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-config.d.ts +512 -0
  99. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-registry.d.ts +43 -0
  100. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-resolver.d.ts +121 -0
  101. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-runtime.d.ts +82 -0
  102. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/models-store.d.ts +17 -0
  103. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/output-guard.d.ts +7 -0
  104. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/package-manager.d.ts +210 -0
  105. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/project-trust.d.ts +15 -0
  106. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/prompt-templates.d.ts +54 -0
  107. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/provider-attribution.d.ts +4 -0
  108. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/provider-composer.d.ts +55 -0
  109. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/radius.d.ts +2 -0
  110. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/remote-catalog-provider.d.ts +5 -0
  111. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/resolve-config-value.d.ts +30 -0
  112. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/resource-loader.d.ts +206 -0
  113. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/runtime-credentials.d.ts +15 -0
  114. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/sdk.d.ts +106 -0
  115. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/session-cwd.d.ts +19 -0
  116. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/session-manager.d.ts +356 -0
  117. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/settings-manager.d.ts +297 -0
  118. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/skills.d.ts +60 -0
  119. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/slash-commands.d.ts +15 -0
  120. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/source-info.d.ts +18 -0
  121. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/system-prompt.d.ts +28 -0
  122. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/telemetry.d.ts +3 -0
  123. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/timings.d.ts +10 -0
  124. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/bash.d.ts +68 -0
  125. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/edit-diff.d.ts +106 -0
  126. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/edit.d.ts +51 -0
  127. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/file-mutation-queue.d.ts +6 -0
  128. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/find.d.ts +35 -0
  129. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/grep.d.ts +37 -0
  130. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/index.d.ts +40 -0
  131. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/ls.d.ts +37 -0
  132. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/output-accumulator.d.ts +52 -0
  133. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/path-utils.d.ts +10 -0
  134. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/read.d.ts +35 -0
  135. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/render-utils.d.ts +24 -0
  136. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/tool-definition-wrapper.d.ts +14 -0
  137. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/truncate.d.ts +70 -0
  138. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/write.d.ts +26 -0
  139. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/trust-manager.d.ts +36 -0
  140. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/usage-totals.d.ts +19 -0
  141. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/index.d.ts +3 -0
  142. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/client.d.ts +61 -0
  143. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/huggingface.d.ts +23 -0
  144. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/index.d.ts +3 -0
  145. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/provider.d.ts +10 -0
  146. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/ui.d.ts +42 -0
  147. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/index.d.ts +35 -0
  148. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/main.d.ts +12 -0
  149. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/migrations.d.ts +33 -0
  150. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/index.d.ts +9 -0
  151. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/armin.d.ts +34 -0
  152. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/assistant-message.d.ts +22 -0
  153. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/bash-execution.d.ts +34 -0
  154. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/bordered-loader.d.ts +16 -0
  155. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/branch-summary-message.d.ts +16 -0
  156. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/compaction-summary-message.d.ts +16 -0
  157. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/config-selector.d.ts +102 -0
  158. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/countdown-timer.d.ts +14 -0
  159. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/custom-editor.d.ts +21 -0
  160. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/custom-entry.d.ts +19 -0
  161. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/custom-message.d.ts +20 -0
  162. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/daxnuts.d.ts +23 -0
  163. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/diff.d.ts +12 -0
  164. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/dynamic-border.d.ts +15 -0
  165. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/earendil-announcement.d.ts +5 -0
  166. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/extension-editor.d.ts +22 -0
  167. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/extension-input.d.ts +23 -0
  168. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/extension-selector.d.ts +26 -0
  169. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/first-time-setup.d.ts +25 -0
  170. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/footer.d.ts +32 -0
  171. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/index.d.ts +34 -0
  172. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/keybinding-hints.d.ts +13 -0
  173. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/login-dialog.d.ts +52 -0
  174. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/model-selector.d.ts +54 -0
  175. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/oauth-selector.d.ts +33 -0
  176. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/scoped-models-selector.d.ts +42 -0
  177. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/session-selector-search.d.ts +23 -0
  178. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/session-selector.d.ts +95 -0
  179. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/settings-selector.d.ts +77 -0
  180. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/show-images-selector.d.ts +10 -0
  181. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/skill-invocation-message.d.ts +17 -0
  182. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/status-indicator.d.ts +28 -0
  183. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/theme-selector.d.ts +11 -0
  184. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/thinking-selector.d.ts +11 -0
  185. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/tool-execution.d.ts +63 -0
  186. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/tree-selector.d.ts +94 -0
  187. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/trust-selector.d.ts +23 -0
  188. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/user-message-selector.d.ts +30 -0
  189. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/user-message.d.ts +14 -0
  190. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/visual-truncate.d.ts +24 -0
  191. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/interactive-mode.d.ts +394 -0
  192. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/model-search.d.ts +12 -0
  193. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/theme/theme-controller.d.ts +29 -0
  194. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/theme/theme.d.ts +120 -0
  195. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/print-mode.d.ts +28 -0
  196. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/jsonl.d.ts +17 -0
  197. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/rpc-client.d.ts +246 -0
  198. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/rpc-mode.d.ts +20 -0
  199. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/rpc-types.d.ts +457 -0
  200. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/package-manager-cli.d.ts +8 -0
  201. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/rpc-entry.d.ts +3 -0
  202. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/ansi.d.ts +2 -0
  203. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/changelog.d.ts +22 -0
  204. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/child-process.d.ts +18 -0
  205. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/clipboard-image.d.ts +11 -0
  206. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/clipboard-native.d.ts +11 -0
  207. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/clipboard.d.ts +4 -0
  208. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/deprecation.d.ts +4 -0
  209. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/exif-orientation.d.ts +5 -0
  210. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/frontmatter.d.ts +8 -0
  211. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/fs-watch.d.ts +5 -0
  212. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/git.d.ts +26 -0
  213. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/html.d.ts +7 -0
  214. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-convert.d.ts +10 -0
  215. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-process.d.ts +18 -0
  216. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-resize-core.d.ts +30 -0
  217. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-resize-worker.d.ts +2 -0
  218. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-resize.d.ts +16 -0
  219. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/json.d.ts +3 -0
  220. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/mime.d.ts +3 -0
  221. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/open-browser.d.ts +9 -0
  222. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/paths.d.ts +31 -0
  223. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/photon.d.ts +21 -0
  224. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/pi-user-agent.d.ts +2 -0
  225. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/shell.d.ts +31 -0
  226. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/sleep.d.ts +5 -0
  227. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/syntax-highlight.d.ts +12 -0
  228. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/tools-manager.d.ts +3 -0
  229. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/version-check.d.ts +15 -0
  230. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/windows-self-update.d.ts +3 -0
  231. package/dist/extensions/pi-tool-display/CHANGELOG.md +329 -0
  232. package/dist/extensions/pi-tool-display/LICENSE +21 -0
  233. package/dist/extensions/pi-tool-display/README.md +417 -0
  234. package/dist/extensions/pi-tool-display/config/config.example.json +40 -0
  235. package/dist/extensions/pi-tool-display/index.ts +3 -0
  236. package/dist/extensions/pi-tool-display/package-lock.json +2555 -0
  237. package/dist/extensions/pi-tool-display/package.json +86 -0
  238. package/dist/extensions/pi-tool-display/src/agent-dir.ts +35 -0
  239. package/dist/extensions/pi-tool-display/src/ansi-utils.ts +116 -0
  240. package/dist/extensions/pi-tool-display/src/bash-display.ts +213 -0
  241. package/dist/extensions/pi-tool-display/src/capabilities.ts +88 -0
  242. package/dist/extensions/pi-tool-display/src/config-modal.ts +541 -0
  243. package/dist/extensions/pi-tool-display/src/config-store.ts +304 -0
  244. package/dist/extensions/pi-tool-display/src/debug-logger.ts +150 -0
  245. package/dist/extensions/pi-tool-display/src/diff-presentation.ts +72 -0
  246. package/dist/extensions/pi-tool-display/src/diff-renderer.ts +2517 -0
  247. package/dist/extensions/pi-tool-display/src/disposable.ts +34 -0
  248. package/dist/extensions/pi-tool-display/src/extension-lifecycle.ts +14 -0
  249. package/dist/extensions/pi-tool-display/src/index.ts +109 -0
  250. package/dist/extensions/pi-tool-display/src/line-width-safety.ts +93 -0
  251. package/dist/extensions/pi-tool-display/src/modal-icons.ts +57 -0
  252. package/dist/extensions/pi-tool-display/src/pending-diff-preview.ts +370 -0
  253. package/dist/extensions/pi-tool-display/src/presets.ts +117 -0
  254. package/dist/extensions/pi-tool-display/src/render-utils.ts +186 -0
  255. package/dist/extensions/pi-tool-display/src/settings-inspector-modal.ts +475 -0
  256. package/dist/extensions/pi-tool-display/src/thinking-label.ts +343 -0
  257. package/dist/extensions/pi-tool-display/src/tool-call-box.ts +181 -0
  258. package/dist/extensions/pi-tool-display/src/tool-metadata.ts +139 -0
  259. package/dist/extensions/pi-tool-display/src/tool-overrides.ts +2168 -0
  260. package/dist/extensions/pi-tool-display/src/types.ts +109 -0
  261. package/dist/extensions/pi-tool-display/src/user-message-box-markdown.ts +64 -0
  262. package/dist/extensions/pi-tool-display/src/user-message-box-native.ts +66 -0
  263. package/dist/extensions/pi-tool-display/src/user-message-box-patch.ts +72 -0
  264. package/dist/extensions/pi-tool-display/src/user-message-box-renderer.ts +419 -0
  265. package/dist/extensions/pi-tool-display/src/user-message-box-utils.ts +106 -0
  266. package/dist/extensions/pi-tool-display/src/write-display-utils.ts +31 -0
  267. package/dist/extensions/pi-tool-display/src/zellij-modal.ts +1027 -0
  268. package/dist/extensions/pi-tool-display/tests/active-backlog-red.test.ts +65 -0
  269. package/dist/extensions/pi-tool-display/tests/ansi-utils.test.ts +345 -0
  270. package/dist/extensions/pi-tool-display/tests/bash-display.test.ts +442 -0
  271. package/dist/extensions/pi-tool-display/tests/capabilities-edge.test.ts +360 -0
  272. package/dist/extensions/pi-tool-display/tests/capabilities.test.ts +54 -0
  273. package/dist/extensions/pi-tool-display/tests/config-modal.test.ts +360 -0
  274. package/dist/extensions/pi-tool-display/tests/config-store.test.ts +87 -0
  275. package/dist/extensions/pi-tool-display/tests/custom-tool-overrides.test.ts +415 -0
  276. package/dist/extensions/pi-tool-display/tests/debug-logger-edge.test.ts +630 -0
  277. package/dist/extensions/pi-tool-display/tests/debug-logger.test.ts +62 -0
  278. package/dist/extensions/pi-tool-display/tests/diff-renderer-ansi.test.ts +55 -0
  279. package/dist/extensions/pi-tool-display/tests/diff-renderer-edge.test.ts +886 -0
  280. package/dist/extensions/pi-tool-display/tests/diff-renderer-numbering.test.ts +135 -0
  281. package/dist/extensions/pi-tool-display/tests/diff-renderer-width.test.ts +454 -0
  282. package/dist/extensions/pi-tool-display/tests/diff-renderer-wrap.test.ts +169 -0
  283. package/dist/extensions/pi-tool-display/tests/index-integration.test.ts +354 -0
  284. package/dist/extensions/pi-tool-display/tests/pending-diff-preview.test.ts +79 -0
  285. package/dist/extensions/pi-tool-display/tests/presets-edge.test.ts +229 -0
  286. package/dist/extensions/pi-tool-display/tests/presets.test.ts +26 -0
  287. package/dist/extensions/pi-tool-display/tests/reload-behavior.test.ts +1241 -0
  288. package/dist/extensions/pi-tool-display/tests/render-utils.test.ts +710 -0
  289. package/dist/extensions/pi-tool-display/tests/settings-inspector.test.ts +450 -0
  290. package/dist/extensions/pi-tool-display/tests/thinking-label-edge.test.ts +904 -0
  291. package/dist/extensions/pi-tool-display/tests/thinking-label.test.ts +72 -0
  292. package/dist/extensions/pi-tool-display/tests/tool-call-box.test.ts +105 -0
  293. package/dist/extensions/pi-tool-display/tests/tool-overrides-config.test.ts +613 -0
  294. package/dist/extensions/pi-tool-display/tests/tool-overrides-mcp.test.ts +499 -0
  295. package/dist/extensions/pi-tool-display/tests/tool-overrides-registration.test.ts +315 -0
  296. package/dist/extensions/pi-tool-display/tests/tool-overrides-write-meta.test.ts +68 -0
  297. package/dist/extensions/pi-tool-display/tests/tool-ui-utils.test.ts +413 -0
  298. package/dist/extensions/pi-tool-display/tests/user-message-box-performance-red.test.ts +176 -0
  299. package/dist/extensions/pi-tool-display/tests/user-message-box.test.ts +908 -0
  300. package/dist/extensions/pi-tool-display/tests/zellij-modal.test.ts +848 -0
  301. package/dist/extensions/pi-tool-display/tool-display-api-consumer.d.ts +30 -0
  302. package/dist/extensions/pi-tool-display/tool-display-api-consumer.js +40 -0
  303. package/dist/extensions/pi-web-agent/package.json +31 -31
  304. package/dist/extensions/pi-web-agent/src/backends/config.ts +205 -205
  305. package/dist/extensions/pi-web-agent/src/backends/doctor.ts +136 -136
  306. package/dist/extensions/pi-web-agent/src/backends/factory.ts +152 -152
  307. package/dist/extensions/pi-web-agent/src/backends/settings-reader.ts +25 -25
  308. package/dist/extensions/pi-web-agent/src/cache/ttl-cache.ts +28 -28
  309. package/dist/extensions/pi-web-agent/src/changelog-notice.ts +136 -136
  310. package/dist/extensions/pi-web-agent/src/commands/web-agent-config.ts +946 -946
  311. package/dist/extensions/pi-web-agent/src/extension.ts +126 -126
  312. package/dist/extensions/pi-web-agent/src/extract/readability.ts +118 -118
  313. package/dist/extensions/pi-web-agent/src/fetch/browser-resolution.ts +199 -199
  314. package/dist/extensions/pi-web-agent/src/fetch/firecrawl-fetch.ts +100 -100
  315. package/dist/extensions/pi-web-agent/src/fetch/headless-fetch.ts +117 -117
  316. package/dist/extensions/pi-web-agent/src/fetch/http-fetch.ts +67 -67
  317. package/dist/extensions/pi-web-agent/src/orchestration/answer-synthesizer.ts +60 -60
  318. package/dist/extensions/pi-web-agent/src/orchestration/candidate-selector.ts +50 -50
  319. package/dist/extensions/pi-web-agent/src/orchestration/direct-url.ts +52 -52
  320. package/dist/extensions/pi-web-agent/src/orchestration/evidence-quality.ts +105 -105
  321. package/dist/extensions/pi-web-agent/src/orchestration/evidence-ranker.ts +45 -45
  322. package/dist/extensions/pi-web-agent/src/orchestration/index.ts +28 -28
  323. package/dist/extensions/pi-web-agent/src/orchestration/query-planner.ts +47 -47
  324. package/dist/extensions/pi-web-agent/src/orchestration/research-orchestrator.ts +376 -376
  325. package/dist/extensions/pi-web-agent/src/orchestration/research-types.ts +64 -64
  326. package/dist/extensions/pi-web-agent/src/orchestration/research-worker.ts +181 -181
  327. package/dist/extensions/pi-web-agent/src/orchestration/source-profile.ts +101 -101
  328. package/dist/extensions/pi-web-agent/src/orchestration/stop-decider.ts +81 -81
  329. package/dist/extensions/pi-web-agent/src/presentation/config-store.ts +210 -210
  330. package/dist/extensions/pi-web-agent/src/presentation/config.ts +75 -75
  331. package/dist/extensions/pi-web-agent/src/presentation/explore-presentation.ts +61 -61
  332. package/dist/extensions/pi-web-agent/src/presentation/fetch-presentation.ts +54 -54
  333. package/dist/extensions/pi-web-agent/src/presentation/search-presentation.ts +41 -41
  334. package/dist/extensions/pi-web-agent/src/presentation/select-view.ts +20 -20
  335. package/dist/extensions/pi-web-agent/src/presentation/types.ts +63 -63
  336. package/dist/extensions/pi-web-agent/src/search/brave.ts +114 -114
  337. package/dist/extensions/pi-web-agent/src/search/duckduckgo.ts +72 -72
  338. package/dist/extensions/pi-web-agent/src/search/searxng.ts +96 -96
  339. package/dist/extensions/pi-web-agent/src/tools/web-explore.ts +71 -71
  340. package/dist/extensions/pi-web-agent/src/tools/web-fetch-headless.ts +31 -31
  341. package/dist/extensions/pi-web-agent/src/tools/web-fetch.ts +31 -31
  342. package/dist/extensions/pi-web-agent/src/tools/web-search.ts +157 -157
  343. package/dist/extensions/pi-web-agent/src/types.ts +88 -88
  344. package/dist/extensions/pi-zentui/extensions/zentui/format.ts +46 -1
  345. package/dist/extensions/pi-zentui/extensions/zentui/index.ts +10 -0
  346. package/dist/extensions/pi-zentui/extensions/zentui/user-message-styles.ts +1 -1
  347. package/dist/extensions/pi-zentui/test/extension-compliance.test.ts +3 -3
  348. package/dist/extensions/pi-zentui/test/format.test.ts +50 -2
  349. package/dist/extensions/ponytail/package.json +8 -8
  350. package/dist/extensions/question/constants.ts +30 -30
  351. package/dist/extensions/question/helpers.ts +58 -58
  352. package/dist/extensions/question/navigation.ts +14 -14
  353. package/dist/extensions/question/package.json +19 -19
  354. package/dist/extensions/question/selection-mode.ts +46 -46
  355. package/dist/extensions/question/shortcuts.ts +44 -44
  356. package/dist/extensions/question/types.ts +132 -132
  357. package/dist/extensions/test-resolve-hook-impl.mjs +6 -6
  358. package/dist/extensions/test-resolve-hook.mjs +6 -6
  359. package/dist/extensions/tokenin-onboarding.ts +112 -2
  360. package/dist/extensions/web-agent-onboarding.ts +222 -222
  361. package/dist/index.d.ts +2 -1
  362. package/dist/index.js +1 -0
  363. package/dist/main.js +2 -0
  364. package/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  365. package/dist/modes/interactive/components/settings-selector.js +10 -0
  366. package/dist/modes/interactive/interactive-mode.d.ts +4 -0
  367. package/dist/modes/interactive/interactive-mode.js +72 -42
  368. package/dist/modes/rpc/rpc-client.d.ts +7 -0
  369. package/dist/modes/rpc/rpc-client.js +7 -0
  370. package/dist/modes/rpc/rpc-mode.js +3 -0
  371. package/dist/modes/rpc/rpc-types.d.ts +12 -0
  372. package/dist/package-manager-cli.js +71 -71
  373. package/dist/rpc-entry.js +0 -0
  374. package/dist/skills/improve-codebase/REFERENCE.md +78 -78
  375. package/dist/utils/shell.js +6 -4
  376. package/docs/compaction.md +396 -396
  377. package/docs/containerization.md +111 -111
  378. package/docs/development.md +71 -71
  379. package/docs/docs.json +164 -164
  380. package/docs/environment-variables.md +86 -86
  381. package/docs/index.md +83 -83
  382. package/docs/json.md +82 -82
  383. package/docs/models.md +502 -502
  384. package/docs/packages.md +227 -227
  385. package/docs/plans/subagent-delegation/phase-0-correctness.md +264 -264
  386. package/docs/plans/subagent-delegation/phase-1-behavioral-contract.md +485 -485
  387. package/docs/plans/subagent-delegation/phase-2-context-controls.md +281 -281
  388. package/docs/plans/subagent-delegation/phase-3-advisory-routing.md +361 -361
  389. package/docs/plans/subagent-delegation/phase-4-optional-enforcement.md +380 -380
  390. package/docs/prompt-templates.md +95 -95
  391. package/docs/providers.md +293 -293
  392. package/docs/security.md +59 -59
  393. package/docs/session-format.md +414 -414
  394. package/docs/sessions.md +145 -145
  395. package/docs/settings.md +4 -0
  396. package/docs/shared-host-extensions.md +109 -109
  397. package/docs/shell-aliases.md +13 -13
  398. package/docs/skills.md +231 -231
  399. package/docs/terminal-setup.md +142 -142
  400. package/docs/termux.md +127 -127
  401. package/docs/themes.md +295 -295
  402. package/docs/tmux.md +63 -63
  403. package/docs/tui.md +927 -927
  404. package/docs/windows.md +17 -17
  405. package/examples/README.md +25 -25
  406. package/examples/extensions/README.md +211 -211
  407. package/examples/extensions/auto-commit-on-exit.ts +49 -49
  408. package/examples/extensions/bash-spawn-hook.ts +30 -30
  409. package/examples/extensions/bookmark.ts +50 -50
  410. package/examples/extensions/border-status-editor.ts +150 -150
  411. package/examples/extensions/built-in-tool-renderer.ts +249 -249
  412. package/examples/extensions/claude-rules.ts +86 -86
  413. package/examples/extensions/commands.ts +72 -72
  414. package/examples/extensions/confirm-destructive.ts +59 -59
  415. package/examples/extensions/custom-compaction.ts +130 -130
  416. package/examples/extensions/custom-footer.ts +64 -64
  417. package/examples/extensions/custom-header.ts +73 -73
  418. package/examples/extensions/custom-provider-anthropic/index.ts +610 -610
  419. package/examples/extensions/custom-provider-anthropic/package-lock.json +24 -24
  420. package/examples/extensions/custom-provider-anthropic/package.json +19 -19
  421. package/examples/extensions/custom-provider-gitlab-duo/index.ts +404 -404
  422. package/examples/extensions/custom-provider-gitlab-duo/package.json +16 -16
  423. package/examples/extensions/custom-provider-gitlab-duo/test.ts +82 -82
  424. package/examples/extensions/dirty-repo-guard.ts +56 -56
  425. package/examples/extensions/doom-overlay/README.md +46 -46
  426. package/examples/extensions/doom-overlay/doom/build/doom.js +21 -21
  427. package/examples/extensions/doom-overlay/doom/build/doom.wasm +0 -0
  428. package/examples/extensions/doom-overlay/doom/build.sh +152 -152
  429. package/examples/extensions/doom-overlay/doom/doomgeneric_pi.c +72 -72
  430. package/examples/extensions/doom-overlay/doom-component.ts +132 -132
  431. package/examples/extensions/doom-overlay/doom-engine.ts +173 -173
  432. package/examples/extensions/doom-overlay/doom-keys.ts +104 -104
  433. package/examples/extensions/doom-overlay/index.ts +74 -74
  434. package/examples/extensions/doom-overlay/wad-finder.ts +51 -51
  435. package/examples/extensions/dynamic-resources/SKILL.md +8 -8
  436. package/examples/extensions/dynamic-resources/dynamic.json +79 -79
  437. package/examples/extensions/dynamic-resources/dynamic.md +5 -5
  438. package/examples/extensions/dynamic-resources/index.ts +15 -15
  439. package/examples/extensions/dynamic-tools.ts +74 -74
  440. package/examples/extensions/event-bus.ts +43 -43
  441. package/examples/extensions/file-trigger.ts +41 -41
  442. package/examples/extensions/git-checkpoint.ts +53 -53
  443. package/examples/extensions/git-merge-and-resolve.ts +115 -115
  444. package/examples/extensions/github-issue-autocomplete.ts +185 -185
  445. package/examples/extensions/gondolin/index.ts +531 -531
  446. package/examples/extensions/gondolin/package-lock.json +185 -185
  447. package/examples/extensions/gondolin/package.json +19 -19
  448. package/examples/extensions/handoff.ts +199 -199
  449. package/examples/extensions/hello.ts +26 -26
  450. package/examples/extensions/hidden-thinking-label.ts +53 -53
  451. package/examples/extensions/inline-bash.ts +94 -94
  452. package/examples/extensions/input-transform-streaming.ts +39 -39
  453. package/examples/extensions/input-transform.ts +43 -43
  454. package/examples/extensions/interactive-shell.ts +196 -196
  455. package/examples/extensions/mac-system-theme.ts +47 -47
  456. package/examples/extensions/message-renderer.ts +59 -59
  457. package/examples/extensions/minimal-mode.ts +426 -426
  458. package/examples/extensions/modal-editor.ts +85 -85
  459. package/examples/extensions/model-status.ts +31 -31
  460. package/examples/extensions/notify.ts +55 -55
  461. package/examples/extensions/overlay-qa-tests.ts +1450 -1450
  462. package/examples/extensions/overlay-test.ts +153 -153
  463. package/examples/extensions/permission-gate.ts +34 -34
  464. package/examples/extensions/pirate.ts +47 -47
  465. package/examples/extensions/plan-mode/README.md +66 -66
  466. package/examples/extensions/plan-mode/index.ts +390 -390
  467. package/examples/extensions/plan-mode/utils.ts +168 -168
  468. package/examples/extensions/preset.ts +436 -436
  469. package/examples/extensions/project-trust.ts +64 -64
  470. package/examples/extensions/prompt-customizer.ts +97 -97
  471. package/examples/extensions/protected-paths.ts +30 -30
  472. package/examples/extensions/provider-payload.ts +18 -18
  473. package/examples/extensions/qna.ts +122 -122
  474. package/examples/extensions/question.ts +285 -285
  475. package/examples/extensions/questionnaire.ts +448 -448
  476. package/examples/extensions/rainbow-editor.ts +88 -88
  477. package/examples/extensions/reload-runtime.ts +37 -37
  478. package/examples/extensions/rpc-demo.ts +118 -118
  479. package/examples/extensions/sandbox/index.ts +321 -321
  480. package/examples/extensions/sandbox/package-lock.json +92 -92
  481. package/examples/extensions/sandbox/package.json +19 -19
  482. package/examples/extensions/send-user-message.ts +97 -97
  483. package/examples/extensions/session-name.ts +27 -27
  484. package/examples/extensions/shutdown-command.ts +63 -63
  485. package/examples/extensions/snake.ts +343 -343
  486. package/examples/extensions/space-invaders.ts +560 -560
  487. package/examples/extensions/ssh.ts +220 -220
  488. package/examples/extensions/status-line.ts +32 -32
  489. package/examples/extensions/structured-output.ts +65 -65
  490. package/examples/extensions/subagent/README.md +175 -175
  491. package/examples/extensions/subagent/agents/planner.md +37 -37
  492. package/examples/extensions/subagent/agents/reviewer.md +35 -35
  493. package/examples/extensions/subagent/agents/scout.md +50 -50
  494. package/examples/extensions/subagent/agents/worker.md +24 -24
  495. package/examples/extensions/subagent/agents.ts +126 -126
  496. package/examples/extensions/subagent/index.ts +1015 -1015
  497. package/examples/extensions/subagent/prompts/implement-and-review.md +10 -10
  498. package/examples/extensions/subagent/prompts/implement.md +10 -10
  499. package/examples/extensions/subagent/prompts/scout-and-plan.md +9 -9
  500. package/examples/extensions/summarize.ts +209 -209
  501. package/examples/extensions/system-prompt-header.ts +17 -17
  502. package/examples/extensions/tic-tac-toe.ts +1008 -1008
  503. package/examples/extensions/timed-confirm.ts +70 -70
  504. package/examples/extensions/titlebar-spinner.ts +58 -58
  505. package/examples/extensions/todo.ts +297 -297
  506. package/examples/extensions/tool-override.ts +144 -144
  507. package/examples/extensions/tools.ts +146 -146
  508. package/examples/extensions/trigger-compact.ts +50 -50
  509. package/examples/extensions/truncated-tool.ts +195 -195
  510. package/examples/extensions/widget-placement.ts +9 -9
  511. package/examples/extensions/with-deps/index.ts +32 -32
  512. package/examples/extensions/with-deps/package-lock.json +31 -31
  513. package/examples/extensions/with-deps/package.json +22 -22
  514. package/examples/extensions/working-indicator.ts +123 -123
  515. package/examples/extensions/working-message-test.ts +25 -25
  516. package/examples/rpc-extension-ui.ts +632 -632
  517. package/examples/sdk/01-minimal.ts +26 -26
  518. package/examples/sdk/02-custom-model.ts +53 -53
  519. package/examples/sdk/03-custom-prompt.ts +75 -75
  520. package/examples/sdk/04-skills.ts +55 -55
  521. package/examples/sdk/05-tools.ts +48 -48
  522. package/examples/sdk/06-extensions.ts +99 -99
  523. package/examples/sdk/07-context-files.ts +47 -47
  524. package/examples/sdk/08-prompt-templates.ts +51 -51
  525. package/examples/sdk/09-api-keys-and-oauth.ts +52 -52
  526. package/examples/sdk/10-settings.ts +53 -53
  527. package/examples/sdk/11-sessions.ts +52 -52
  528. package/examples/sdk/12-full-control.ts +79 -79
  529. package/examples/sdk/13-session-runtime.ts +67 -67
  530. package/examples/sdk/README.md +144 -144
  531. package/package.json +6 -6
@@ -0,0 +1,908 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+ import {
4
+ extractUserMessageMarkdownState,
5
+ } from "../src/user-message-box-markdown.ts";
6
+ import {
7
+ patchUserMessageRenderPrototype,
8
+ type PatchableUserMessagePrototype,
9
+ } from "../src/user-message-box-patch.ts";
10
+ import {
11
+ patchNativeUserMessagePrototype,
12
+ shouldBypassUserMessageMarkdownRebuild,
13
+ createUserMessageMarkdownLineRenderer,
14
+ } from "../src/user-message-box-renderer.ts";
15
+ import {
16
+ addUserMessageVerticalPadding,
17
+ applyUserMessageBackground,
18
+ normalizeUserMessageContentLine,
19
+ normalizeUserMessageContentLines,
20
+ type UserMessageBackgroundTheme,
21
+ } from "../src/user-message-box-utils.ts";
22
+
23
+ // ===========================================================================
24
+ // Issue #10: OSC 133 prompt marker stripping
25
+ // Each variant: BEL-terminated (\x07) and ST-terminated (\x1b\\)
26
+ // ===========================================================================
27
+
28
+ test("osc133 strips BEL-terminated A marker from content", () => {
29
+ assert.equal(
30
+ normalizeUserMessageContentLine("before\x1b]133;A\x07after"),
31
+ "beforeafter",
32
+ );
33
+ });
34
+
35
+ test("osc133 strips BEL-terminated B marker from content", () => {
36
+ assert.equal(
37
+ normalizeUserMessageContentLine("\x1b]133;B\x07middle"),
38
+ "middle",
39
+ );
40
+ });
41
+
42
+ test("osc133 strips BEL-terminated C marker from content", () => {
43
+ assert.equal(
44
+ normalizeUserMessageContentLine("data\x1b]133;C\x07"),
45
+ "data",
46
+ );
47
+ });
48
+
49
+ test("osc133 strips BEL-terminated D marker from content", () => {
50
+ assert.equal(
51
+ normalizeUserMessageContentLine("\x1b]133;D\x07trailing"),
52
+ "trailing",
53
+ );
54
+ });
55
+
56
+ test("osc133 strips ST-terminated A marker", () => {
57
+ assert.equal(
58
+ normalizeUserMessageContentLine("lead\x1b]133;A\x1b\\tail"),
59
+ "leadtail",
60
+ );
61
+ });
62
+
63
+ test("osc133 strips ST-terminated B marker", () => {
64
+ assert.equal(
65
+ normalizeUserMessageContentLine("\x1b]133;B\x1b\\inner"),
66
+ "inner",
67
+ );
68
+ });
69
+
70
+ test("osc133 strips ST-terminated C marker", () => {
71
+ assert.equal(
72
+ normalizeUserMessageContentLine("\x1b]133;C\x1b\\"),
73
+ "",
74
+ );
75
+ });
76
+
77
+ test("osc133 strips ST-terminated D marker", () => {
78
+ assert.equal(
79
+ normalizeUserMessageContentLine("\x1b]133;D\x1b\\data"),
80
+ "data",
81
+ );
82
+ });
83
+
84
+ test("osc133 strips multiple markers in a single line", () => {
85
+ assert.equal(
86
+ normalizeUserMessageContentLine("\x1b]133;A\x07hello\x1b]133;B\x07 world\x1b]133;C\x07"),
87
+ "hello world",
88
+ );
89
+ });
90
+
91
+ test("osc133 strips marker with optional semicolon-delimited parameters", () => {
92
+ assert.equal(
93
+ normalizeUserMessageContentLine("\x1b]133;A;url=https://example.com\x07text\x1b]133;B\x07"),
94
+ "text",
95
+ );
96
+ });
97
+
98
+ test("osc133 markers are stripped via applyUserMessageBackground path", () => {
99
+ assert.equal(
100
+ applyUserMessageBackground(undefined, "hello\x1b]133;A\x07"),
101
+ "hello",
102
+ );
103
+ });
104
+
105
+ test("osc133-only line is treated as visually empty", () => {
106
+ assert.equal(
107
+ normalizeUserMessageContentLine("\x1b]133;A\x07\x1b]133;B\x07"),
108
+ "",
109
+ );
110
+ });
111
+
112
+ // ===========================================================================
113
+ // Nested Box → Markdown structures
114
+ // ===========================================================================
115
+
116
+ test("extract finds deeply nested markdown child at depth 10", () => {
117
+ const theme = { heading: () => "" };
118
+ let child: Record<string, unknown> = {
119
+ text: "deep markdown",
120
+ theme,
121
+ };
122
+ for (let i = 0; i < 10; i++) {
123
+ child = { children: [child] };
124
+ }
125
+ const extracted = extractUserMessageMarkdownState({ children: [child] });
126
+ assert.equal(extracted?.text, "deep markdown");
127
+ assert.equal(extracted?.theme, theme);
128
+ });
129
+
130
+ test("extract returns first markdown child via DFS (not last)", () => {
131
+ const themeA = { heading: () => "a" };
132
+ const themeB = { heading: () => "b" };
133
+ const extracted = extractUserMessageMarkdownState({
134
+ children: [
135
+ { text: "first", theme: themeA },
136
+ { text: "second", theme: themeB },
137
+ ],
138
+ });
139
+ assert.equal(extracted?.text, "first");
140
+ assert.equal(extracted?.theme, themeA);
141
+ });
142
+
143
+ test("extract returns undefined when no markdown child exists", () => {
144
+ const extracted = extractUserMessageMarkdownState({
145
+ children: [{ lines: 3 }, { other: "data" }],
146
+ });
147
+ assert.equal(extracted, undefined);
148
+ });
149
+
150
+ test("extract returns undefined when child has theme but no text string", () => {
151
+ const extracted = extractUserMessageMarkdownState({
152
+ children: [{ theme: { heading: () => "" } }],
153
+ });
154
+ assert.equal(extracted, undefined);
155
+ });
156
+
157
+ test("extract returns markdown when top-level value itself is markdown-like", () => {
158
+ const theme = { heading: () => "" };
159
+ const extracted = extractUserMessageMarkdownState({
160
+ text: "self markdown",
161
+ theme,
162
+ } as never);
163
+ assert.equal(extracted?.text, "self markdown");
164
+ assert.equal(extracted?.theme, theme);
165
+ });
166
+
167
+ // ===========================================================================
168
+ // Malformed children on extractUserMessageMarkdownState
169
+ // ===========================================================================
170
+
171
+ test("extract handles null children gracefully", () => {
172
+ assert.equal(extractUserMessageMarkdownState({ children: null }), undefined);
173
+ });
174
+
175
+ test("extract handles undefined children (missing property) gracefully", () => {
176
+ assert.equal(extractUserMessageMarkdownState({}), undefined);
177
+ });
178
+
179
+ test("extract handles children as a plain string (non-array)", () => {
180
+ assert.equal(
181
+ extractUserMessageMarkdownState({ children: "not-an-array" as never }),
182
+ undefined,
183
+ );
184
+ });
185
+
186
+ test("extract handles children as a number", () => {
187
+ assert.equal(
188
+ extractUserMessageMarkdownState({ children: 42 as never }),
189
+ undefined,
190
+ );
191
+ });
192
+
193
+ test("extract handles array children containing only non-object items", () => {
194
+ assert.equal(
195
+ extractUserMessageMarkdownState({ children: [null, 42, "str", undefined, true] }),
196
+ undefined,
197
+ );
198
+ });
199
+
200
+ test("extract handles null top-level value", () => {
201
+ assert.equal(extractUserMessageMarkdownState(null as never), undefined);
202
+ });
203
+
204
+ test("extract handles undefined top-level value", () => {
205
+ assert.equal(extractUserMessageMarkdownState(undefined as never), undefined);
206
+ });
207
+
208
+ test("extract handles circular reference (stack overflow expected)", () => {
209
+ const circular: Record<string, unknown> = { children: [] };
210
+ circular.children = [circular];
211
+ // findMarkdownChild recurses without cycle detection, so this throws.
212
+ // In production the caller wraps extract in try/catch.
213
+ assert.throws(() => {
214
+ extractUserMessageMarkdownState(circular);
215
+ });
216
+ });
217
+
218
+ // ===========================================================================
219
+ // defaultTextStyle bgColor sanitization
220
+ // ===========================================================================
221
+
222
+ test("extract strips bgColor but keeps other defaultTextStyle props", () => {
223
+ const extracted = extractUserMessageMarkdownState({
224
+ children: [{
225
+ text: "styled",
226
+ theme: {},
227
+ defaultTextStyle: { color: "red", bgColor: () => "", bold: true },
228
+ }],
229
+ });
230
+ assert.equal(extracted?.defaultTextStyle?.color, "red");
231
+ assert.equal(extracted?.defaultTextStyle?.bold, true);
232
+ assert.equal("bgColor" in (extracted?.defaultTextStyle ?? {}), false);
233
+ });
234
+
235
+ test("extract returns undefined defaultTextStyle when all props were bgColor-only", () => {
236
+ const extracted = extractUserMessageMarkdownState({
237
+ children: [{
238
+ text: "text",
239
+ theme: {},
240
+ defaultTextStyle: { bgColor: () => "" },
241
+ }],
242
+ });
243
+ assert.equal(extracted?.defaultTextStyle, undefined);
244
+ });
245
+
246
+ test("extract returns undefined defaultTextStyle when value is not a record", () => {
247
+ const extracted = extractUserMessageMarkdownState({
248
+ children: [{
249
+ text: "raw",
250
+ theme: {},
251
+ defaultTextStyle: "string" as never,
252
+ }],
253
+ });
254
+ assert.equal(extracted?.defaultTextStyle, undefined);
255
+ });
256
+
257
+ // ===========================================================================
258
+ // applyUserMessageBackground with various theme objects
259
+ // ===========================================================================
260
+
261
+ test("applyBg on empty theme object returns sanitized text unchanged", () => {
262
+ const result = applyUserMessageBackground({}, "\x1b[31mred\x1b[0m");
263
+ // \x1b[0m → \x1b[39;22;23;24;25;27;28;29m (reset sans bg params)
264
+ assert.ok(result.includes("\x1b[31mred"));
265
+ assert.doesNotMatch(result, /\x1b\[0m/);
266
+ });
267
+
268
+ test("applyBg with empty string returns empty string", () => {
269
+ assert.equal(applyUserMessageBackground({ getBgAnsi: () => "\x1b[48;5;24m" }, ""), "");
270
+ assert.equal(applyUserMessageBackground(undefined, ""), "");
271
+ });
272
+
273
+ test("applyBg ignores getBgAnsi when it is not a function and falls to bg", () => {
274
+ const result = applyUserMessageBackground(
275
+ {
276
+ getBgAnsi: "not-a-fn" as never,
277
+ bg: (_color, text) => `wrapped(${text})`,
278
+ },
279
+ "hello",
280
+ );
281
+ assert.equal(result, "wrapped(hello)");
282
+ });
283
+
284
+ test("applyBg falls back to bg when getBgAnsi throws", () => {
285
+ const result = applyUserMessageBackground(
286
+ {
287
+ getBgAnsi: () => { throw new Error("oops"); },
288
+ bg: (_color, text) => `fallback(${text})`,
289
+ },
290
+ "hello",
291
+ );
292
+ assert.equal(result, "fallback(hello)");
293
+ });
294
+
295
+ test("applyBg returns sanitized text when both getBgAnsi and bg throw", () => {
296
+ const result = applyUserMessageBackground(
297
+ {
298
+ getBgAnsi: () => { throw new Error("e1"); },
299
+ bg: (_color, _text) => { throw new Error("e2"); },
300
+ },
301
+ "\x1b[32mtext",
302
+ );
303
+ assert.equal(result, "\x1b[32mtext");
304
+ });
305
+
306
+ test("applyBg returns sanitized text when theme has neither method", () => {
307
+ const result = applyUserMessageBackground(
308
+ { unrelated: true } as never,
309
+ "\x1b[33myellow\x1b[0m",
310
+ );
311
+ assert.ok(result.includes("\x1b[33myellow"));
312
+ });
313
+
314
+ test("applyBg passes userMessageBg constant to getBgAnsi", () => {
315
+ let capturedColor = "";
316
+ applyUserMessageBackground(
317
+ {
318
+ getBgAnsi: (color) => {
319
+ capturedColor = color;
320
+ return "\x1b[48;5;24m";
321
+ },
322
+ },
323
+ "test",
324
+ );
325
+ assert.equal(capturedColor, "userMessageBg");
326
+ });
327
+
328
+ test("applyBg passes userMessageBg constant to bg fallback", () => {
329
+ let capturedColor = "";
330
+ const result = applyUserMessageBackground(
331
+ {
332
+ bg: (color, text) => {
333
+ capturedColor = color;
334
+ return `[${color}]${text}`;
335
+ },
336
+ },
337
+ "text",
338
+ );
339
+ assert.equal(capturedColor, "userMessageBg");
340
+ assert.equal(result, "[userMessageBg]text");
341
+ });
342
+
343
+ // ===========================================================================
344
+ // Background double-application prevention (Issue #8 / #3)
345
+ // ===========================================================================
346
+
347
+ test("applyBg strips internal SGR 49 and appends exactly one reset at end", () => {
348
+ const rendered = applyUserMessageBackground(
349
+ { getBgAnsi: () => "\x1b[48;5;24m" },
350
+ "\x1b[31mhello\x1b[49m",
351
+ );
352
+ const fortyNineMatches = rendered.match(/\x1b\[49m/g);
353
+ assert.equal(fortyNineMatches?.length ?? 0, 1);
354
+ assert.ok(rendered.endsWith("\x1b[49m"));
355
+ });
356
+
357
+ test("applyBg strips multiple SGR 49 occurrences, appends single reset", () => {
358
+ const rendered = applyUserMessageBackground(
359
+ { getBgAnsi: () => "\x1b[48;5;24m" },
360
+ "\x1b[49mstart\x1b[49m middle\x1b[49m",
361
+ );
362
+ const fortyNineMatches = rendered.match(/\x1b\[49m/g);
363
+ assert.equal(fortyNineMatches?.length ?? 0, 1);
364
+ assert.ok(rendered.endsWith("\x1b[49m"));
365
+ });
366
+
367
+ test("applyBg strips existing background SGR before applying new bg via getBgAnsi", () => {
368
+ const rendered = applyUserMessageBackground(
369
+ { getBgAnsi: () => "\x1b[48;5;24m" },
370
+ "\x1b[48;5;160mtext\x1b[49m",
371
+ );
372
+ // Original bg (48;5;160) stripped
373
+ assert.doesNotMatch(rendered, /\x1b\[48;5;160m/);
374
+ // New bg applied exactly once
375
+ const bg24Matches = rendered.match(/\x1b\[48;5;24m/g);
376
+ assert.equal(bg24Matches?.length ?? 0, 1);
377
+ // Reset appended exactly once
378
+ const fortyNineMatches = rendered.match(/\x1b\[49m/g);
379
+ assert.equal(fortyNineMatches?.length ?? 0, 1);
380
+ assert.ok(rendered.endsWith("\x1b[49m"));
381
+ });
382
+
383
+ test("applyBg via bg function does not double-wrap", () => {
384
+ const rendered = applyUserMessageBackground(
385
+ { bg: (_color, text) => `[bg]${text}[/bg]` },
386
+ "\x1b[48;5;24mhello",
387
+ );
388
+ assert.ok(rendered.startsWith("[bg]"));
389
+ assert.ok(rendered.includes("hello"));
390
+ // The SGR 48;5;24 is stripped by sanitizeAnsiForThemedOutput
391
+ assert.doesNotMatch(rendered, /\x1b\[48;5;24m/);
392
+ });
393
+
394
+ // ===========================================================================
395
+ // normalizeUserMessageContentLines edge cases
396
+ // ===========================================================================
397
+
398
+ test("normalizeLines empty array returns empty array", () => {
399
+ assert.deepEqual(normalizeUserMessageContentLines([]), []);
400
+ });
401
+
402
+ test("normalizeLines trims leading and trailing whitespace-only lines", () => {
403
+ assert.deepEqual(
404
+ normalizeUserMessageContentLines([" ", "content", "\t"]),
405
+ ["content"],
406
+ );
407
+ });
408
+
409
+ test("normalizeLines preserves interior empty lines", () => {
410
+ assert.deepEqual(
411
+ normalizeUserMessageContentLines(["start", "", "end"]),
412
+ ["start", "", "end"],
413
+ );
414
+ });
415
+
416
+ test("normalizeLines trims only edge lines, not interior whitespace", () => {
417
+ assert.deepEqual(
418
+ normalizeUserMessageContentLines(["", " indented ", "middle", ""]),
419
+ [" indented ", "middle"],
420
+ );
421
+ });
422
+
423
+ test("normalizeLines treats leading OSC133-only lines as visually empty and trims them", () => {
424
+ assert.deepEqual(
425
+ normalizeUserMessageContentLines([
426
+ "\x1b]133;A\x07\x1b]133;B\x07 ",
427
+ "actual",
428
+ "\x1b]133;C\x07\u001b[0m",
429
+ ]),
430
+ ["actual"],
431
+ );
432
+ });
433
+
434
+ test("normalizeLines handles array with all visually empty lines", () => {
435
+ assert.deepEqual(
436
+ normalizeUserMessageContentLines(["", " ", "\x1b[0m"]),
437
+ [],
438
+ );
439
+ });
440
+
441
+ test("normalizeLines preserves lines with trailing spaces that are not edge lines", () => {
442
+ // Trailing spaces on interior lines are preserved
443
+ const result = normalizeUserMessageContentLines(["hello ", "world"]);
444
+ assert.equal(result[0], "hello ");
445
+ assert.equal(result[1], "world");
446
+ });
447
+
448
+ // ===========================================================================
449
+ // normalizeUserMessageContentLine edge cases
450
+ // ===========================================================================
451
+
452
+ test("normalizeLine preserves tab characters", () => {
453
+ assert.equal(normalizeUserMessageContentLine("\thello\tworld"), "\thello\tworld");
454
+ });
455
+
456
+ test("normalizeLine preserves non-SGR control characters", () => {
457
+ assert.equal(normalizeUserMessageContentLine("a\x00b\x01c"), "a\x00b\x01c");
458
+ });
459
+
460
+ test("normalizeLine handles very long line without truncation", () => {
461
+ const longLine = "x".repeat(10000);
462
+ assert.equal(normalizeUserMessageContentLine(longLine), longLine);
463
+ });
464
+
465
+ test("normalizeLine handles very long line with ANSI sequences", () => {
466
+ const result = normalizeUserMessageContentLine(
467
+ "\x1b[31m" + "x".repeat(5000) + "\x1b[0m" + "y".repeat(5000),
468
+ );
469
+ // Content survives; SGR 0 is converted to reset params sans bg
470
+ assert.ok(result.includes("x".repeat(5000)));
471
+ assert.ok(result.includes("y".repeat(5000)));
472
+ });
473
+
474
+ test("normalizeLine returns empty for line with only SGR control sequences", () => {
475
+ assert.equal(normalizeUserMessageContentLine("\x1b[0m\x1b[31m\x1b[0m"), "");
476
+ });
477
+
478
+ test("normalizeLine returns empty for empty string", () => {
479
+ assert.equal(normalizeUserMessageContentLine(""), "");
480
+ });
481
+
482
+ test("normalizeLine returns empty for whitespace-only string", () => {
483
+ assert.equal(normalizeUserMessageContentLine(" \t "), "");
484
+ });
485
+
486
+ test("normalizeLine preserves hyperlinks (OSC 8) while stripping OSC 133", () => {
487
+ const hyperlink = "\x1b]8;;https://example.com\x1b\\link\x1b]8;;\x1b\\";
488
+ const result = normalizeUserMessageContentLine(hyperlink);
489
+ // OSC 8 hyperlinks should be preserved, not stripped
490
+ assert.equal(result, hyperlink);
491
+ });
492
+
493
+ // ===========================================================================
494
+ // addUserMessageVerticalPadding edge cases
495
+ // ===========================================================================
496
+
497
+ test("addPadding on empty array returns two empty padding lines", () => {
498
+ assert.deepEqual(addUserMessageVerticalPadding([]), ["", ""]);
499
+ });
500
+
501
+ test("addPadding on single line adds one blank line before and after", () => {
502
+ assert.deepEqual(addUserMessageVerticalPadding(["only"]), ["", "only", ""]);
503
+ });
504
+
505
+ test("addPadding on already-padded input adds another layer of padding", () => {
506
+ assert.deepEqual(
507
+ addUserMessageVerticalPadding(["", "content", ""]),
508
+ ["", "", "content", "", ""],
509
+ );
510
+ });
511
+
512
+ test("addPadding on multi-line input pads all sides equally", () => {
513
+ const result = addUserMessageVerticalPadding(["a", "b", "c"]);
514
+ assert.equal(result.length, 5);
515
+ assert.equal(result[0], "");
516
+ assert.equal(result[result.length - 1], "");
517
+ assert.deepEqual(result.slice(1, -1), ["a", "b", "c"]);
518
+ });
519
+
520
+ // ===========================================================================
521
+ // patchUserMessageRenderPrototype version handling
522
+ // ===========================================================================
523
+
524
+ test("patchRenderPrototype skips when prototype.render is not a function", () => {
525
+ const prototype: PatchableUserMessagePrototype = {
526
+ render: undefined as never,
527
+ };
528
+ patchUserMessageRenderPrototype(prototype, 7, (orig) => orig);
529
+ assert.equal(prototype.render, undefined);
530
+ });
531
+
532
+ test("patchRenderPrototype skips when already patched with same version", () => {
533
+ let buildCallCount = 0;
534
+ const originalRender = (width: number) => [`orig:${width}`];
535
+ const prototype: PatchableUserMessagePrototype = {
536
+ render: originalRender,
537
+ __piUserMessageOriginalRender: originalRender,
538
+ __piUserMessageNativePatched: true,
539
+ __piUserMessagePatchVersion: 7,
540
+ };
541
+ patchUserMessageRenderPrototype(prototype, 7, (_orig) => {
542
+ buildCallCount++;
543
+ return (width) => [`patched:${width}`];
544
+ });
545
+ assert.equal(buildCallCount, 0);
546
+ assert.equal(prototype.render, originalRender);
547
+ });
548
+
549
+ test("patchRenderPrototype reapplies when version is different (upgrade)", () => {
550
+ const originalRender = (width: number) => [`orig:${width}`];
551
+ const prototype: PatchableUserMessagePrototype = {
552
+ render: (width: number) => [`stale:${width}`],
553
+ __piUserMessageOriginalRender: originalRender,
554
+ __piUserMessageNativePatched: true,
555
+ __piUserMessagePatchVersion: 1,
556
+ };
557
+ patchUserMessageRenderPrototype(prototype, 7, (baseRender) => {
558
+ return function (this: unknown, width: number) {
559
+ return [`v7:${baseRender.call(this, width)}`];
560
+ };
561
+ });
562
+ assert.deepEqual(prototype.render(42), ["v7:orig:42"]);
563
+ assert.equal(prototype.__piUserMessagePatchVersion, 7);
564
+ });
565
+
566
+ test("patchRenderPrototype saves original render when __piUserMessageOriginalRender is absent", () => {
567
+ const originalRender = (width: number) => [`orig:${width}`];
568
+ const prototype: PatchableUserMessagePrototype = {
569
+ render: originalRender,
570
+ };
571
+ patchUserMessageRenderPrototype(prototype, 7, (baseRender) => {
572
+ return function (this: unknown, width: number) {
573
+ return [`patched:${baseRender.call(this, width)}`];
574
+ };
575
+ });
576
+ assert.equal(prototype.__piUserMessageOriginalRender, originalRender);
577
+ assert.notEqual(prototype.render, originalRender);
578
+ assert.deepEqual(prototype.render(10), ["patched:orig:10"]);
579
+ });
580
+
581
+ test("patchRenderPrototype saves original and patches when same version but original undefined", () => {
582
+ const originalRender = (width: number) => [`r:${width}`];
583
+ const prototype: PatchableUserMessagePrototype = {
584
+ render: originalRender,
585
+ __piUserMessageOriginalRender: undefined,
586
+ __piUserMessageNativePatched: true,
587
+ __piUserMessagePatchVersion: 5,
588
+ };
589
+ // Guard requires all three: patched + same version + original IS function.
590
+ // Since original is undefined, the function saves it and applies patch.
591
+ patchUserMessageRenderPrototype(prototype, 5, (baseRender) => {
592
+ return function (this: unknown, width: number) {
593
+ return [`patched:${baseRender.call(this, width)}`];
594
+ };
595
+ });
596
+ assert.equal(prototype.__piUserMessageOriginalRender, originalRender);
597
+ assert.deepEqual(prototype.render(10), ["patched:r:10"]);
598
+ assert.equal(prototype.__piUserMessagePatchVersion, 5);
599
+ });
600
+
601
+ test("patchRenderPrototype saves original and patches when version differs and original undefined", () => {
602
+ const originalRender = (width: number) => [`r:${width}`];
603
+ const prototype: PatchableUserMessagePrototype = {
604
+ render: originalRender,
605
+ __piUserMessageOriginalRender: undefined,
606
+ __piUserMessageNativePatched: true,
607
+ __piUserMessagePatchVersion: 5,
608
+ };
609
+ // Version differs (5 !== 7) so guard doesn't skip.
610
+ // Original is undefined, so the function saves it and applies patch.
611
+ patchUserMessageRenderPrototype(prototype, 7, (baseRender) => {
612
+ return function (this: unknown, width: number) {
613
+ return [`v7:${baseRender.call(this, width)}`];
614
+ };
615
+ });
616
+ assert.equal(prototype.__piUserMessageOriginalRender, originalRender);
617
+ assert.deepEqual(prototype.render(10), ["v7:r:10"]);
618
+ assert.equal(prototype.__piUserMessagePatchVersion, 7);
619
+ });
620
+
621
+ // ===========================================================================
622
+ // patchNativeUserMessagePrototype: width threshold and enable guard
623
+ // ===========================================================================
624
+
625
+ test("nativeRender width < 8 bypasses native rendering", () => {
626
+ let capturedWidth: number | undefined;
627
+ const prototype: PatchableUserMessagePrototype = {
628
+ render: (width: number) => {
629
+ capturedWidth = width;
630
+ return [`orig:${width}`];
631
+ },
632
+ };
633
+ patchNativeUserMessagePrototype(prototype, () => undefined, () => true);
634
+ assert.deepEqual(prototype.render(7), ["orig:7"]);
635
+ assert.equal(capturedWidth, 7);
636
+ });
637
+
638
+ test("nativeRender width exactly 8 triggers native rendering", () => {
639
+ const prototype: PatchableUserMessagePrototype = {
640
+ render: () => ["content"],
641
+ };
642
+ patchNativeUserMessagePrototype(prototype, () => undefined, () => true);
643
+ const rendered = prototype.render(8);
644
+ assert.ok(rendered.some((line) => line.includes("╭")), "should have top border");
645
+ assert.ok(rendered.some((line) => line.includes("╰")), "should have bottom border");
646
+ });
647
+
648
+ test("nativeRender width 0 bypasses native rendering", () => {
649
+ let capturedWidth: number | undefined;
650
+ const prototype: PatchableUserMessagePrototype = {
651
+ render: (width: number) => {
652
+ capturedWidth = width;
653
+ return [`orig:${width}`];
654
+ },
655
+ };
656
+ patchNativeUserMessagePrototype(prototype, () => undefined, () => true);
657
+ assert.deepEqual(prototype.render(0), ["orig:0"]);
658
+ assert.equal(capturedWidth, 0);
659
+ });
660
+
661
+ test("nativeRender negative width bypasses native rendering", () => {
662
+ let capturedWidth: number | undefined;
663
+ const prototype: PatchableUserMessagePrototype = {
664
+ render: (width: number) => {
665
+ capturedWidth = width;
666
+ return [`orig:${width}`];
667
+ },
668
+ };
669
+ patchNativeUserMessagePrototype(prototype, () => undefined, () => true);
670
+ assert.deepEqual(prototype.render(-5), ["orig:0"]);
671
+ assert.equal(capturedWidth, 0);
672
+ });
673
+
674
+ test("nativeRender fractional width floors before threshold check", () => {
675
+ let capturedWidth: number | undefined;
676
+ const prototype: PatchableUserMessagePrototype = {
677
+ render: (width: number) => {
678
+ capturedWidth = width;
679
+ return [`orig:${width}`];
680
+ },
681
+ };
682
+ patchNativeUserMessagePrototype(prototype, () => undefined, () => true);
683
+ // 7.5 floors to 7 → < 8 → bypass
684
+ assert.deepEqual(prototype.render(7.5), ["orig:7"]);
685
+ assert.equal(capturedWidth, 7);
686
+ });
687
+
688
+ test("nativeRender isEnabled false bypasses native rendering regardless of width", () => {
689
+ let capturedWidth: number | undefined;
690
+ const prototype: PatchableUserMessagePrototype = {
691
+ render: (width: number) => {
692
+ capturedWidth = width;
693
+ return [`orig:${width}`];
694
+ },
695
+ };
696
+ patchNativeUserMessagePrototype(prototype, () => undefined, () => false);
697
+ assert.deepEqual(prototype.render(100), ["orig:100"]);
698
+ assert.equal(capturedWidth, 100);
699
+ });
700
+
701
+ test("nativeRender produces top margin spacer and border when enabled and width >= 8", () => {
702
+ const prototype: PatchableUserMessagePrototype = {
703
+ render: () => ["user message body"],
704
+ };
705
+ patchNativeUserMessagePrototype(prototype, () => undefined, () => true);
706
+ const rendered = prototype.render(40);
707
+ assert.equal(rendered[0], "", "first line is top margin spacer");
708
+ assert.ok(rendered[1]?.includes("╭"), "second line has top border");
709
+ assert.ok(rendered.some((l) => l.includes("│")), "has content border lines");
710
+ assert.ok(rendered.some((l) => l.includes("╰")), "has bottom border");
711
+ });
712
+
713
+ test("nativeRender prototype without render function does not crash", () => {
714
+ const prototype: Partial<PatchableUserMessagePrototype> = {};
715
+ patchNativeUserMessagePrototype(
716
+ prototype as PatchableUserMessagePrototype,
717
+ () => undefined,
718
+ () => true,
719
+ );
720
+ assert.equal((prototype as PatchableUserMessagePrototype).render, undefined);
721
+ });
722
+
723
+ test("nativeRender invokes original for empty body content", () => {
724
+ let calledWith = -1;
725
+ const prototype: PatchableUserMessagePrototype = {
726
+ render: (w) => {
727
+ calledWith = w;
728
+ return [];
729
+ },
730
+ };
731
+ patchNativeUserMessagePrototype(prototype, () => undefined, () => true);
732
+ prototype.render(8);
733
+ // original called with content-width = max(1, 8-2-1*2) = max(1, 4) = 4
734
+ assert.equal(calledWith, 4);
735
+ });
736
+
737
+ // ===========================================================================
738
+ // shouldBypassUserMessageMarkdownRebuild edge cases
739
+ // ===========================================================================
740
+
741
+ test("bypass guard allows short text within limits", () => {
742
+ assert.equal(
743
+ shouldBypassUserMessageMarkdownRebuild({ text: "short", theme: {} }),
744
+ false,
745
+ );
746
+ });
747
+
748
+ test("bypass guard triggers on text over 100000 chars", () => {
749
+ assert.equal(
750
+ shouldBypassUserMessageMarkdownRebuild({
751
+ text: "x".repeat(100001),
752
+ theme: {},
753
+ }),
754
+ true,
755
+ );
756
+ });
757
+
758
+ test("bypass guard triggers when line count exceeds 2000", () => {
759
+ assert.equal(
760
+ shouldBypassUserMessageMarkdownRebuild({
761
+ text: `${"line\n".repeat(2000)}tail`,
762
+ theme: {},
763
+ }),
764
+ true,
765
+ );
766
+ });
767
+
768
+ test("bypass guard does NOT bypass exactly 2000 lines (threshold is > 2000)", () => {
769
+ // 1999 newlines = 2000 lines; guard checks > 2000, so 2000 should NOT bypass
770
+ assert.equal(
771
+ shouldBypassUserMessageMarkdownRebuild({
772
+ text: "a\n".repeat(1999) + "a",
773
+ theme: {},
774
+ }),
775
+ false,
776
+ );
777
+ });
778
+
779
+ // ===========================================================================
780
+ // createUserMessageMarkdownLineRenderer cache behavior
781
+ // ===========================================================================
782
+
783
+ test("markdown line renderer cache hits on identical state and width", () => {
784
+ let rendererCreationCount = 0;
785
+ let renderCallCount = 0;
786
+ const renderMarkdown = createUserMessageMarkdownLineRenderer((state) => {
787
+ rendererCreationCount++;
788
+ return {
789
+ render(width: number) {
790
+ renderCallCount++;
791
+ return [`${state.text}:${width}`];
792
+ },
793
+ };
794
+ });
795
+
796
+ const instance = {};
797
+ const theme = { heading: () => "" };
798
+ const state = { text: "cached", theme, defaultTextStyle: { bold: true } };
799
+
800
+ assert.deepEqual(renderMarkdown(instance, state, 24), ["cached:24"]);
801
+ assert.deepEqual(renderMarkdown(instance, state, 24), ["cached:24"]);
802
+ assert.equal(rendererCreationCount, 1);
803
+ assert.equal(renderCallCount, 1);
804
+ });
805
+
806
+ test("markdown line renderer re-renders on width change with same renderer", () => {
807
+ let rendererCreationCount = 0;
808
+ let renderCallCount = 0;
809
+ const renderMarkdown = createUserMessageMarkdownLineRenderer((state) => {
810
+ rendererCreationCount++;
811
+ return {
812
+ render(width: number) {
813
+ renderCallCount++;
814
+ return [`${state.text}:${width}`];
815
+ },
816
+ };
817
+ });
818
+
819
+ const instance = {};
820
+ const theme = { heading: () => "" };
821
+ const state = { text: "width-test", theme };
822
+
823
+ assert.deepEqual(renderMarkdown(instance, state, 10), ["width-test:10"]);
824
+ assert.deepEqual(renderMarkdown(instance, state, 20), ["width-test:20"]);
825
+ assert.equal(rendererCreationCount, 1);
826
+ assert.equal(renderCallCount, 2);
827
+ });
828
+
829
+ test("markdown line renderer creates new renderer on state change", () => {
830
+ let rendererCreationCount = 0;
831
+ const renderMarkdown = createUserMessageMarkdownLineRenderer((state) => {
832
+ rendererCreationCount++;
833
+ return {
834
+ render(_width: number) {
835
+ return [`${state.text}`];
836
+ },
837
+ };
838
+ });
839
+
840
+ const instance = {};
841
+ const theme = { heading: () => "" };
842
+
843
+ assert.deepEqual(renderMarkdown(instance, { text: "a", theme }, 10), ["a"]);
844
+ assert.deepEqual(renderMarkdown(instance, { text: "b", theme }, 10), ["b"]);
845
+ assert.equal(rendererCreationCount, 2);
846
+ });
847
+
848
+ test("markdown line renderer uses separate cache per instance (WeakMap)", () => {
849
+ let rendererCreationCount = 0;
850
+ const renderMarkdown = createUserMessageMarkdownLineRenderer((state) => {
851
+ rendererCreationCount++;
852
+ return {
853
+ render(_width: number) {
854
+ return [`${state.text}`];
855
+ },
856
+ };
857
+ });
858
+
859
+ const instanceA = {};
860
+ const instanceB = {};
861
+ const theme = { heading: () => "" };
862
+ const state = { text: "shared", theme };
863
+
864
+ assert.deepEqual(renderMarkdown(instanceA, state, 10), ["shared"]);
865
+ assert.deepEqual(renderMarkdown(instanceB, state, 10), ["shared"]);
866
+ // Each instance gets its own cache entry, so two renderers created
867
+ assert.equal(rendererCreationCount, 2);
868
+ });
869
+
870
+ // ===========================================================================
871
+ // End-to-end: patchNativeUserMessagePrototype with real theme
872
+ // ===========================================================================
873
+
874
+ test("nativeRender applies theme coloring via fg and bold", () => {
875
+ const prototype: PatchableUserMessagePrototype = {
876
+ render: () => ["hello world"],
877
+ };
878
+ const theme = {
879
+ fg: (_color: string, text: string) => `[${_color}]${text}`,
880
+ bold: (text: string) => `*${text}*`,
881
+ };
882
+ patchNativeUserMessagePrototype(prototype, () => theme, () => true);
883
+
884
+ const rendered = prototype.render(30);
885
+ // Title should be bold + accent-colored
886
+ const titleLine = rendered.find((l) => l.includes("user")) ?? "";
887
+ assert.ok(titleLine.includes("* user *") || titleLine.includes("[accent]"));
888
+ // Border should be border-colored
889
+ const topBorder = rendered.find((l) => l.includes("╭")) ?? "";
890
+ assert.ok(topBorder.includes("[border]"));
891
+ });
892
+
893
+ test("nativeRender builds correct box structure with all required line types", () => {
894
+ const prototype: PatchableUserMessagePrototype = {
895
+ render: () => ["line one", "line two"],
896
+ };
897
+ patchNativeUserMessagePrototype(prototype, () => undefined, () => true);
898
+
899
+ const rendered = prototype.render(30);
900
+ // Structure: [spacer, top-border, padding, content-line, padding, content-line, padding, bottom-border]
901
+ // With vertical padding of 1, each content line gets padding on both sides:
902
+ // But actually, addUserMessageVerticalPadding adds 1 padding before and after ALL content:
903
+ // So: spacer(blank), top-border, blank, content1, content2, blank, bottom-border
904
+ // = 7 lines total
905
+ assert.ok(rendered.length >= 5);
906
+ assert.equal(rendered.filter((l) => l.includes("│")).length, 4); // 2 content + 2 padding
907
+ assert.equal(rendered.filter((l) => l.includes("╭") || l.includes("╰")).length, 2);
908
+ });