@tomsun28/pizza 0.1.0 → 0.1.1

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 (382) hide show
  1. package/README.md +20 -143
  2. package/README.zh-CN.md +36 -0
  3. package/dist/bun/cli.d.ts +2 -0
  4. package/dist/bun/cli.js +6 -0
  5. package/dist/bun/register-bedrock.d.ts +1 -0
  6. package/dist/bun/register-bedrock.js +3 -0
  7. package/dist/cli/args.d.ts +48 -0
  8. package/dist/cli/args.js +330 -0
  9. package/dist/cli/config-selector.d.ts +13 -0
  10. package/dist/cli/config-selector.js +30 -0
  11. package/dist/cli/file-processor.d.ts +14 -0
  12. package/dist/cli/file-processor.js +82 -0
  13. package/dist/cli/initial-message.d.ts +17 -0
  14. package/dist/cli/initial-message.js +21 -0
  15. package/dist/cli/list-models.d.ts +8 -0
  16. package/dist/cli/list-models.js +96 -0
  17. package/dist/cli.d.ts +2 -0
  18. package/dist/cli.js +68 -0
  19. package/dist/config.d.ts +79 -0
  20. package/dist/config.js +223 -0
  21. package/dist/core/agent/index.d.ts +6 -0
  22. package/dist/core/agent/index.js +6 -0
  23. package/dist/core/agent/types.d.ts +202 -0
  24. package/dist/core/agent/types.js +51 -0
  25. package/dist/core/auth-storage.d.ts +135 -0
  26. package/dist/core/auth-storage.js +417 -0
  27. package/dist/core/bash-executor.d.ts +31 -0
  28. package/dist/core/bash-executor.js +107 -0
  29. package/dist/core/compaction/branch-summarization.d.ts +87 -0
  30. package/dist/core/compaction/branch-summarization.js +242 -0
  31. package/dist/core/compaction/compaction-engine.d.ts +40 -0
  32. package/dist/core/compaction/compaction-engine.js +292 -0
  33. package/dist/core/compaction/compaction.d.ts +106 -0
  34. package/dist/core/compaction/compaction.js +295 -0
  35. package/dist/core/compaction/index.d.ts +7 -0
  36. package/dist/core/compaction/index.js +7 -0
  37. package/dist/core/compaction/utils.d.ts +37 -0
  38. package/dist/core/compaction/utils.js +152 -0
  39. package/dist/core/defaults.d.ts +2 -0
  40. package/dist/core/defaults.js +1 -0
  41. package/dist/core/diagnostics.d.ts +14 -0
  42. package/dist/core/diagnostics.js +1 -0
  43. package/dist/core/event-bus.d.ts +8 -0
  44. package/dist/core/event-bus.js +24 -0
  45. package/dist/core/event-store/events.d.ts +465 -0
  46. package/dist/core/event-store/events.js +6 -0
  47. package/dist/core/event-store/index.d.ts +10 -0
  48. package/dist/core/event-store/index.js +10 -0
  49. package/dist/core/event-store/sqlite-store.d.ts +27 -0
  50. package/dist/core/event-store/sqlite-store.js +275 -0
  51. package/dist/core/event-store/store.d.ts +91 -0
  52. package/dist/core/event-store/store.js +7 -0
  53. package/dist/core/event-store/thread-scoped-store.d.ts +29 -0
  54. package/dist/core/event-store/thread-scoped-store.js +50 -0
  55. package/dist/core/event-store/types.d.ts +70 -0
  56. package/dist/core/event-store/types.js +7 -0
  57. package/dist/core/event-store/workspace.d.ts +37 -0
  58. package/dist/core/event-store/workspace.js +71 -0
  59. package/dist/core/exec.d.ts +28 -0
  60. package/dist/core/exec.js +74 -0
  61. package/dist/core/export-html/ansi-to-html.d.ts +21 -0
  62. package/dist/core/export-html/ansi-to-html.js +248 -0
  63. package/dist/core/export-html/index.d.ts +29 -0
  64. package/dist/core/export-html/index.js +186 -0
  65. package/dist/core/export-html/template.css +1017 -0
  66. package/dist/core/export-html/template.html +55 -0
  67. package/dist/core/export-html/template.js +1742 -0
  68. package/dist/core/export-html/tool-renderer.d.ts +39 -0
  69. package/dist/core/export-html/tool-renderer.js +94 -0
  70. package/dist/core/export-html/vendor/highlight.min.js +1213 -0
  71. package/dist/core/export-html/vendor/marked.min.js +6 -0
  72. package/dist/core/extensions/index.d.ts +12 -0
  73. package/dist/core/extensions/index.js +9 -0
  74. package/dist/core/extensions/loader.d.ts +24 -0
  75. package/dist/core/extensions/loader.js +492 -0
  76. package/dist/core/extensions/runner.d.ts +167 -0
  77. package/dist/core/extensions/runner.js +898 -0
  78. package/dist/core/extensions/session-context.d.ts +67 -0
  79. package/dist/core/extensions/session-context.js +272 -0
  80. package/dist/core/extensions/types.d.ts +1147 -0
  81. package/dist/core/extensions/types.js +44 -0
  82. package/dist/core/extensions/wrapper.d.ts +19 -0
  83. package/dist/core/extensions/wrapper.js +21 -0
  84. package/dist/core/footer-data-provider.d.ts +47 -0
  85. package/dist/core/footer-data-provider.js +321 -0
  86. package/dist/core/goal/index.d.ts +3 -0
  87. package/dist/core/goal/index.js +1 -0
  88. package/dist/core/goal/scheduler.d.ts +83 -0
  89. package/dist/core/goal/scheduler.js +154 -0
  90. package/dist/core/goal/types.d.ts +182 -0
  91. package/dist/core/goal/types.js +11 -0
  92. package/dist/core/index.d.ts +8 -0
  93. package/dist/core/index.js +8 -0
  94. package/dist/core/intent/classifier.d.ts +53 -0
  95. package/dist/core/intent/classifier.js +353 -0
  96. package/dist/core/intent/index.d.ts +8 -0
  97. package/dist/core/intent/index.js +8 -0
  98. package/dist/core/intent/tool-adapter.d.ts +31 -0
  99. package/dist/core/intent/tool-adapter.js +168 -0
  100. package/dist/core/intent/types.d.ts +71 -0
  101. package/dist/core/intent/types.js +6 -0
  102. package/dist/core/keybindings.d.ts +297 -0
  103. package/dist/core/keybindings.js +250 -0
  104. package/dist/core/messages.d.ts +30 -0
  105. package/dist/core/messages.js +134 -0
  106. package/dist/core/model-registry.d.ts +131 -0
  107. package/dist/core/model-registry.js +634 -0
  108. package/dist/core/model-resolver.d.ts +109 -0
  109. package/dist/core/model-resolver.js +486 -0
  110. package/dist/core/output-guard.d.ts +5 -0
  111. package/dist/core/output-guard.js +58 -0
  112. package/dist/core/package-manager.d.ts +196 -0
  113. package/dist/core/package-manager.js +1873 -0
  114. package/dist/core/projection/boundary-inferrer.d.ts +58 -0
  115. package/dist/core/projection/boundary-inferrer.js +122 -0
  116. package/dist/core/projection/event-to-message.d.ts +35 -0
  117. package/dist/core/projection/event-to-message.js +253 -0
  118. package/dist/core/projection/goal-projection.d.ts +67 -0
  119. package/dist/core/projection/goal-projection.js +339 -0
  120. package/dist/core/projection/index.d.ts +13 -0
  121. package/dist/core/projection/index.js +13 -0
  122. package/dist/core/projection/session-manager.d.ts +100 -0
  123. package/dist/core/projection/session-manager.js +331 -0
  124. package/dist/core/projection/session-projection.d.ts +58 -0
  125. package/dist/core/projection/session-projection.js +257 -0
  126. package/dist/core/projection/task-history.d.ts +13 -0
  127. package/dist/core/projection/task-history.js +61 -0
  128. package/dist/core/projection/timeline-projection.d.ts +82 -0
  129. package/dist/core/projection/timeline-projection.js +276 -0
  130. package/dist/core/projection/types.d.ts +69 -0
  131. package/dist/core/projection/types.js +6 -0
  132. package/dist/core/prompt-templates.d.ts +51 -0
  133. package/dist/core/prompt-templates.js +249 -0
  134. package/dist/core/resolve-config-value.d.ts +22 -0
  135. package/dist/core/resolve-config-value.js +125 -0
  136. package/dist/core/resource-loader.d.ts +193 -0
  137. package/dist/core/resource-loader.js +685 -0
  138. package/dist/core/runtime/ai-client.d.ts +12 -0
  139. package/dist/core/runtime/ai-client.js +153 -0
  140. package/dist/core/runtime/checkpoint.d.ts +12 -0
  141. package/dist/core/runtime/checkpoint.js +78 -0
  142. package/dist/core/runtime/index.d.ts +12 -0
  143. package/dist/core/runtime/index.js +12 -0
  144. package/dist/core/runtime/llm-types.d.ts +99 -0
  145. package/dist/core/runtime/llm-types.js +6 -0
  146. package/dist/core/runtime/local-runtime.d.ts +23 -0
  147. package/dist/core/runtime/local-runtime.js +59 -0
  148. package/dist/core/runtime/policies.d.ts +72 -0
  149. package/dist/core/runtime/policies.js +37 -0
  150. package/dist/core/runtime/reactor.d.ts +213 -0
  151. package/dist/core/runtime/reactor.js +992 -0
  152. package/dist/core/runtime/runtime.d.ts +191 -0
  153. package/dist/core/runtime/runtime.js +449 -0
  154. package/dist/core/runtime/types.d.ts +42 -0
  155. package/dist/core/runtime/types.js +1 -0
  156. package/dist/core/sdk.d.ts +12 -0
  157. package/dist/core/sdk.js +10 -0
  158. package/dist/core/session-context-builder.d.ts +9 -0
  159. package/dist/core/session-context-builder.js +87 -0
  160. package/dist/core/session-cwd.d.ts +18 -0
  161. package/dist/core/session-cwd.js +36 -0
  162. package/dist/core/session-facade-factory.d.ts +79 -0
  163. package/dist/core/session-facade-factory.js +460 -0
  164. package/dist/core/session-facade.d.ts +57 -0
  165. package/dist/core/session-facade.js +91 -0
  166. package/dist/core/session-listing.d.ts +30 -0
  167. package/dist/core/session-listing.js +168 -0
  168. package/dist/core/session-reader.d.ts +19 -0
  169. package/dist/core/session-reader.js +101 -0
  170. package/dist/core/session-ref.d.ts +7 -0
  171. package/dist/core/session-ref.js +25 -0
  172. package/dist/core/session-services.d.ts +51 -0
  173. package/dist/core/session-services.js +90 -0
  174. package/dist/core/session-stats.d.ts +43 -0
  175. package/dist/core/session-stats.js +41 -0
  176. package/dist/core/settings-manager.d.ts +236 -0
  177. package/dist/core/settings-manager.js +706 -0
  178. package/dist/core/skill-block-parser.d.ts +12 -0
  179. package/dist/core/skill-block-parser.js +15 -0
  180. package/dist/core/skills.d.ts +59 -0
  181. package/dist/core/skills.js +408 -0
  182. package/dist/core/slash-commands.d.ts +13 -0
  183. package/dist/core/slash-commands.js +17 -0
  184. package/dist/core/source-info.d.ts +17 -0
  185. package/dist/core/source-info.js +18 -0
  186. package/dist/core/system-prompt.d.ts +27 -0
  187. package/dist/core/system-prompt.js +179 -0
  188. package/dist/core/timings.d.ts +7 -0
  189. package/dist/core/timings.js +30 -0
  190. package/dist/core/tools/bash.d.ts +95 -0
  191. package/dist/core/tools/bash.js +513 -0
  192. package/dist/core/tools/builtin-commands.d.ts +75 -0
  193. package/dist/core/tools/builtin-commands.js +503 -0
  194. package/dist/core/tools/compat-commands.d.ts +12 -0
  195. package/dist/core/tools/compat-commands.js +1280 -0
  196. package/dist/core/tools/edit-diff.d.ts +59 -0
  197. package/dist/core/tools/edit-diff.js +263 -0
  198. package/dist/core/tools/edit.d.ts +49 -0
  199. package/dist/core/tools/edit.js +340 -0
  200. package/dist/core/tools/file-mutation-queue.d.ts +5 -0
  201. package/dist/core/tools/file-mutation-queue.js +36 -0
  202. package/dist/core/tools/find.d.ts +34 -0
  203. package/dist/core/tools/find.js +459 -0
  204. package/dist/core/tools/grep.d.ts +36 -0
  205. package/dist/core/tools/grep.js +422 -0
  206. package/dist/core/tools/index.d.ts +70 -0
  207. package/dist/core/tools/index.js +129 -0
  208. package/dist/core/tools/line-anchors.d.ts +33 -0
  209. package/dist/core/tools/line-anchors.js +151 -0
  210. package/dist/core/tools/ls.d.ts +36 -0
  211. package/dist/core/tools/ls.js +268 -0
  212. package/dist/core/tools/path-utils.d.ts +7 -0
  213. package/dist/core/tools/path-utils.js +80 -0
  214. package/dist/core/tools/read.d.ts +35 -0
  215. package/dist/core/tools/read.js +244 -0
  216. package/dist/core/tools/render-utils.d.ts +20 -0
  217. package/dist/core/tools/render-utils.js +48 -0
  218. package/dist/core/tools/session-split.d.ts +9 -0
  219. package/dist/core/tools/session-split.js +77 -0
  220. package/dist/core/tools/tool-definition-wrapper.d.ts +13 -0
  221. package/dist/core/tools/tool-definition-wrapper.js +32 -0
  222. package/dist/core/tools/truncate.d.ts +69 -0
  223. package/dist/core/tools/truncate.js +204 -0
  224. package/dist/core/tools/write.d.ts +25 -0
  225. package/dist/core/tools/write.js +211 -0
  226. package/dist/core/types/session-types.d.ts +123 -0
  227. package/dist/core/types/session-types.js +8 -0
  228. package/dist/index.d.ts +27 -0
  229. package/dist/index.js +38 -0
  230. package/dist/main.d.ts +11 -2
  231. package/dist/main.js +577 -149
  232. package/dist/modes/event-mapper.d.ts +115 -0
  233. package/dist/modes/event-mapper.js +200 -0
  234. package/dist/modes/gui/server.d.ts +14 -0
  235. package/dist/modes/gui/server.js +1032 -0
  236. package/dist/modes/index.d.ts +10 -0
  237. package/dist/modes/index.js +9 -0
  238. package/dist/modes/interactive/assets/clankolas.png +0 -0
  239. package/dist/modes/interactive/components/armin.d.ts +33 -0
  240. package/dist/modes/interactive/components/armin.js +328 -0
  241. package/dist/modes/interactive/components/assistant-message.d.ts +19 -0
  242. package/dist/modes/interactive/components/assistant-message.js +115 -0
  243. package/dist/modes/interactive/components/bash-execution.d.ts +33 -0
  244. package/dist/modes/interactive/components/bash-execution.js +169 -0
  245. package/dist/modes/interactive/components/bordered-loader.d.ts +15 -0
  246. package/dist/modes/interactive/components/bordered-loader.js +50 -0
  247. package/dist/modes/interactive/components/branch-summary-message.d.ts +15 -0
  248. package/dist/modes/interactive/components/branch-summary-message.js +41 -0
  249. package/dist/modes/interactive/components/brand-header.d.ts +33 -0
  250. package/dist/modes/interactive/components/brand-header.js +235 -0
  251. package/dist/modes/interactive/components/compaction-summary-message.d.ts +15 -0
  252. package/dist/modes/interactive/components/compaction-summary-message.js +42 -0
  253. package/dist/modes/interactive/components/config-selector.d.ts +70 -0
  254. package/dist/modes/interactive/components/config-selector.js +469 -0
  255. package/dist/modes/interactive/components/countdown-timer.d.ts +13 -0
  256. package/dist/modes/interactive/components/countdown-timer.js +27 -0
  257. package/dist/modes/interactive/components/custom-editor.d.ts +27 -0
  258. package/dist/modes/interactive/components/custom-editor.js +94 -0
  259. package/dist/modes/interactive/components/custom-message.d.ts +19 -0
  260. package/dist/modes/interactive/components/custom-message.js +73 -0
  261. package/dist/modes/interactive/components/daxnuts.d.ts +22 -0
  262. package/dist/modes/interactive/components/daxnuts.js +137 -0
  263. package/dist/modes/interactive/components/diff.d.ts +11 -0
  264. package/dist/modes/interactive/components/diff.js +132 -0
  265. package/dist/modes/interactive/components/dynamic-border.d.ts +14 -0
  266. package/dist/modes/interactive/components/dynamic-border.js +19 -0
  267. package/dist/modes/interactive/components/earendil-announcement.d.ts +4 -0
  268. package/dist/modes/interactive/components/earendil-announcement.js +39 -0
  269. package/dist/modes/interactive/components/extension-editor.d.ts +19 -0
  270. package/dist/modes/interactive/components/extension-editor.js +105 -0
  271. package/dist/modes/interactive/components/extension-input.d.ts +22 -0
  272. package/dist/modes/interactive/components/extension-input.js +54 -0
  273. package/dist/modes/interactive/components/extension-selector.d.ts +23 -0
  274. package/dist/modes/interactive/components/extension-selector.js +70 -0
  275. package/dist/modes/interactive/components/footer.d.ts +55 -0
  276. package/dist/modes/interactive/components/footer.js +207 -0
  277. package/dist/modes/interactive/components/index.d.ts +31 -0
  278. package/dist/modes/interactive/components/index.js +32 -0
  279. package/dist/modes/interactive/components/keybinding-hints.d.ts +7 -0
  280. package/dist/modes/interactive/components/keybinding-hints.js +21 -0
  281. package/dist/modes/interactive/components/login-dialog.d.ts +41 -0
  282. package/dist/modes/interactive/components/login-dialog.js +138 -0
  283. package/dist/modes/interactive/components/model-selector.d.ts +32 -0
  284. package/dist/modes/interactive/components/model-selector.js +209 -0
  285. package/dist/modes/interactive/components/oauth-selector.d.ts +18 -0
  286. package/dist/modes/interactive/components/oauth-selector.js +91 -0
  287. package/dist/modes/interactive/components/settings-selector.d.ts +57 -0
  288. package/dist/modes/interactive/components/settings-selector.js +299 -0
  289. package/dist/modes/interactive/components/show-images-selector.d.ts +9 -0
  290. package/dist/modes/interactive/components/show-images-selector.js +37 -0
  291. package/dist/modes/interactive/components/skill-invocation-message.d.ts +16 -0
  292. package/dist/modes/interactive/components/skill-invocation-message.js +44 -0
  293. package/dist/modes/interactive/components/theme-selector.d.ts +10 -0
  294. package/dist/modes/interactive/components/theme-selector.js +47 -0
  295. package/dist/modes/interactive/components/thinking-selector.d.ts +10 -0
  296. package/dist/modes/interactive/components/thinking-selector.js +50 -0
  297. package/dist/modes/interactive/components/timeline-view.d.ts +31 -0
  298. package/dist/modes/interactive/components/timeline-view.js +81 -0
  299. package/dist/modes/interactive/components/tool-execution.d.ts +64 -0
  300. package/dist/modes/interactive/components/tool-execution.js +305 -0
  301. package/dist/modes/interactive/components/tree-selector.d.ts +88 -0
  302. package/dist/modes/interactive/components/tree-selector.js +1072 -0
  303. package/dist/modes/interactive/components/user-message-selector.d.ts +29 -0
  304. package/dist/modes/interactive/components/user-message-selector.js +110 -0
  305. package/dist/modes/interactive/components/user-message.d.ts +9 -0
  306. package/dist/modes/interactive/components/user-message.js +27 -0
  307. package/dist/modes/interactive/components/visual-truncate.d.ts +23 -0
  308. package/dist/modes/interactive/components/visual-truncate.js +32 -0
  309. package/dist/modes/interactive/interactive-mode.d.ts +394 -0
  310. package/dist/modes/interactive/interactive-mode.js +4116 -0
  311. package/dist/modes/interactive/theme/dark.json +85 -0
  312. package/dist/modes/interactive/theme/light.json +84 -0
  313. package/dist/modes/interactive/theme/theme-schema.json +335 -0
  314. package/dist/modes/interactive/theme/theme.d.ts +80 -0
  315. package/dist/modes/interactive/theme/theme.js +973 -0
  316. package/dist/modes/print-mode.d.ts +27 -0
  317. package/dist/modes/print-mode.js +102 -0
  318. package/dist/modes/rpc/jsonl.d.ts +16 -0
  319. package/dist/modes/rpc/jsonl.js +48 -0
  320. package/dist/modes/rpc/rpc-client.d.ts +219 -0
  321. package/dist/modes/rpc/rpc-client.js +405 -0
  322. package/dist/modes/rpc/rpc-mode.d.ts +19 -0
  323. package/dist/modes/rpc/rpc-mode.js +381 -0
  324. package/dist/modes/rpc/rpc-types.d.ts +406 -0
  325. package/dist/modes/rpc/rpc-types.js +7 -0
  326. package/dist/package-manager-cli.d.ts +3 -0
  327. package/dist/package-manager-cli.js +233 -0
  328. package/dist/utils/changelog.d.ts +20 -0
  329. package/dist/utils/changelog.js +86 -0
  330. package/dist/utils/child-process.d.ts +10 -0
  331. package/dist/utils/child-process.js +77 -0
  332. package/dist/utils/clipboard-image.d.ts +10 -0
  333. package/dist/utils/clipboard-image.js +244 -0
  334. package/dist/utils/clipboard-native.d.ts +7 -0
  335. package/dist/utils/clipboard-native.js +13 -0
  336. package/dist/utils/clipboard.d.ts +1 -0
  337. package/dist/utils/clipboard.js +77 -0
  338. package/dist/utils/exif-orientation.d.ts +4 -0
  339. package/dist/utils/exif-orientation.js +157 -0
  340. package/dist/utils/frontmatter.d.ts +7 -0
  341. package/dist/utils/frontmatter.js +25 -0
  342. package/dist/utils/git.d.ts +25 -0
  343. package/dist/utils/git.js +162 -0
  344. package/dist/utils/image-convert.d.ts +8 -0
  345. package/dist/utils/image-convert.js +38 -0
  346. package/dist/utils/image-resize.d.ts +35 -0
  347. package/dist/utils/image-resize.js +136 -0
  348. package/dist/utils/mime.d.ts +1 -0
  349. package/dist/utils/mime.js +25 -0
  350. package/dist/utils/path-shims.d.ts +1 -0
  351. package/dist/utils/path-shims.js +90 -0
  352. package/dist/utils/paths.d.ts +6 -0
  353. package/dist/utils/paths.js +18 -0
  354. package/dist/utils/photon.d.ts +20 -0
  355. package/dist/utils/photon.js +120 -0
  356. package/dist/utils/shell.d.ts +29 -0
  357. package/dist/utils/shell.js +189 -0
  358. package/dist/utils/sleep.d.ts +4 -0
  359. package/dist/utils/sleep.js +16 -0
  360. package/dist/utils/tools-manager.d.ts +3 -0
  361. package/dist/utils/tools-manager.js +101 -0
  362. package/dist/vendor/bin/darwin-arm64/fd +0 -0
  363. package/dist/vendor/bin/darwin-arm64/rg +0 -0
  364. package/dist/vendor/bin/darwin-x64/fd +0 -0
  365. package/dist/vendor/bin/darwin-x64/rg +0 -0
  366. package/dist/vendor/bin/linux-arm64/fd +0 -0
  367. package/dist/vendor/bin/linux-arm64/rg +0 -0
  368. package/dist/vendor/bin/linux-x64/fd +0 -0
  369. package/dist/vendor/bin/linux-x64/rg +0 -0
  370. package/dist/vendor/bin/win32-arm64/fd.exe +0 -0
  371. package/dist/vendor/bin/win32-arm64/rg.exe +0 -0
  372. package/dist/vendor/bin/win32-x64/fd.exe +0 -0
  373. package/dist/vendor/bin/win32-x64/rg.exe +0 -0
  374. package/package.json +90 -26
  375. package/dist/extension/core.d.ts +0 -69
  376. package/dist/extension/core.js +0 -270
  377. package/dist/extension/core.js.map +0 -1
  378. package/dist/extension/index.d.ts +0 -14
  379. package/dist/extension/index.js +0 -374
  380. package/dist/extension/index.js.map +0 -1
  381. package/dist/main.js.map +0 -1
  382. package/themes/pizza.json +0 -87
@@ -0,0 +1,70 @@
1
+ /**
2
+ * TUI component for managing package resources (enable/disable)
3
+ */
4
+ import { type Component, Container, type Focusable } from "@earendil-works/pi-tui";
5
+ import type { PathMetadata, ResolvedPaths } from "../../../core/package-manager.js";
6
+ import type { SettingsManager } from "../../../core/settings-manager.js";
7
+ type ResourceType = "extensions" | "skills" | "prompts" | "themes";
8
+ interface ResourceItem {
9
+ path: string;
10
+ enabled: boolean;
11
+ metadata: PathMetadata;
12
+ resourceType: ResourceType;
13
+ displayName: string;
14
+ groupKey: string;
15
+ subgroupKey: string;
16
+ }
17
+ interface ResourceSubgroup {
18
+ type: ResourceType;
19
+ label: string;
20
+ items: ResourceItem[];
21
+ }
22
+ interface ResourceGroup {
23
+ key: string;
24
+ label: string;
25
+ scope: "user" | "project" | "temporary";
26
+ origin: "package" | "top-level";
27
+ source: string;
28
+ subgroups: ResourceSubgroup[];
29
+ }
30
+ declare class ResourceList implements Component, Focusable {
31
+ private groups;
32
+ private flatItems;
33
+ private filteredItems;
34
+ private selectedIndex;
35
+ private searchInput;
36
+ private maxVisible;
37
+ private settingsManager;
38
+ private cwd;
39
+ private agentDir;
40
+ onCancel?: () => void;
41
+ onExit?: () => void;
42
+ onToggle?: (item: ResourceItem, newEnabled: boolean) => void;
43
+ private _focused;
44
+ get focused(): boolean;
45
+ set focused(value: boolean);
46
+ constructor(groups: ResourceGroup[], settingsManager: SettingsManager, cwd: string, agentDir: string);
47
+ private buildFlatList;
48
+ private findNextItem;
49
+ private filterItems;
50
+ private selectFirstItem;
51
+ updateItem(item: ResourceItem, enabled: boolean): void;
52
+ invalidate(): void;
53
+ render(width: number): string[];
54
+ handleInput(data: string): void;
55
+ private toggleResource;
56
+ private toggleTopLevelResource;
57
+ private togglePackageResource;
58
+ private getTopLevelBaseDir;
59
+ private getResourcePattern;
60
+ private getPackageResourcePattern;
61
+ }
62
+ export declare class ConfigSelectorComponent extends Container implements Focusable {
63
+ private resourceList;
64
+ private _focused;
65
+ get focused(): boolean;
66
+ set focused(value: boolean);
67
+ constructor(resolvedPaths: ResolvedPaths, settingsManager: SettingsManager, cwd: string, agentDir: string, onClose: () => void, onExit: () => void, requestRender: () => void);
68
+ getResourceList(): ResourceList;
69
+ }
70
+ export {};
@@ -0,0 +1,469 @@
1
+ /**
2
+ * TUI component for managing package resources (enable/disable)
3
+ */
4
+ import { basename, dirname, join, relative } from "node:path";
5
+ import { Container, getKeybindings, Input, matchesKey, Spacer, truncateToWidth, visibleWidth, } from "@earendil-works/pi-tui";
6
+ import { CONFIG_DIR_NAME } from "../../../config.js";
7
+ import { theme } from "../theme/theme.js";
8
+ import { DynamicBorder } from "./dynamic-border.js";
9
+ import { rawKeyHint } from "./keybinding-hints.js";
10
+ const RESOURCE_TYPE_LABELS = {
11
+ extensions: "Extensions",
12
+ skills: "Skills",
13
+ prompts: "Prompts",
14
+ themes: "Themes",
15
+ };
16
+ function getGroupLabel(metadata) {
17
+ if (metadata.origin === "package") {
18
+ return `${metadata.source} (${metadata.scope})`;
19
+ }
20
+ // Top-level resources
21
+ if (metadata.source === "auto") {
22
+ return metadata.scope === "user" ? `User (~/${CONFIG_DIR_NAME}/agent/)` : `Project (${CONFIG_DIR_NAME}/)`;
23
+ }
24
+ return metadata.scope === "user" ? "User settings" : "Project settings";
25
+ }
26
+ function buildGroups(resolved) {
27
+ const groupMap = new Map();
28
+ const addToGroup = (resources, resourceType) => {
29
+ for (const res of resources) {
30
+ const { path, enabled, metadata } = res;
31
+ const groupKey = `${metadata.origin}:${metadata.scope}:${metadata.source}`;
32
+ if (!groupMap.has(groupKey)) {
33
+ groupMap.set(groupKey, {
34
+ key: groupKey,
35
+ label: getGroupLabel(metadata),
36
+ scope: metadata.scope,
37
+ origin: metadata.origin,
38
+ source: metadata.source,
39
+ subgroups: [],
40
+ });
41
+ }
42
+ const group = groupMap.get(groupKey);
43
+ const subgroupKey = `${groupKey}:${resourceType}`;
44
+ let subgroup = group.subgroups.find((sg) => sg.type === resourceType);
45
+ if (!subgroup) {
46
+ subgroup = {
47
+ type: resourceType,
48
+ label: RESOURCE_TYPE_LABELS[resourceType],
49
+ items: [],
50
+ };
51
+ group.subgroups.push(subgroup);
52
+ }
53
+ const fileName = basename(path);
54
+ const parentFolder = basename(dirname(path));
55
+ let displayName;
56
+ if (resourceType === "extensions" && parentFolder !== "extensions") {
57
+ displayName = `${parentFolder}/${fileName}`;
58
+ }
59
+ else if (resourceType === "skills" && fileName === "SKILL.md") {
60
+ displayName = parentFolder;
61
+ }
62
+ else {
63
+ displayName = fileName;
64
+ }
65
+ subgroup.items.push({
66
+ path,
67
+ enabled,
68
+ metadata,
69
+ resourceType,
70
+ displayName,
71
+ groupKey,
72
+ subgroupKey,
73
+ });
74
+ }
75
+ };
76
+ addToGroup(resolved.extensions, "extensions");
77
+ addToGroup(resolved.skills, "skills");
78
+ addToGroup(resolved.prompts, "prompts");
79
+ addToGroup(resolved.themes, "themes");
80
+ // Sort groups: packages first, then top-level; user before project
81
+ const groups = Array.from(groupMap.values());
82
+ groups.sort((a, b) => {
83
+ if (a.origin !== b.origin) {
84
+ return a.origin === "package" ? -1 : 1;
85
+ }
86
+ if (a.scope !== b.scope) {
87
+ return a.scope === "user" ? -1 : 1;
88
+ }
89
+ return a.source.localeCompare(b.source);
90
+ });
91
+ // Sort subgroups within each group by type order, and items by name
92
+ const typeOrder = { extensions: 0, skills: 1, prompts: 2, themes: 3 };
93
+ for (const group of groups) {
94
+ group.subgroups.sort((a, b) => typeOrder[a.type] - typeOrder[b.type]);
95
+ for (const subgroup of group.subgroups) {
96
+ subgroup.items.sort((a, b) => a.displayName.localeCompare(b.displayName));
97
+ }
98
+ }
99
+ return groups;
100
+ }
101
+ class ConfigSelectorHeader {
102
+ invalidate() { }
103
+ render(width) {
104
+ const title = theme.bold("Resource Configuration");
105
+ const sep = theme.fg("muted", " · ");
106
+ const hint = rawKeyHint("space", "toggle") + sep + rawKeyHint("esc", "close");
107
+ const hintWidth = visibleWidth(hint);
108
+ const titleWidth = visibleWidth(title);
109
+ const spacing = Math.max(1, width - titleWidth - hintWidth);
110
+ return [
111
+ truncateToWidth(`${title}${" ".repeat(spacing)}${hint}`, width, ""),
112
+ theme.fg("muted", "Type to filter resources"),
113
+ ];
114
+ }
115
+ }
116
+ class ResourceList {
117
+ get focused() {
118
+ return this._focused;
119
+ }
120
+ set focused(value) {
121
+ this._focused = value;
122
+ this.searchInput.focused = value;
123
+ }
124
+ constructor(groups, settingsManager, cwd, agentDir) {
125
+ this.flatItems = [];
126
+ this.filteredItems = [];
127
+ this.selectedIndex = 0;
128
+ this.maxVisible = 15;
129
+ this._focused = false;
130
+ this.groups = groups;
131
+ this.settingsManager = settingsManager;
132
+ this.cwd = cwd;
133
+ this.agentDir = agentDir;
134
+ this.searchInput = new Input();
135
+ this.buildFlatList();
136
+ this.filteredItems = [...this.flatItems];
137
+ }
138
+ buildFlatList() {
139
+ this.flatItems = [];
140
+ for (const group of this.groups) {
141
+ this.flatItems.push({ type: "group", group });
142
+ for (const subgroup of group.subgroups) {
143
+ this.flatItems.push({ type: "subgroup", subgroup, group });
144
+ for (const item of subgroup.items) {
145
+ this.flatItems.push({ type: "item", item });
146
+ }
147
+ }
148
+ }
149
+ // Start selection on first item (not header)
150
+ this.selectedIndex = this.flatItems.findIndex((e) => e.type === "item");
151
+ if (this.selectedIndex < 0)
152
+ this.selectedIndex = 0;
153
+ }
154
+ findNextItem(fromIndex, direction) {
155
+ let idx = fromIndex + direction;
156
+ while (idx >= 0 && idx < this.filteredItems.length) {
157
+ if (this.filteredItems[idx].type === "item") {
158
+ return idx;
159
+ }
160
+ idx += direction;
161
+ }
162
+ return fromIndex; // Stay at current if no item found
163
+ }
164
+ filterItems(query) {
165
+ if (!query.trim()) {
166
+ this.filteredItems = [...this.flatItems];
167
+ this.selectFirstItem();
168
+ return;
169
+ }
170
+ const lowerQuery = query.toLowerCase();
171
+ const matchingItems = new Set();
172
+ const matchingSubgroups = new Set();
173
+ const matchingGroups = new Set();
174
+ for (const entry of this.flatItems) {
175
+ if (entry.type === "item") {
176
+ const item = entry.item;
177
+ if (item.displayName.toLowerCase().includes(lowerQuery) ||
178
+ item.resourceType.toLowerCase().includes(lowerQuery) ||
179
+ item.path.toLowerCase().includes(lowerQuery)) {
180
+ matchingItems.add(item);
181
+ }
182
+ }
183
+ }
184
+ // Find which subgroups and groups contain matching items
185
+ for (const group of this.groups) {
186
+ for (const subgroup of group.subgroups) {
187
+ for (const item of subgroup.items) {
188
+ if (matchingItems.has(item)) {
189
+ matchingSubgroups.add(subgroup);
190
+ matchingGroups.add(group);
191
+ }
192
+ }
193
+ }
194
+ }
195
+ this.filteredItems = [];
196
+ for (const entry of this.flatItems) {
197
+ if (entry.type === "group" && matchingGroups.has(entry.group)) {
198
+ this.filteredItems.push(entry);
199
+ }
200
+ else if (entry.type === "subgroup" && matchingSubgroups.has(entry.subgroup)) {
201
+ this.filteredItems.push(entry);
202
+ }
203
+ else if (entry.type === "item" && matchingItems.has(entry.item)) {
204
+ this.filteredItems.push(entry);
205
+ }
206
+ }
207
+ this.selectFirstItem();
208
+ }
209
+ selectFirstItem() {
210
+ const firstItemIndex = this.filteredItems.findIndex((e) => e.type === "item");
211
+ this.selectedIndex = firstItemIndex >= 0 ? firstItemIndex : 0;
212
+ }
213
+ updateItem(item, enabled) {
214
+ item.enabled = enabled;
215
+ // Update in groups too
216
+ for (const group of this.groups) {
217
+ for (const subgroup of group.subgroups) {
218
+ const found = subgroup.items.find((i) => i.path === item.path && i.resourceType === item.resourceType);
219
+ if (found) {
220
+ found.enabled = enabled;
221
+ return;
222
+ }
223
+ }
224
+ }
225
+ }
226
+ invalidate() { }
227
+ render(width) {
228
+ const lines = [];
229
+ // Search input
230
+ lines.push(...this.searchInput.render(width));
231
+ lines.push("");
232
+ if (this.filteredItems.length === 0) {
233
+ lines.push(theme.fg("muted", " No resources found"));
234
+ return lines;
235
+ }
236
+ // Calculate visible range
237
+ const startIndex = Math.max(0, Math.min(this.selectedIndex - Math.floor(this.maxVisible / 2), this.filteredItems.length - this.maxVisible));
238
+ const endIndex = Math.min(startIndex + this.maxVisible, this.filteredItems.length);
239
+ for (let i = startIndex; i < endIndex; i++) {
240
+ const entry = this.filteredItems[i];
241
+ const isSelected = i === this.selectedIndex;
242
+ if (entry.type === "group") {
243
+ // Main group header (no cursor)
244
+ const groupLine = theme.fg("accent", theme.bold(entry.group.label));
245
+ lines.push(truncateToWidth(` ${groupLine}`, width, ""));
246
+ }
247
+ else if (entry.type === "subgroup") {
248
+ // Subgroup header (indented, no cursor)
249
+ const subgroupLine = theme.fg("muted", entry.subgroup.label);
250
+ lines.push(truncateToWidth(` ${subgroupLine}`, width, ""));
251
+ }
252
+ else {
253
+ // Resource item (cursor only on items)
254
+ const item = entry.item;
255
+ const cursor = isSelected ? "> " : " ";
256
+ const checkbox = item.enabled ? theme.fg("success", "[x]") : theme.fg("dim", "[ ]");
257
+ const name = isSelected ? theme.bold(item.displayName) : item.displayName;
258
+ lines.push(truncateToWidth(`${cursor} ${checkbox} ${name}`, width, "..."));
259
+ }
260
+ }
261
+ // Scroll indicator
262
+ if (startIndex > 0 || endIndex < this.filteredItems.length) {
263
+ lines.push(theme.fg("dim", ` (${this.selectedIndex + 1}/${this.filteredItems.length})`));
264
+ }
265
+ return lines;
266
+ }
267
+ handleInput(data) {
268
+ const kb = getKeybindings();
269
+ if (kb.matches(data, "tui.select.up")) {
270
+ this.selectedIndex = this.findNextItem(this.selectedIndex, -1);
271
+ return;
272
+ }
273
+ if (kb.matches(data, "tui.select.down")) {
274
+ this.selectedIndex = this.findNextItem(this.selectedIndex, 1);
275
+ return;
276
+ }
277
+ if (kb.matches(data, "tui.select.pageUp")) {
278
+ // Jump up by maxVisible, then find nearest item
279
+ let target = Math.max(0, this.selectedIndex - this.maxVisible);
280
+ while (target < this.filteredItems.length && this.filteredItems[target].type !== "item") {
281
+ target++;
282
+ }
283
+ if (target < this.filteredItems.length) {
284
+ this.selectedIndex = target;
285
+ }
286
+ return;
287
+ }
288
+ if (kb.matches(data, "tui.select.pageDown")) {
289
+ // Jump down by maxVisible, then find nearest item
290
+ let target = Math.min(this.filteredItems.length - 1, this.selectedIndex + this.maxVisible);
291
+ while (target >= 0 && this.filteredItems[target].type !== "item") {
292
+ target--;
293
+ }
294
+ if (target >= 0) {
295
+ this.selectedIndex = target;
296
+ }
297
+ return;
298
+ }
299
+ if (kb.matches(data, "tui.select.cancel")) {
300
+ this.onCancel?.();
301
+ return;
302
+ }
303
+ if (matchesKey(data, "ctrl+c")) {
304
+ this.onExit?.();
305
+ return;
306
+ }
307
+ if (data === " " || kb.matches(data, "tui.select.confirm")) {
308
+ const entry = this.filteredItems[this.selectedIndex];
309
+ if (entry?.type === "item") {
310
+ const newEnabled = !entry.item.enabled;
311
+ this.toggleResource(entry.item, newEnabled);
312
+ this.updateItem(entry.item, newEnabled);
313
+ this.onToggle?.(entry.item, newEnabled);
314
+ }
315
+ return;
316
+ }
317
+ // Pass to search input
318
+ this.searchInput.handleInput(data);
319
+ this.filterItems(this.searchInput.getValue());
320
+ }
321
+ toggleResource(item, enabled) {
322
+ if (item.metadata.origin === "top-level") {
323
+ this.toggleTopLevelResource(item, enabled);
324
+ }
325
+ else {
326
+ this.togglePackageResource(item, enabled);
327
+ }
328
+ }
329
+ toggleTopLevelResource(item, enabled) {
330
+ const scope = item.metadata.scope;
331
+ const settings = scope === "project" ? this.settingsManager.getProjectSettings() : this.settingsManager.getGlobalSettings();
332
+ const arrayKey = item.resourceType;
333
+ const current = (settings[arrayKey] ?? []);
334
+ // Generate pattern for this resource
335
+ const pattern = this.getResourcePattern(item);
336
+ const disablePattern = `-${pattern}`;
337
+ const enablePattern = `+${pattern}`;
338
+ // Filter out existing patterns for this resource
339
+ const updated = current.filter((p) => {
340
+ const stripped = p.startsWith("!") || p.startsWith("+") || p.startsWith("-") ? p.slice(1) : p;
341
+ return stripped !== pattern;
342
+ });
343
+ if (enabled) {
344
+ updated.push(enablePattern);
345
+ }
346
+ else {
347
+ updated.push(disablePattern);
348
+ }
349
+ if (scope === "project") {
350
+ if (arrayKey === "extensions") {
351
+ this.settingsManager.setProjectExtensionPaths(updated);
352
+ }
353
+ else if (arrayKey === "skills") {
354
+ this.settingsManager.setProjectSkillPaths(updated);
355
+ }
356
+ else if (arrayKey === "prompts") {
357
+ this.settingsManager.setProjectPromptTemplatePaths(updated);
358
+ }
359
+ else if (arrayKey === "themes") {
360
+ this.settingsManager.setProjectThemePaths(updated);
361
+ }
362
+ }
363
+ else {
364
+ if (arrayKey === "extensions") {
365
+ this.settingsManager.setExtensionPaths(updated);
366
+ }
367
+ else if (arrayKey === "skills") {
368
+ this.settingsManager.setSkillPaths(updated);
369
+ }
370
+ else if (arrayKey === "prompts") {
371
+ this.settingsManager.setPromptTemplatePaths(updated);
372
+ }
373
+ else if (arrayKey === "themes") {
374
+ this.settingsManager.setThemePaths(updated);
375
+ }
376
+ }
377
+ }
378
+ togglePackageResource(item, enabled) {
379
+ const scope = item.metadata.scope;
380
+ const settings = scope === "project" ? this.settingsManager.getProjectSettings() : this.settingsManager.getGlobalSettings();
381
+ const packages = [...(settings.packages ?? [])];
382
+ const pkgIndex = packages.findIndex((pkg) => {
383
+ const source = typeof pkg === "string" ? pkg : pkg.source;
384
+ return source === item.metadata.source;
385
+ });
386
+ if (pkgIndex === -1)
387
+ return;
388
+ let pkg = packages[pkgIndex];
389
+ // Convert string to object form if needed
390
+ if (typeof pkg === "string") {
391
+ pkg = { source: pkg };
392
+ packages[pkgIndex] = pkg;
393
+ }
394
+ // Get the resource array for this type
395
+ const arrayKey = item.resourceType;
396
+ const current = (pkg[arrayKey] ?? []);
397
+ // Generate pattern relative to package root
398
+ const pattern = this.getPackageResourcePattern(item);
399
+ const disablePattern = `-${pattern}`;
400
+ const enablePattern = `+${pattern}`;
401
+ // Filter out existing patterns for this resource
402
+ const updated = current.filter((p) => {
403
+ const stripped = p.startsWith("!") || p.startsWith("+") || p.startsWith("-") ? p.slice(1) : p;
404
+ return stripped !== pattern;
405
+ });
406
+ if (enabled) {
407
+ updated.push(enablePattern);
408
+ }
409
+ else {
410
+ updated.push(disablePattern);
411
+ }
412
+ pkg[arrayKey] = updated.length > 0 ? updated : undefined;
413
+ // Clean up empty filter object
414
+ const hasFilters = ["extensions", "skills", "prompts", "themes"].some((k) => pkg[k] !== undefined);
415
+ if (!hasFilters) {
416
+ packages[pkgIndex] = pkg.source;
417
+ }
418
+ if (scope === "project") {
419
+ this.settingsManager.setProjectPackages(packages);
420
+ }
421
+ else {
422
+ this.settingsManager.setPackages(packages);
423
+ }
424
+ }
425
+ getTopLevelBaseDir(scope) {
426
+ return scope === "project" ? join(this.cwd, CONFIG_DIR_NAME) : this.agentDir;
427
+ }
428
+ getResourcePattern(item) {
429
+ const scope = item.metadata.scope;
430
+ const baseDir = this.getTopLevelBaseDir(scope);
431
+ return relative(baseDir, item.path);
432
+ }
433
+ getPackageResourcePattern(item) {
434
+ const baseDir = item.metadata.baseDir ?? dirname(item.path);
435
+ return relative(baseDir, item.path);
436
+ }
437
+ }
438
+ export class ConfigSelectorComponent extends Container {
439
+ get focused() {
440
+ return this._focused;
441
+ }
442
+ set focused(value) {
443
+ this._focused = value;
444
+ this.resourceList.focused = value;
445
+ }
446
+ constructor(resolvedPaths, settingsManager, cwd, agentDir, onClose, onExit, requestRender) {
447
+ super();
448
+ this._focused = false;
449
+ const groups = buildGroups(resolvedPaths);
450
+ // Add header
451
+ this.addChild(new Spacer(1));
452
+ this.addChild(new DynamicBorder());
453
+ this.addChild(new Spacer(1));
454
+ this.addChild(new ConfigSelectorHeader());
455
+ this.addChild(new Spacer(1));
456
+ // Resource list
457
+ this.resourceList = new ResourceList(groups, settingsManager, cwd, agentDir);
458
+ this.resourceList.onCancel = onClose;
459
+ this.resourceList.onExit = onExit;
460
+ this.resourceList.onToggle = () => requestRender();
461
+ this.addChild(this.resourceList);
462
+ // Bottom border
463
+ this.addChild(new Spacer(1));
464
+ this.addChild(new DynamicBorder());
465
+ }
466
+ getResourceList() {
467
+ return this.resourceList;
468
+ }
469
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Reusable countdown timer for dialog components.
3
+ */
4
+ import type { TUI } from "@earendil-works/pi-tui";
5
+ export declare class CountdownTimer {
6
+ private tui;
7
+ private onTick;
8
+ private onExpire;
9
+ private intervalId;
10
+ private remainingSeconds;
11
+ constructor(timeoutMs: number, tui: TUI | undefined, onTick: (seconds: number) => void, onExpire: () => void);
12
+ dispose(): void;
13
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Reusable countdown timer for dialog components.
3
+ */
4
+ export class CountdownTimer {
5
+ constructor(timeoutMs, tui, onTick, onExpire) {
6
+ this.tui = tui;
7
+ this.onTick = onTick;
8
+ this.onExpire = onExpire;
9
+ this.remainingSeconds = Math.ceil(timeoutMs / 1000);
10
+ this.onTick(this.remainingSeconds);
11
+ this.intervalId = setInterval(() => {
12
+ this.remainingSeconds--;
13
+ this.onTick(this.remainingSeconds);
14
+ this.tui?.requestRender();
15
+ if (this.remainingSeconds <= 0) {
16
+ this.dispose();
17
+ this.onExpire();
18
+ }
19
+ }, 1000);
20
+ }
21
+ dispose() {
22
+ if (this.intervalId) {
23
+ clearInterval(this.intervalId);
24
+ this.intervalId = undefined;
25
+ }
26
+ }
27
+ }
@@ -0,0 +1,27 @@
1
+ import { Editor, type EditorOptions, type EditorTheme, type TUI } from "@earendil-works/pi-tui";
2
+ import type { AppKeybinding, KeybindingsManager } from "../../../core/keybindings.js";
3
+ /**
4
+ * Custom editor that handles app-level keybindings for coding-agent.
5
+ */
6
+ export declare class CustomEditor extends Editor {
7
+ private keybindings;
8
+ actionHandlers: Map<AppKeybinding, () => void>;
9
+ onEscape?: () => void;
10
+ onCtrlD?: () => void;
11
+ onPasteImage?: () => void;
12
+ /** Handler for extension-registered shortcuts. Returns true if handled. */
13
+ onExtensionShortcut?: (data: string) => boolean;
14
+ constructor(tui: TUI, theme: EditorTheme, keybindings: KeybindingsManager, options?: EditorOptions);
15
+ /**
16
+ * Register a handler for an app action.
17
+ */
18
+ onAction(action: AppKeybinding, handler: () => void): void;
19
+ handleInput(data: string): void;
20
+ /**
21
+ * Override render to add cyber-style corner brackets on border lines.
22
+ * The parent Editor renders plain ─── lines; we replace the first and
23
+ * last simple border lines with angular corners (┌┐ / └┘).
24
+ * Scroll indicators and content lines are passed through unchanged.
25
+ */
26
+ render(width: number): string[];
27
+ }