gsd-pi 2.34.0-dev.ed0bfbf → 2.35.0-dev.55dcc60

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 (255) hide show
  1. package/dist/resources/extensions/gsd/changelog.js +162 -0
  2. package/dist/resources/extensions/gsd/commands-bootstrap.js +1 -0
  3. package/dist/resources/extensions/gsd/commands-inspect.js +10 -3
  4. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +5 -1
  5. package/dist/resources/extensions/gsd/commands.js +8 -1
  6. package/dist/resources/extensions/gsd/docs/preferences-reference.md +10 -0
  7. package/dist/resources/extensions/gsd/doctor-checks.js +113 -5
  8. package/dist/resources/extensions/gsd/doctor-proactive.js +22 -0
  9. package/dist/resources/extensions/gsd/doctor.js +36 -0
  10. package/dist/resources/extensions/gsd/guided-flow.js +4 -2
  11. package/dist/resources/extensions/gsd/preferences-validation.js +38 -0
  12. package/dist/resources/extensions/gsd/preferences.js +2 -0
  13. package/dist/resources/skills/create-gsd-extension/references/events-reference.md +4 -4
  14. package/package.json +1 -1
  15. package/packages/pi-agent-core/dist/agent-loop.d.ts +14 -0
  16. package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  17. package/packages/pi-agent-core/dist/agent-loop.js +24 -27
  18. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  19. package/packages/pi-agent-core/dist/agent.d.ts +1 -0
  20. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  21. package/packages/pi-agent-core/dist/agent.js +11 -22
  22. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  23. package/packages/pi-agent-core/dist/proxy.d.ts.map +1 -1
  24. package/packages/pi-agent-core/dist/proxy.js +2 -8
  25. package/packages/pi-agent-core/dist/proxy.js.map +1 -1
  26. package/packages/pi-agent-core/src/agent-loop.ts +30 -27
  27. package/packages/pi-agent-core/src/agent.ts +12 -23
  28. package/packages/pi-agent-core/src/proxy.ts +2 -8
  29. package/packages/pi-ai/dist/providers/azure-openai-responses.d.ts.map +1 -1
  30. package/packages/pi-ai/dist/providers/azure-openai-responses.js +5 -41
  31. package/packages/pi-ai/dist/providers/azure-openai-responses.js.map +1 -1
  32. package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  33. package/packages/pi-ai/dist/providers/openai-completions.js +10 -73
  34. package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
  35. package/packages/pi-ai/dist/providers/openai-responses.d.ts.map +1 -1
  36. package/packages/pi-ai/dist/providers/openai-responses.js +8 -79
  37. package/packages/pi-ai/dist/providers/openai-responses.js.map +1 -1
  38. package/packages/pi-ai/dist/providers/openai-shared.d.ts +65 -0
  39. package/packages/pi-ai/dist/providers/openai-shared.d.ts.map +1 -0
  40. package/packages/pi-ai/dist/providers/openai-shared.js +146 -0
  41. package/packages/pi-ai/dist/providers/openai-shared.js.map +1 -0
  42. package/packages/pi-ai/dist/utils/oauth/google-antigravity.d.ts.map +1 -1
  43. package/packages/pi-ai/dist/utils/oauth/google-antigravity.js +7 -135
  44. package/packages/pi-ai/dist/utils/oauth/google-antigravity.js.map +1 -1
  45. package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.d.ts.map +1 -1
  46. package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.js +7 -135
  47. package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.js.map +1 -1
  48. package/packages/pi-ai/dist/utils/oauth/google-oauth-utils.d.ts +46 -0
  49. package/packages/pi-ai/dist/utils/oauth/google-oauth-utils.d.ts.map +1 -0
  50. package/packages/pi-ai/dist/utils/oauth/google-oauth-utils.js +160 -0
  51. package/packages/pi-ai/dist/utils/oauth/google-oauth-utils.js.map +1 -0
  52. package/packages/pi-ai/src/providers/azure-openai-responses.ts +11 -45
  53. package/packages/pi-ai/src/providers/openai-completions.ts +16 -86
  54. package/packages/pi-ai/src/providers/openai-responses.ts +15 -95
  55. package/packages/pi-ai/src/providers/openai-shared.ts +193 -0
  56. package/packages/pi-ai/src/utils/oauth/google-antigravity.ts +14 -162
  57. package/packages/pi-ai/src/utils/oauth/google-gemini-cli.ts +13 -161
  58. package/packages/pi-ai/src/utils/oauth/google-oauth-utils.ts +201 -0
  59. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +16 -63
  60. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  61. package/packages/pi-coding-agent/dist/core/agent-session.js +104 -641
  62. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  63. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +0 -1
  64. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  65. package/packages/pi-coding-agent/dist/core/auth-storage.js +4 -35
  66. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  67. package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  68. package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.js +5 -43
  69. package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.js.map +1 -1
  70. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  71. package/packages/pi-coding-agent/dist/core/compaction/compaction.js +11 -69
  72. package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  73. package/packages/pi-coding-agent/dist/core/compaction/utils.d.ts +40 -0
  74. package/packages/pi-coding-agent/dist/core/compaction/utils.d.ts.map +1 -1
  75. package/packages/pi-coding-agent/dist/core/compaction/utils.js +78 -0
  76. package/packages/pi-coding-agent/dist/core/compaction/utils.js.map +1 -1
  77. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts +77 -0
  78. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts.map +1 -0
  79. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js +331 -0
  80. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js.map +1 -0
  81. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +2 -2
  82. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
  83. package/packages/pi-coding-agent/dist/core/extensions/index.js +1 -1
  84. package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
  85. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +15 -0
  86. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  87. package/packages/pi-coding-agent/dist/core/extensions/runner.js +129 -243
  88. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  89. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +49 -42
  90. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  91. package/packages/pi-coding-agent/dist/core/extensions/types.js +2 -21
  92. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  93. package/packages/pi-coding-agent/dist/core/lock-utils.d.ts +39 -0
  94. package/packages/pi-coding-agent/dist/core/lock-utils.d.ts.map +1 -0
  95. package/packages/pi-coding-agent/dist/core/lock-utils.js +89 -0
  96. package/packages/pi-coding-agent/dist/core/lock-utils.js.map +1 -0
  97. package/packages/pi-coding-agent/dist/core/lsp/config.d.ts +2 -0
  98. package/packages/pi-coding-agent/dist/core/lsp/config.d.ts.map +1 -1
  99. package/packages/pi-coding-agent/dist/core/lsp/config.js +4 -1
  100. package/packages/pi-coding-agent/dist/core/lsp/config.js.map +1 -1
  101. package/packages/pi-coding-agent/dist/core/lsp/index.d.ts.map +1 -1
  102. package/packages/pi-coding-agent/dist/core/lsp/index.js +52 -107
  103. package/packages/pi-coding-agent/dist/core/lsp/index.js.map +1 -1
  104. package/packages/pi-coding-agent/dist/core/lsp/lspmux.d.ts.map +1 -1
  105. package/packages/pi-coding-agent/dist/core/lsp/lspmux.js +2 -21
  106. package/packages/pi-coding-agent/dist/core/lsp/lspmux.js.map +1 -1
  107. package/packages/pi-coding-agent/dist/core/lsp/types.d.ts +0 -1
  108. package/packages/pi-coding-agent/dist/core/lsp/types.d.ts.map +1 -1
  109. package/packages/pi-coding-agent/dist/core/lsp/types.js +0 -28
  110. package/packages/pi-coding-agent/dist/core/lsp/types.js.map +1 -1
  111. package/packages/pi-coding-agent/dist/core/package-manager.d.ts.map +1 -1
  112. package/packages/pi-coding-agent/dist/core/package-manager.js +2 -4
  113. package/packages/pi-coding-agent/dist/core/package-manager.js.map +1 -1
  114. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts +2 -4
  115. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
  116. package/packages/pi-coding-agent/dist/core/resource-loader.js +33 -58
  117. package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
  118. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts +87 -0
  119. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -0
  120. package/packages/pi-coding-agent/dist/core/retry-handler.js +295 -0
  121. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -0
  122. package/packages/pi-coding-agent/dist/core/session-manager.d.ts +0 -1
  123. package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
  124. package/packages/pi-coding-agent/dist/core/session-manager.js +3 -28
  125. package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
  126. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +8 -0
  127. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  128. package/packages/pi-coding-agent/dist/core/settings-manager.js +76 -166
  129. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  130. package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
  131. package/packages/pi-coding-agent/dist/core/skills.js +1 -3
  132. package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
  133. package/packages/pi-coding-agent/dist/index.d.ts +1 -1
  134. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  135. package/packages/pi-coding-agent/dist/index.js +1 -1
  136. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  137. package/packages/pi-coding-agent/dist/modes/interactive/components/session-selector.d.ts +1 -1
  138. package/packages/pi-coding-agent/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  139. package/packages/pi-coding-agent/dist/modes/interactive/components/session-selector.js +9 -26
  140. package/packages/pi-coding-agent/dist/modes/interactive/components/session-selector.js.map +1 -1
  141. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  142. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +1 -13
  143. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  144. package/packages/pi-coding-agent/dist/modes/interactive/components/tree-render-utils.d.ts +44 -0
  145. package/packages/pi-coding-agent/dist/modes/interactive/components/tree-render-utils.d.ts.map +1 -0
  146. package/packages/pi-coding-agent/dist/modes/interactive/components/tree-render-utils.js +61 -0
  147. package/packages/pi-coding-agent/dist/modes/interactive/components/tree-render-utils.js.map +1 -0
  148. package/packages/pi-coding-agent/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  149. package/packages/pi-coding-agent/dist/modes/interactive/components/tree-selector.js +6 -9
  150. package/packages/pi-coding-agent/dist/modes/interactive/components/tree-selector.js.map +1 -1
  151. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts +65 -0
  152. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  153. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js +6 -16
  154. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
  155. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.d.ts +12 -0
  156. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.d.ts.map +1 -0
  157. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +175 -0
  158. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -0
  159. package/packages/pi-coding-agent/dist/modes/interactive/utils/shorten-path.d.ts +6 -0
  160. package/packages/pi-coding-agent/dist/modes/interactive/utils/shorten-path.d.ts.map +1 -0
  161. package/packages/pi-coding-agent/dist/modes/interactive/utils/shorten-path.js +15 -0
  162. package/packages/pi-coding-agent/dist/modes/interactive/utils/shorten-path.js.map +1 -0
  163. package/packages/pi-coding-agent/dist/modes/print-mode.d.ts.map +1 -1
  164. package/packages/pi-coding-agent/dist/modes/print-mode.js +2 -30
  165. package/packages/pi-coding-agent/dist/modes/print-mode.js.map +1 -1
  166. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  167. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js +2 -28
  168. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js.map +1 -1
  169. package/packages/pi-coding-agent/dist/modes/shared/command-context-actions.d.ts +19 -0
  170. package/packages/pi-coding-agent/dist/modes/shared/command-context-actions.d.ts.map +1 -0
  171. package/packages/pi-coding-agent/dist/modes/shared/command-context-actions.js +45 -0
  172. package/packages/pi-coding-agent/dist/modes/shared/command-context-actions.js.map +1 -0
  173. package/packages/pi-coding-agent/dist/utils/error.d.ts +5 -0
  174. package/packages/pi-coding-agent/dist/utils/error.d.ts.map +1 -0
  175. package/packages/pi-coding-agent/dist/utils/error.js +7 -0
  176. package/packages/pi-coding-agent/dist/utils/error.js.map +1 -0
  177. package/packages/pi-coding-agent/package.json +1 -1
  178. package/packages/pi-coding-agent/src/core/agent-session.ts +117 -745
  179. package/packages/pi-coding-agent/src/core/auth-storage.ts +4 -38
  180. package/packages/pi-coding-agent/src/core/compaction/branch-summarization.ts +7 -53
  181. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +14 -74
  182. package/packages/pi-coding-agent/src/core/compaction/utils.ts +100 -0
  183. package/packages/pi-coding-agent/src/core/compaction-orchestrator.ts +424 -0
  184. package/packages/pi-coding-agent/src/core/extensions/index.ts +1 -21
  185. package/packages/pi-coding-agent/src/core/extensions/runner.ts +119 -243
  186. package/packages/pi-coding-agent/src/core/extensions/types.ts +50 -69
  187. package/packages/pi-coding-agent/src/core/lock-utils.ts +113 -0
  188. package/packages/pi-coding-agent/src/core/lsp/config.ts +4 -1
  189. package/packages/pi-coding-agent/src/core/lsp/index.ts +83 -152
  190. package/packages/pi-coding-agent/src/core/lsp/lspmux.ts +2 -22
  191. package/packages/pi-coding-agent/src/core/lsp/types.ts +0 -29
  192. package/packages/pi-coding-agent/src/core/package-manager.ts +1 -4
  193. package/packages/pi-coding-agent/src/core/resource-loader.ts +43 -67
  194. package/packages/pi-coding-agent/src/core/retry-handler.ts +359 -0
  195. package/packages/pi-coding-agent/src/core/session-manager.ts +3 -30
  196. package/packages/pi-coding-agent/src/core/settings-manager.ts +85 -164
  197. package/packages/pi-coding-agent/src/core/skills.ts +1 -4
  198. package/packages/pi-coding-agent/src/index.ts +1 -7
  199. package/packages/pi-coding-agent/src/modes/interactive/components/session-selector.ts +17 -29
  200. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +1 -13
  201. package/packages/pi-coding-agent/src/modes/interactive/components/tree-render-utils.ts +81 -0
  202. package/packages/pi-coding-agent/src/modes/interactive/components/tree-selector.ts +14 -19
  203. package/packages/pi-coding-agent/src/modes/interactive/theme/theme.ts +7 -18
  204. package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +196 -0
  205. package/packages/pi-coding-agent/src/modes/interactive/utils/shorten-path.ts +14 -0
  206. package/packages/pi-coding-agent/src/modes/print-mode.ts +2 -30
  207. package/packages/pi-coding-agent/src/modes/rpc/rpc-mode.ts +2 -28
  208. package/packages/pi-coding-agent/src/modes/shared/command-context-actions.ts +53 -0
  209. package/packages/pi-coding-agent/src/utils/error.ts +6 -0
  210. package/packages/pi-tui/dist/components/markdown.d.ts +5 -0
  211. package/packages/pi-tui/dist/components/markdown.d.ts.map +1 -1
  212. package/packages/pi-tui/dist/components/markdown.js +25 -31
  213. package/packages/pi-tui/dist/components/markdown.js.map +1 -1
  214. package/packages/pi-tui/dist/keys.d.ts +0 -4
  215. package/packages/pi-tui/dist/keys.d.ts.map +1 -1
  216. package/packages/pi-tui/dist/keys.js +94 -162
  217. package/packages/pi-tui/dist/keys.js.map +1 -1
  218. package/packages/pi-tui/src/components/markdown.ts +25 -29
  219. package/packages/pi-tui/src/keys.ts +94 -173
  220. package/pkg/dist/modes/interactive/theme/theme.d.ts +65 -0
  221. package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  222. package/pkg/dist/modes/interactive/theme/theme.js +6 -16
  223. package/pkg/dist/modes/interactive/theme/theme.js.map +1 -1
  224. package/pkg/dist/modes/interactive/theme/themes.d.ts +12 -0
  225. package/pkg/dist/modes/interactive/theme/themes.d.ts.map +1 -0
  226. package/pkg/dist/modes/interactive/theme/themes.js +175 -0
  227. package/pkg/dist/modes/interactive/theme/themes.js.map +1 -0
  228. package/pkg/package.json +1 -1
  229. package/src/resources/extensions/gsd/changelog.ts +213 -0
  230. package/src/resources/extensions/gsd/commands-bootstrap.ts +1 -0
  231. package/src/resources/extensions/gsd/commands-inspect.ts +10 -3
  232. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +5 -1
  233. package/src/resources/extensions/gsd/commands.ts +9 -1
  234. package/src/resources/extensions/gsd/docs/preferences-reference.md +10 -0
  235. package/src/resources/extensions/gsd/doctor-checks.ts +107 -5
  236. package/src/resources/extensions/gsd/doctor-proactive.ts +24 -0
  237. package/src/resources/extensions/gsd/doctor-types.ts +9 -1
  238. package/src/resources/extensions/gsd/doctor.ts +35 -0
  239. package/src/resources/extensions/gsd/guided-flow.ts +4 -2
  240. package/src/resources/extensions/gsd/preferences-validation.ts +38 -0
  241. package/src/resources/extensions/gsd/preferences.ts +2 -0
  242. package/src/resources/extensions/gsd/tests/commands-inspect-open-db.test.ts +46 -0
  243. package/src/resources/extensions/gsd/tests/doctor-git.test.ts +98 -2
  244. package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +59 -3
  245. package/src/resources/extensions/gsd/tests/preferences.test.ts +28 -0
  246. package/src/resources/skills/create-gsd-extension/references/events-reference.md +4 -4
  247. package/packages/pi-coding-agent/dist/modes/interactive/theme/dark.json +0 -85
  248. package/packages/pi-coding-agent/dist/modes/interactive/theme/light.json +0 -84
  249. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.json +0 -335
  250. package/packages/pi-coding-agent/src/modes/interactive/theme/dark.json +0 -85
  251. package/packages/pi-coding-agent/src/modes/interactive/theme/light.json +0 -84
  252. package/packages/pi-coding-agent/src/modes/interactive/theme/theme-schema.json +0 -335
  253. package/pkg/dist/modes/interactive/theme/dark.json +0 -85
  254. package/pkg/dist/modes/interactive/theme/light.json +0 -84
  255. package/pkg/dist/modes/interactive/theme/theme-schema.json +0 -335
@@ -0,0 +1,81 @@
1
+ import { truncateToWidth } from "@gsd/pi-tui";
2
+ import { theme } from "../theme/theme.js";
3
+
4
+ // ── Tree connector characters ────────────────────────────────────────
5
+ export const TREE_BRANCH = "\u251C\u2500 "; // "├─ "
6
+ export const TREE_LAST = "\u2514\u2500 "; // "└─ "
7
+ export const TREE_PIPE = "\u2502 "; // "│ "
8
+ export const TREE_SPACE = " "; // 3 spaces
9
+
10
+ /**
11
+ * Build a tree prefix string from ancestor-continuation flags and branch position.
12
+ *
13
+ * Each ancestor level contributes either a pipe ("│ ") or blank spacing (" ")
14
+ * depending on whether that ancestor has more siblings after it. The final segment
15
+ * is the branch connector: "├─ " (more siblings) or "└─ " (last sibling).
16
+ *
17
+ * Used by session-selector for its simpler flat tree display.
18
+ * tree-selector uses its own gutter-based char-by-char builder for richer rendering.
19
+ */
20
+ export function buildTreePrefix(ancestorContinues: boolean[], isLast: boolean, depth: number): string {
21
+ if (depth === 0) return "";
22
+ const parts = ancestorContinues.map((continues) => (continues ? TREE_PIPE : TREE_SPACE));
23
+ const branch = isLast ? TREE_LAST : TREE_BRANCH;
24
+ return parts.join("") + branch;
25
+ }
26
+
27
+ // ── Scroll window ────────────────────────────────────────────────────
28
+
29
+ export interface ScrollWindow {
30
+ /** First visible index (inclusive) */
31
+ startIndex: number;
32
+ /** Last visible index (exclusive) */
33
+ endIndex: number;
34
+ }
35
+
36
+ /**
37
+ * Compute a centered scroll window around `selectedIndex` within a list of `totalItems`.
38
+ *
39
+ * The window tries to center the selected item. When near the beginning or end of the
40
+ * list the window clamps so it doesn't exceed bounds.
41
+ */
42
+ export function computeScrollWindow(selectedIndex: number, totalItems: number, maxVisible: number): ScrollWindow {
43
+ const startIndex = Math.max(0, Math.min(selectedIndex - Math.floor(maxVisible / 2), totalItems - maxVisible));
44
+ const endIndex = Math.min(startIndex + maxVisible, totalItems);
45
+ return { startIndex, endIndex };
46
+ }
47
+
48
+ // ── Cursor & selection helpers ───────────────────────────────────────
49
+
50
+ /**
51
+ * Return the cursor indicator for a list row.
52
+ *
53
+ * Selected: "› " (accent-colored)
54
+ * Unselected: " " (two spaces, matching width)
55
+ */
56
+ export function renderCursor(isSelected: boolean): string {
57
+ return isSelected ? theme.fg("accent", "\u203A ") : " ";
58
+ }
59
+
60
+ /**
61
+ * Apply selected-row background highlight and truncate to `width`.
62
+ */
63
+ export function applyRowHighlight(line: string, isSelected: boolean, width: number): string {
64
+ const truncated = truncateToWidth(line, width);
65
+ return isSelected ? theme.bg("selectedBg", truncated) : truncated;
66
+ }
67
+
68
+ // ── Scroll position indicator ────────────────────────────────────────
69
+
70
+ /**
71
+ * Render a muted "(current/total)" position indicator, optionally with a suffix label.
72
+ */
73
+ export function renderScrollPosition(
74
+ selectedIndex: number,
75
+ totalItems: number,
76
+ width: number,
77
+ suffixLabel?: string,
78
+ ): string {
79
+ const suffix = suffixLabel ?? "";
80
+ return truncateToWidth(theme.fg("muted", ` (${selectedIndex + 1}/${totalItems})${suffix}`), width);
81
+ }
@@ -14,6 +14,12 @@ import type { SessionTreeNode } from "../../../core/session-manager.js";
14
14
  import { theme } from "../theme/theme.js";
15
15
  import { DynamicBorder } from "./dynamic-border.js";
16
16
  import { keyHint } from "./keybinding-hints.js";
17
+ import {
18
+ applyRowHighlight,
19
+ computeScrollWindow,
20
+ renderCursor,
21
+ renderScrollPosition,
22
+ } from "./tree-render-utils.js";
17
23
 
18
24
  /** Gutter info: position (displayIndent where connector was) and whether to show │ */
19
25
  interface GutterInfo {
@@ -595,14 +601,11 @@ class TreeList implements Component {
595
601
  return lines;
596
602
  }
597
603
 
598
- const startIndex = Math.max(
599
- 0,
600
- Math.min(
601
- this.selectedIndex - Math.floor(this.maxVisibleLines / 2),
602
- this.filteredNodes.length - this.maxVisibleLines,
603
- ),
604
+ const { startIndex, endIndex } = computeScrollWindow(
605
+ this.selectedIndex,
606
+ this.filteredNodes.length,
607
+ this.maxVisibleLines,
604
608
  );
605
- const endIndex = Math.min(startIndex + this.maxVisibleLines, this.filteredNodes.length);
606
609
 
607
610
  for (let i = startIndex; i < endIndex; i++) {
608
611
  const flatNode = this.filteredNodes[i];
@@ -610,7 +613,7 @@ class TreeList implements Component {
610
613
  const isSelected = i === this.selectedIndex;
611
614
 
612
615
  // Build line: cursor + prefix + path marker + label + content
613
- const cursor = isSelected ? theme.fg("accent", "› ") : " ";
616
+ const cursor = renderCursor(isSelected);
614
617
 
615
618
  // If multiple roots, shift display (roots at 0, not 1)
616
619
  const displayIndent = this.multipleRoots ? Math.max(0, flatNode.indent - 1) : flatNode.indent;
@@ -664,19 +667,11 @@ class TreeList implements Component {
664
667
  const label = flatNode.node.label ? theme.fg("warning", `[${flatNode.node.label}] `) : "";
665
668
  const content = this.getEntryDisplayText(flatNode.node, isSelected);
666
669
 
667
- let line = cursor + theme.fg("dim", prefix) + foldMarker + pathMarker + label + content;
668
- if (isSelected) {
669
- line = theme.bg("selectedBg", line);
670
- }
671
- lines.push(truncateToWidth(line, width));
670
+ const line = cursor + theme.fg("dim", prefix) + foldMarker + pathMarker + label + content;
671
+ lines.push(applyRowHighlight(line, isSelected, width));
672
672
  }
673
673
 
674
- lines.push(
675
- truncateToWidth(
676
- theme.fg("muted", ` (${this.selectedIndex + 1}/${this.filteredNodes.length})${this.getFilterLabel()}`),
677
- width,
678
- ),
679
- );
674
+ lines.push(renderScrollPosition(this.selectedIndex, this.filteredNodes.length, width, this.getFilterLabel()));
680
675
 
681
676
  return lines;
682
677
  }
@@ -9,7 +9,8 @@ import {
9
9
  supportsLanguage,
10
10
  type HighlightColors,
11
11
  } from "@gsd/native";
12
- import { getCustomThemesDir, getThemesDir } from "../../../config.js";
12
+ import { getCustomThemesDir } from "../../../config.js";
13
+ import { builtinThemes } from "./themes.js";
13
14
 
14
15
  // Issue #453: native preview highlighting can wedge the entire interactive
15
16
  // session after a successful file tool. Keep the safer plain-text path as the
@@ -100,7 +101,7 @@ const ThemeJsonSchema = Type.Object({
100
101
  ),
101
102
  });
102
103
 
103
- type ThemeJson = Static<typeof ThemeJsonSchema>;
104
+ export type ThemeJson = Static<typeof ThemeJsonSchema>;
104
105
 
105
106
  const validateThemeJson = TypeCompiler.Compile(ThemeJsonSchema);
106
107
 
@@ -450,19 +451,8 @@ export class Theme {
450
451
  // Theme Loading
451
452
  // ============================================================================
452
453
 
453
- let BUILTIN_THEMES: Record<string, ThemeJson> | undefined;
454
-
455
454
  function getBuiltinThemes(): Record<string, ThemeJson> {
456
- if (!BUILTIN_THEMES) {
457
- const themesDir = getThemesDir();
458
- const darkPath = path.join(themesDir, "dark.json");
459
- const lightPath = path.join(themesDir, "light.json");
460
- BUILTIN_THEMES = {
461
- dark: JSON.parse(fs.readFileSync(darkPath, "utf-8")) as ThemeJson,
462
- light: JSON.parse(fs.readFileSync(lightPath, "utf-8")) as ThemeJson,
463
- };
464
- }
465
- return BUILTIN_THEMES;
455
+ return builtinThemes;
466
456
  }
467
457
 
468
458
  export function getAvailableThemes(): string[] {
@@ -488,13 +478,12 @@ export interface ThemeInfo {
488
478
  }
489
479
 
490
480
  export function getAvailableThemesWithPaths(): ThemeInfo[] {
491
- const themesDir = getThemesDir();
492
481
  const customThemesDir = getCustomThemesDir();
493
482
  const result: ThemeInfo[] = [];
494
483
 
495
- // Built-in themes
484
+ // Built-in themes (embedded in code, no file path)
496
485
  for (const name of Object.keys(getBuiltinThemes())) {
497
- result.push({ name, path: path.join(themesDir, `${name}.json`) });
486
+ result.push({ name, path: undefined });
498
487
  }
499
488
 
500
489
  // Custom themes
@@ -539,7 +528,7 @@ function parseThemeJson(label: string, json: unknown): ThemeJson {
539
528
  errorMessage += "\nMissing required color tokens:\n";
540
529
  errorMessage += missingColors.map((c) => ` - ${c}`).join("\n");
541
530
  errorMessage += '\n\nPlease add these colors to your theme\'s "colors" object.';
542
- errorMessage += "\nSee the built-in themes (dark.json, light.json) for reference values.";
531
+ errorMessage += "\nSee the built-in dark/light themes for reference values.";
543
532
  }
544
533
  if (otherErrors.length > 0) {
545
534
  errorMessage += `\n\nOther errors:\n${otherErrors.join("\n")}`;
@@ -0,0 +1,196 @@
1
+ /**
2
+ * Built-in theme definitions.
3
+ *
4
+ * Each theme is a self-contained record of color values. Variable references
5
+ * (e.g. "accent") are resolved against the `vars` map at load time by the
6
+ * theme engine in theme.ts.
7
+ *
8
+ * To add a new built-in theme, add an entry to `builtinThemes` below.
9
+ */
10
+
11
+ // Re-use the ThemeJson type from the schema defined in theme.ts.
12
+ // We import only the type to avoid circular runtime dependencies.
13
+ import type { ThemeJson } from "./theme.js";
14
+
15
+ // ---------------------------------------------------------------------------
16
+ // Dark theme
17
+ // ---------------------------------------------------------------------------
18
+
19
+ const dark: ThemeJson = {
20
+ name: "dark",
21
+ vars: {
22
+ cyan: "#00d7ff",
23
+ blue: "#5f87ff",
24
+ green: "#b5bd68",
25
+ red: "#cc6666",
26
+ yellow: "#ffff00",
27
+ gray: "#808080",
28
+ dimGray: "#666666",
29
+ darkGray: "#505050",
30
+ accent: "#8abeb7",
31
+ selectedBg: "#3a3a4a",
32
+ userMsgBg: "#343541",
33
+ toolPendingBg: "#282832",
34
+ toolSuccessBg: "#283228",
35
+ toolErrorBg: "#3c2828",
36
+ customMsgBg: "#2d2838",
37
+ },
38
+ colors: {
39
+ accent: "accent",
40
+ border: "blue",
41
+ borderAccent: "cyan",
42
+ borderMuted: "darkGray",
43
+ success: "green",
44
+ error: "red",
45
+ warning: "yellow",
46
+ muted: "gray",
47
+ dim: "dimGray",
48
+ text: "",
49
+ thinkingText: "gray",
50
+
51
+ selectedBg: "selectedBg",
52
+ userMessageBg: "userMsgBg",
53
+ userMessageText: "",
54
+ customMessageBg: "customMsgBg",
55
+ customMessageText: "",
56
+ customMessageLabel: "#9575cd",
57
+ toolPendingBg: "toolPendingBg",
58
+ toolSuccessBg: "toolSuccessBg",
59
+ toolErrorBg: "toolErrorBg",
60
+ toolTitle: "",
61
+ toolOutput: "gray",
62
+
63
+ mdHeading: "#f0c674",
64
+ mdLink: "#81a2be",
65
+ mdLinkUrl: "dimGray",
66
+ mdCode: "accent",
67
+ mdCodeBlock: "green",
68
+ mdCodeBlockBorder: "gray",
69
+ mdQuote: "gray",
70
+ mdQuoteBorder: "gray",
71
+ mdHr: "gray",
72
+ mdListBullet: "accent",
73
+
74
+ toolDiffAdded: "green",
75
+ toolDiffRemoved: "red",
76
+ toolDiffContext: "gray",
77
+
78
+ syntaxComment: "#6A9955",
79
+ syntaxKeyword: "#569CD6",
80
+ syntaxFunction: "#DCDCAA",
81
+ syntaxVariable: "#9CDCFE",
82
+ syntaxString: "#CE9178",
83
+ syntaxNumber: "#B5CEA8",
84
+ syntaxType: "#4EC9B0",
85
+ syntaxOperator: "#D4D4D4",
86
+ syntaxPunctuation: "#D4D4D4",
87
+
88
+ thinkingOff: "darkGray",
89
+ thinkingMinimal: "#6e6e6e",
90
+ thinkingLow: "#5f87af",
91
+ thinkingMedium: "#81a2be",
92
+ thinkingHigh: "#b294bb",
93
+ thinkingXhigh: "#d183e8",
94
+
95
+ bashMode: "green",
96
+ },
97
+ export: {
98
+ pageBg: "#18181e",
99
+ cardBg: "#1e1e24",
100
+ infoBg: "#3c3728",
101
+ },
102
+ };
103
+
104
+ // ---------------------------------------------------------------------------
105
+ // Light theme
106
+ // ---------------------------------------------------------------------------
107
+
108
+ const light: ThemeJson = {
109
+ name: "light",
110
+ vars: {
111
+ teal: "#5a8080",
112
+ blue: "#547da7",
113
+ green: "#588458",
114
+ red: "#aa5555",
115
+ yellow: "#9a7326",
116
+ mediumGray: "#6c6c6c",
117
+ dimGray: "#767676",
118
+ lightGray: "#b0b0b0",
119
+ selectedBg: "#d0d0e0",
120
+ userMsgBg: "#e8e8e8",
121
+ toolPendingBg: "#e8e8f0",
122
+ toolSuccessBg: "#e8f0e8",
123
+ toolErrorBg: "#f0e8e8",
124
+ customMsgBg: "#ede7f6",
125
+ },
126
+ colors: {
127
+ accent: "teal",
128
+ border: "blue",
129
+ borderAccent: "teal",
130
+ borderMuted: "lightGray",
131
+ success: "green",
132
+ error: "red",
133
+ warning: "yellow",
134
+ muted: "mediumGray",
135
+ dim: "dimGray",
136
+ text: "",
137
+ thinkingText: "mediumGray",
138
+
139
+ selectedBg: "selectedBg",
140
+ userMessageBg: "userMsgBg",
141
+ userMessageText: "",
142
+ customMessageBg: "customMsgBg",
143
+ customMessageText: "",
144
+ customMessageLabel: "#7e57c2",
145
+ toolPendingBg: "toolPendingBg",
146
+ toolSuccessBg: "toolSuccessBg",
147
+ toolErrorBg: "toolErrorBg",
148
+ toolTitle: "",
149
+ toolOutput: "mediumGray",
150
+
151
+ mdHeading: "yellow",
152
+ mdLink: "blue",
153
+ mdLinkUrl: "dimGray",
154
+ mdCode: "teal",
155
+ mdCodeBlock: "green",
156
+ mdCodeBlockBorder: "mediumGray",
157
+ mdQuote: "mediumGray",
158
+ mdQuoteBorder: "mediumGray",
159
+ mdHr: "mediumGray",
160
+ mdListBullet: "green",
161
+
162
+ toolDiffAdded: "green",
163
+ toolDiffRemoved: "red",
164
+ toolDiffContext: "mediumGray",
165
+
166
+ syntaxComment: "#008000",
167
+ syntaxKeyword: "#0000FF",
168
+ syntaxFunction: "#795E26",
169
+ syntaxVariable: "#001080",
170
+ syntaxString: "#A31515",
171
+ syntaxNumber: "#098658",
172
+ syntaxType: "#267F99",
173
+ syntaxOperator: "#000000",
174
+ syntaxPunctuation: "#000000",
175
+
176
+ thinkingOff: "lightGray",
177
+ thinkingMinimal: "#767676",
178
+ thinkingLow: "blue",
179
+ thinkingMedium: "teal",
180
+ thinkingHigh: "#875f87",
181
+ thinkingXhigh: "#8b008b",
182
+
183
+ bashMode: "green",
184
+ },
185
+ export: {
186
+ pageBg: "#f8f8f8",
187
+ cardBg: "#ffffff",
188
+ infoBg: "#fffae6",
189
+ },
190
+ };
191
+
192
+ // ---------------------------------------------------------------------------
193
+ // Export
194
+ // ---------------------------------------------------------------------------
195
+
196
+ export const builtinThemes: Record<string, ThemeJson> = { dark, light };
@@ -0,0 +1,14 @@
1
+ import * as os from "node:os";
2
+
3
+ /**
4
+ * Convert absolute path to tilde notation if it's in home directory.
5
+ * Returns empty string for non-string or empty inputs.
6
+ */
7
+ export function shortenPath(path: unknown): string {
8
+ if (typeof path !== "string" || !path) return "";
9
+ const home = os.homedir();
10
+ if (path.startsWith(home)) {
11
+ return `~${path.slice(home.length)}`;
12
+ }
13
+ return path;
14
+ }
@@ -8,6 +8,7 @@
8
8
 
9
9
  import type { AssistantMessage, ImageContent } from "@gsd/pi-ai";
10
10
  import type { AgentSession } from "../core/agent-session.js";
11
+ import { createDefaultCommandContextActions } from "./shared/command-context-actions.js";
11
12
 
12
13
  /**
13
14
  * Options for print mode.
@@ -37,36 +38,7 @@ export async function runPrintMode(session: AgentSession, options: PrintModeOpti
37
38
  }
38
39
  // Set up extensions for print mode (no UI)
39
40
  await session.bindExtensions({
40
- commandContextActions: {
41
- waitForIdle: () => session.agent.waitForIdle(),
42
- newSession: async (options) => {
43
- const success = await session.newSession({ parentSession: options?.parentSession });
44
- if (success && options?.setup) {
45
- await options.setup(session.sessionManager);
46
- }
47
- return { cancelled: !success };
48
- },
49
- fork: async (entryId) => {
50
- const result = await session.fork(entryId);
51
- return { cancelled: result.cancelled };
52
- },
53
- navigateTree: async (targetId, options) => {
54
- const result = await session.navigateTree(targetId, {
55
- summarize: options?.summarize,
56
- customInstructions: options?.customInstructions,
57
- replaceInstructions: options?.replaceInstructions,
58
- label: options?.label,
59
- });
60
- return { cancelled: result.cancelled };
61
- },
62
- switchSession: async (sessionPath) => {
63
- const success = await session.switchSession(sessionPath);
64
- return { cancelled: !success };
65
- },
66
- reload: async () => {
67
- await session.reload();
68
- },
69
- },
41
+ commandContextActions: createDefaultCommandContextActions(session),
70
42
  onError: (err) => {
71
43
  console.error(`Extension error (${err.extensionPath}): ${err.error}`);
72
44
  },
@@ -19,6 +19,7 @@ import type {
19
19
  ExtensionWidgetOptions,
20
20
  } from "../../core/extensions/index.js";
21
21
  import { type Theme, theme } from "../interactive/theme/theme.js";
22
+ import { createDefaultCommandContextActions } from "../shared/command-context-actions.js";
22
23
  import { attachJsonlLineReader, serializeJsonLine } from "./jsonl.js";
23
24
  import type {
24
25
  RpcCommand,
@@ -285,34 +286,7 @@ export async function runRpcMode(session: AgentSession): Promise<never> {
285
286
  // Set up extensions with RPC-based UI context
286
287
  await session.bindExtensions({
287
288
  uiContext: createExtensionUIContext(),
288
- commandContextActions: {
289
- waitForIdle: () => session.agent.waitForIdle(),
290
- newSession: async (options) => {
291
- // Delegate to AgentSession (handles setup + agent state sync)
292
- const success = await session.newSession(options);
293
- return { cancelled: !success };
294
- },
295
- fork: async (entryId) => {
296
- const result = await session.fork(entryId);
297
- return { cancelled: result.cancelled };
298
- },
299
- navigateTree: async (targetId, options) => {
300
- const result = await session.navigateTree(targetId, {
301
- summarize: options?.summarize,
302
- customInstructions: options?.customInstructions,
303
- replaceInstructions: options?.replaceInstructions,
304
- label: options?.label,
305
- });
306
- return { cancelled: result.cancelled };
307
- },
308
- switchSession: async (sessionPath) => {
309
- const success = await session.switchSession(sessionPath);
310
- return { cancelled: !success };
311
- },
312
- reload: async () => {
313
- await session.reload();
314
- },
315
- },
289
+ commandContextActions: createDefaultCommandContextActions(session),
316
290
  shutdownHandler: () => {
317
291
  shutdownRequested = true;
318
292
  },
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Default (headless) implementations of ExtensionCommandContextActions.
3
+ *
4
+ * These delegate directly to AgentSession without any UI side-effects.
5
+ * Interactive mode layers TUI-specific behavior on top of these.
6
+ * RPC and print modes use them as-is.
7
+ */
8
+
9
+ import type { AgentSession } from "../../core/agent-session.js";
10
+ import type { ExtensionCommandContextActions } from "../../core/extensions/index.js";
11
+
12
+ /**
13
+ * Create the default set of command context actions that simply delegate
14
+ * to the corresponding AgentSession methods.
15
+ *
16
+ * Callers can spread the result and override individual actions to add
17
+ * mode-specific behavior (e.g., interactive mode clears TUI state after
18
+ * forking).
19
+ */
20
+ export function createDefaultCommandContextActions(session: AgentSession): ExtensionCommandContextActions {
21
+ return {
22
+ waitForIdle: () => session.agent.waitForIdle(),
23
+
24
+ newSession: async (options) => {
25
+ const success = await session.newSession(options);
26
+ return { cancelled: !success };
27
+ },
28
+
29
+ fork: async (entryId) => {
30
+ const result = await session.fork(entryId);
31
+ return { cancelled: result.cancelled };
32
+ },
33
+
34
+ navigateTree: async (targetId, options) => {
35
+ const result = await session.navigateTree(targetId, {
36
+ summarize: options?.summarize,
37
+ customInstructions: options?.customInstructions,
38
+ replaceInstructions: options?.replaceInstructions,
39
+ label: options?.label,
40
+ });
41
+ return { cancelled: result.cancelled };
42
+ },
43
+
44
+ switchSession: async (sessionPath) => {
45
+ const success = await session.switchSession(sessionPath);
46
+ return { cancelled: !success };
47
+ },
48
+
49
+ reload: async () => {
50
+ await session.reload();
51
+ },
52
+ };
53
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Extract a human-readable message from an unknown caught value.
3
+ */
4
+ export function getErrorMessage(err: unknown): string {
5
+ return err instanceof Error ? err.message : String(err);
6
+ }
@@ -75,6 +75,11 @@ export declare class Markdown implements Component {
75
75
  * Returns lines WITHOUT the parent indent (renderList will add it)
76
76
  */
77
77
  private renderListItem;
78
+ /**
79
+ * Render a fenced code block with syntax highlighting support.
80
+ * Used by both renderToken (top-level code blocks) and renderListItem (code blocks inside lists).
81
+ */
82
+ private renderCodeBlock;
78
83
  /**
79
84
  * Get the visible width of the longest word in a string.
80
85
  */
@@ -1 +1 @@
1
- {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/components/markdown.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/components/markdown.ts"],"names":[],"mappings":"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"}
@@ -204,22 +204,7 @@ export class Markdown {
204
204
  break;
205
205
  }
206
206
  case "code": {
207
- const indent = this.theme.codeBlockIndent ?? " ";
208
- lines.push(this.theme.codeBlockBorder(`\`\`\`${token.lang || ""}`));
209
- if (this.theme.highlightCode) {
210
- const highlightedLines = this.theme.highlightCode(token.text, token.lang);
211
- for (const hlLine of highlightedLines) {
212
- lines.push(`${indent}${hlLine}`);
213
- }
214
- }
215
- else {
216
- // Split code by newlines and style each line
217
- const codeLines = token.text.split("\n");
218
- for (const codeLine of codeLines) {
219
- lines.push(`${indent}${this.theme.codeBlock(codeLine)}`);
220
- }
221
- }
222
- lines.push(this.theme.codeBlockBorder("```"));
207
+ lines.push(...this.renderCodeBlock(token.text, token.lang));
223
208
  if (nextTokenType !== "space") {
224
209
  lines.push(""); // Add spacing after code blocks (unless space token follows)
225
210
  }
@@ -453,21 +438,7 @@ export class Markdown {
453
438
  }
454
439
  else if (token.type === "code") {
455
440
  // Code block in list item
456
- const indent = this.theme.codeBlockIndent ?? " ";
457
- lines.push(this.theme.codeBlockBorder(`\`\`\`${token.lang || ""}`));
458
- if (this.theme.highlightCode) {
459
- const highlightedLines = this.theme.highlightCode(token.text, token.lang);
460
- for (const hlLine of highlightedLines) {
461
- lines.push(`${indent}${hlLine}`);
462
- }
463
- }
464
- else {
465
- const codeLines = token.text.split("\n");
466
- for (const codeLine of codeLines) {
467
- lines.push(`${indent}${this.theme.codeBlock(codeLine)}`);
468
- }
469
- }
470
- lines.push(this.theme.codeBlockBorder("```"));
441
+ lines.push(...this.renderCodeBlock(token.text, token.lang));
471
442
  }
472
443
  else {
473
444
  // Other token types - try to render as inline
@@ -479,6 +450,29 @@ export class Markdown {
479
450
  }
480
451
  return lines;
481
452
  }
453
+ /**
454
+ * Render a fenced code block with syntax highlighting support.
455
+ * Used by both renderToken (top-level code blocks) and renderListItem (code blocks inside lists).
456
+ */
457
+ renderCodeBlock(code, lang) {
458
+ const lines = [];
459
+ const indent = this.theme.codeBlockIndent ?? " ";
460
+ lines.push(this.theme.codeBlockBorder(`\`\`\`${lang || ""}`));
461
+ if (this.theme.highlightCode) {
462
+ const highlightedLines = this.theme.highlightCode(code, lang);
463
+ for (const hlLine of highlightedLines) {
464
+ lines.push(`${indent}${hlLine}`);
465
+ }
466
+ }
467
+ else {
468
+ const codeLines = code.split("\n");
469
+ for (const codeLine of codeLines) {
470
+ lines.push(`${indent}${this.theme.codeBlock(codeLine)}`);
471
+ }
472
+ }
473
+ lines.push(this.theme.codeBlockBorder("```"));
474
+ return lines;
475
+ }
482
476
  /**
483
477
  * Get the visible width of the longest word in a string.
484
478
  */