@wonderwhy-er/desktop-commander 0.2.38 → 0.2.39

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 (364) hide show
  1. package/README.md +53 -2
  2. package/dist/handlers/filesystem-handlers.d.ts +5 -0
  3. package/dist/handlers/filesystem-handlers.js +14 -2
  4. package/dist/remote-device/desktop-commander-integration.js +1 -1
  5. package/dist/search-manager.js +31 -38
  6. package/dist/server.js +8 -3
  7. package/dist/terminal-manager.js +4 -2
  8. package/dist/tools/edit.js +34 -1
  9. package/dist/tools/filesystem.js +91 -3
  10. package/dist/tools/improved-process-tools.js +2 -1
  11. package/dist/ui/config-editor/app.js +840 -0
  12. package/dist/ui/config-editor/array-modal.d.ts +19 -0
  13. package/dist/ui/config-editor/array-modal.js +185 -0
  14. package/dist/ui/config-editor/config-editor-runtime.js +65 -14096
  15. package/dist/ui/config-editor/main.js +2 -0
  16. package/dist/ui/config-editor/src/App.d.ts +43 -0
  17. package/dist/ui/config-editor/src/components/layout.d.ts +4 -0
  18. package/dist/ui/config-editor/src/components/layout.js +83 -0
  19. package/dist/ui/config-editor/src/components/toolbar.d.ts +1 -0
  20. package/dist/ui/config-editor/src/components/toolbar.js +21 -0
  21. package/dist/ui/config-editor/src/config-values.d.ts +6 -0
  22. package/dist/ui/config-editor/src/config-values.js +61 -0
  23. package/dist/ui/config-editor/src/contracts.d.ts +14 -0
  24. package/dist/ui/config-editor/src/contracts.js +3 -0
  25. package/dist/ui/config-editor/src/directory-browser.d.ts +6 -0
  26. package/dist/ui/config-editor/src/directory-browser.js +71 -0
  27. package/dist/ui/config-editor/src/layout.d.ts +5 -0
  28. package/dist/ui/config-editor/src/layout.js +90 -0
  29. package/dist/ui/config-editor/src/parsing.d.ts +5 -0
  30. package/dist/ui/config-editor/src/parsing.js +50 -0
  31. package/dist/ui/config-editor/src/toolbar.d.ts +1 -0
  32. package/dist/ui/config-editor/src/toolbar.js +18 -0
  33. package/dist/ui/config-editor/src/types.d.ts +17 -0
  34. package/dist/ui/config-editor/src/types.js +3 -0
  35. package/dist/ui/config-editor/src/utils/config-values.d.ts +9 -0
  36. package/dist/ui/config-editor/src/utils/config-values.js +61 -0
  37. package/dist/ui/config-editor/src/utils/directory-browser.d.ts +31 -0
  38. package/dist/ui/config-editor/src/utils/directory-browser.js +201 -0
  39. package/dist/ui/config-editor/src/utils/parsing.d.ts +8 -0
  40. package/dist/ui/config-editor/src/utils/parsing.js +50 -0
  41. package/dist/ui/config-editor/styles.css +2 -1
  42. package/dist/ui/file-preview/{src/app.d.ts → app.d.ts} +1 -1
  43. package/dist/ui/file-preview/app.js +2020 -0
  44. package/dist/ui/file-preview/components/code-viewer.d.ts +6 -0
  45. package/dist/ui/file-preview/components/code-viewer.js +73 -0
  46. package/dist/ui/file-preview/components/highlighting.d.ts +2 -0
  47. package/dist/ui/file-preview/components/highlighting.js +54 -0
  48. package/dist/ui/file-preview/components/html-renderer.d.ts +5 -0
  49. package/dist/ui/file-preview/components/html-renderer.js +47 -0
  50. package/dist/ui/file-preview/components/markdown-renderer.d.ts +1 -0
  51. package/dist/ui/file-preview/components/markdown-renderer.js +67 -0
  52. package/dist/ui/file-preview/components/toolbar.d.ts +6 -0
  53. package/dist/ui/file-preview/components/toolbar.js +75 -0
  54. package/dist/ui/file-preview/image-preview.d.ts +3 -0
  55. package/dist/ui/file-preview/image-preview.js +21 -0
  56. package/dist/ui/file-preview/main.js +5 -0
  57. package/dist/ui/file-preview/markdown/editor.d.ts +36 -0
  58. package/dist/ui/file-preview/markdown/editor.js +643 -0
  59. package/dist/ui/file-preview/markdown/linking.d.ts +9 -0
  60. package/dist/ui/file-preview/markdown/linking.js +210 -0
  61. package/dist/ui/file-preview/markdown/outline.d.ts +7 -0
  62. package/dist/ui/file-preview/markdown/outline.js +40 -0
  63. package/dist/ui/file-preview/markdown/preview.d.ts +8 -0
  64. package/dist/ui/file-preview/markdown/preview.js +33 -0
  65. package/dist/ui/file-preview/markdown/slugify.d.ts +3 -0
  66. package/dist/ui/file-preview/markdown/slugify.js +31 -0
  67. package/dist/ui/file-preview/markdown/toc.d.ts +11 -0
  68. package/dist/ui/file-preview/markdown/toc.js +75 -0
  69. package/dist/ui/file-preview/markdown/utils.d.ts +1 -0
  70. package/dist/ui/file-preview/markdown/utils.js +15 -0
  71. package/dist/ui/file-preview/markdown/workspace-controller.d.ts +25 -0
  72. package/dist/ui/file-preview/markdown/workspace-controller.js +40 -0
  73. package/dist/ui/file-preview/preview-runtime.js +384 -26533
  74. package/dist/ui/file-preview/shared/preview-file-types.d.ts +1 -1
  75. package/dist/ui/file-preview/src/App.d.ts +4 -0
  76. package/dist/ui/file-preview/src/App.js +564 -0
  77. package/dist/ui/file-preview/src/components/CodeViewer.d.ts +6 -0
  78. package/dist/ui/file-preview/src/components/CodeViewer.js +60 -0
  79. package/dist/ui/file-preview/src/components/HtmlRenderer.d.ts +8 -0
  80. package/dist/ui/file-preview/src/components/HtmlRenderer.js +45 -0
  81. package/dist/ui/file-preview/src/components/MarkdownRenderer.d.ts +1 -0
  82. package/dist/ui/file-preview/src/components/MarkdownRenderer.js +15 -0
  83. package/dist/ui/file-preview/src/components/editor-toolbar.d.ts +15 -0
  84. package/dist/ui/file-preview/src/components/editor-toolbar.js +384 -0
  85. package/dist/ui/file-preview/src/components/markdown-editor.d.ts +29 -0
  86. package/dist/ui/file-preview/src/components/markdown-editor.js +535 -0
  87. package/dist/ui/file-preview/src/components/markdown-renderer.js +47 -9
  88. package/dist/ui/file-preview/src/directory-controller.d.ts +8 -0
  89. package/dist/ui/file-preview/src/directory-controller.js +233 -0
  90. package/dist/ui/file-preview/src/document-layout.d.ts +20 -0
  91. package/dist/ui/file-preview/src/document-layout.js +109 -0
  92. package/dist/ui/file-preview/src/document-outline.d.ts +17 -0
  93. package/dist/ui/file-preview/src/document-outline.js +97 -0
  94. package/dist/ui/file-preview/src/document-workspace.d.ts +19 -0
  95. package/dist/ui/file-preview/src/document-workspace.js +33 -0
  96. package/dist/ui/file-preview/src/file-type-handlers.d.ts +10 -0
  97. package/dist/ui/file-preview/src/file-type-handlers.js +98 -0
  98. package/dist/ui/file-preview/src/host/external-actions.d.ts +19 -0
  99. package/dist/ui/file-preview/src/host/external-actions.js +94 -0
  100. package/dist/ui/file-preview/src/host/selection-context.d.ts +9 -0
  101. package/dist/ui/file-preview/src/host/selection-context.js +106 -0
  102. package/dist/ui/file-preview/src/markdown/block-merge.d.ts +25 -0
  103. package/dist/ui/file-preview/src/markdown/block-merge.js +86 -0
  104. package/dist/ui/file-preview/src/markdown/conflict-dialog.d.ts +40 -0
  105. package/dist/ui/file-preview/src/markdown/conflict-dialog.js +163 -0
  106. package/dist/ui/file-preview/src/markdown/controller.d.ts +38 -0
  107. package/dist/ui/file-preview/src/markdown/controller.js +921 -0
  108. package/dist/ui/file-preview/src/markdown/editor.d.ts +35 -0
  109. package/dist/ui/file-preview/src/markdown/editor.js +691 -0
  110. package/dist/ui/file-preview/src/markdown/link-modal.d.ts +13 -0
  111. package/dist/ui/file-preview/src/markdown/link-modal.js +213 -0
  112. package/dist/ui/file-preview/src/markdown/linking.d.ts +16 -0
  113. package/dist/ui/file-preview/src/markdown/linking.js +228 -0
  114. package/dist/ui/file-preview/src/markdown/outline.d.ts +2 -0
  115. package/dist/ui/file-preview/src/markdown/outline.js +16 -0
  116. package/dist/ui/file-preview/src/markdown/parser.d.ts +30 -0
  117. package/dist/ui/file-preview/src/markdown/parser.js +38 -0
  118. package/dist/ui/file-preview/src/markdown/preview.d.ts +1 -0
  119. package/dist/ui/file-preview/src/markdown/preview.js +20 -0
  120. package/dist/ui/file-preview/src/markdown/raw-editor.d.ts +8 -0
  121. package/dist/ui/file-preview/src/markdown/raw-editor.js +61 -0
  122. package/dist/ui/file-preview/src/markdown/selection-toolbar.d.ts +14 -0
  123. package/dist/ui/file-preview/src/markdown/selection-toolbar.js +128 -0
  124. package/dist/ui/file-preview/src/markdown/slugify.d.ts +3 -0
  125. package/dist/ui/file-preview/src/markdown/slugify.js +31 -0
  126. package/dist/ui/file-preview/src/markdown/toc.d.ts +11 -0
  127. package/dist/ui/file-preview/src/markdown/toc.js +75 -0
  128. package/dist/ui/file-preview/src/markdown/utils.d.ts +1 -0
  129. package/dist/ui/file-preview/src/markdown/utils.js +15 -0
  130. package/dist/ui/file-preview/src/markdown-workspace/editor.d.ts +36 -0
  131. package/dist/ui/file-preview/src/markdown-workspace/editor.js +643 -0
  132. package/dist/ui/file-preview/src/markdown-workspace/linking.d.ts +9 -0
  133. package/dist/ui/file-preview/src/markdown-workspace/linking.js +210 -0
  134. package/dist/ui/file-preview/src/markdown-workspace/outline.d.ts +7 -0
  135. package/dist/ui/file-preview/src/markdown-workspace/outline.js +40 -0
  136. package/dist/ui/file-preview/src/markdown-workspace/preview.d.ts +8 -0
  137. package/dist/ui/file-preview/src/markdown-workspace/preview.js +33 -0
  138. package/dist/ui/file-preview/src/markdown-workspace/slugify.d.ts +3 -0
  139. package/dist/ui/file-preview/src/markdown-workspace/slugify.js +31 -0
  140. package/dist/ui/file-preview/src/markdown-workspace/toc.d.ts +11 -0
  141. package/dist/ui/file-preview/src/markdown-workspace/toc.js +75 -0
  142. package/dist/ui/file-preview/src/markdown-workspace/utils.d.ts +1 -0
  143. package/dist/ui/file-preview/src/markdown-workspace/utils.js +15 -0
  144. package/dist/ui/file-preview/src/markdown-workspace/workspace-controller.d.ts +25 -0
  145. package/dist/ui/file-preview/src/markdown-workspace/workspace-controller.js +40 -0
  146. package/dist/ui/file-preview/src/model.d.ts +34 -0
  147. package/dist/ui/file-preview/src/panel-actions.d.ts +17 -0
  148. package/dist/ui/file-preview/src/panel-actions.js +182 -0
  149. package/dist/ui/file-preview/src/path-utils.d.ts +6 -0
  150. package/dist/ui/file-preview/src/path-utils.js +64 -0
  151. package/dist/ui/file-preview/src/payload-utils.d.ts +11 -0
  152. package/dist/ui/file-preview/src/payload-utils.js +94 -0
  153. package/dist/ui/file-preview/styles.css +1066 -233
  154. package/dist/ui/file-preview/types.d.ts +1 -0
  155. package/dist/ui/server-integration.d.ts +13 -0
  156. package/dist/ui/server-integration.js +31 -0
  157. package/dist/ui/shared/ToolHeader.d.ts +9 -0
  158. package/dist/ui/shared/ToolHeader.js +29 -0
  159. package/dist/ui/shared/app-bootstrap.d.ts +9 -0
  160. package/dist/ui/shared/app-bootstrap.js +15 -0
  161. package/dist/ui/shared/guards.d.ts +1 -0
  162. package/dist/ui/shared/guards.js +3 -0
  163. package/dist/ui/shared/host-lifecycle.d.ts +1 -0
  164. package/dist/ui/shared/host-lifecycle.js +8 -2
  165. package/dist/ui/shared/widget-state.d.ts +6 -1
  166. package/dist/ui/shared/widget-state.js +102 -4
  167. package/dist/utils/files/base.d.ts +2 -0
  168. package/dist/utils/open-browser.js +1 -1
  169. package/dist/utils/ui-call-context.d.ts +8 -0
  170. package/dist/utils/ui-call-context.js +72 -0
  171. package/dist/version.d.ts +1 -1
  172. package/dist/version.js +1 -1
  173. package/package.json +6 -1
  174. package/dist/data/spec-kit-prompts.json +0 -123
  175. package/dist/handlers/macos-control-handlers.d.ts +0 -16
  176. package/dist/handlers/macos-control-handlers.js +0 -81
  177. package/dist/handlers/node-handlers.d.ts +0 -6
  178. package/dist/handlers/node-handlers.js +0 -73
  179. package/dist/handlers/test-crash-handler.d.ts +0 -11
  180. package/dist/handlers/test-crash-handler.js +0 -26
  181. package/dist/http-index.d.ts +0 -45
  182. package/dist/http-index.js +0 -51
  183. package/dist/http-server-auto-tunnel.js +0 -667
  184. package/dist/http-server-named-tunnel.d.ts +0 -2
  185. package/dist/http-server-named-tunnel.js +0 -167
  186. package/dist/http-server-tunnel.d.ts +0 -2
  187. package/dist/http-server-tunnel.js +0 -111
  188. package/dist/http-server.d.ts +0 -2
  189. package/dist/http-server.js +0 -270
  190. package/dist/index-oauth.d.ts +0 -2
  191. package/dist/index-oauth.js +0 -201
  192. package/dist/lib.d.ts +0 -10
  193. package/dist/lib.js +0 -10
  194. package/dist/oauth/auth-middleware.d.ts +0 -20
  195. package/dist/oauth/auth-middleware.js +0 -62
  196. package/dist/oauth/index.d.ts +0 -3
  197. package/dist/oauth/index.js +0 -3
  198. package/dist/oauth/oauth-manager.d.ts +0 -80
  199. package/dist/oauth/oauth-manager.js +0 -179
  200. package/dist/oauth/oauth-routes.d.ts +0 -3
  201. package/dist/oauth/oauth-routes.js +0 -377
  202. package/dist/oauth/provider.d.ts +0 -22
  203. package/dist/oauth/provider.js +0 -124
  204. package/dist/oauth/server.d.ts +0 -18
  205. package/dist/oauth/server.js +0 -160
  206. package/dist/oauth/types.d.ts +0 -54
  207. package/dist/oauth/types.js +0 -2
  208. package/dist/remote-device/templates/auth-success.d.ts +0 -1
  209. package/dist/remote-device/templates/auth-success.js +0 -30
  210. package/dist/setup.log +0 -275
  211. package/dist/test-setup.js +0 -14
  212. package/dist/tools/docx/builders/html-builder.d.ts +0 -17
  213. package/dist/tools/docx/builders/html-builder.js +0 -92
  214. package/dist/tools/docx/builders/image.d.ts +0 -14
  215. package/dist/tools/docx/builders/image.js +0 -84
  216. package/dist/tools/docx/builders/index.d.ts +0 -11
  217. package/dist/tools/docx/builders/index.js +0 -11
  218. package/dist/tools/docx/builders/markdown-builder.d.ts +0 -2
  219. package/dist/tools/docx/builders/markdown-builder.js +0 -260
  220. package/dist/tools/docx/builders/paragraph.d.ts +0 -12
  221. package/dist/tools/docx/builders/paragraph.js +0 -29
  222. package/dist/tools/docx/builders/table.d.ts +0 -10
  223. package/dist/tools/docx/builders/table.js +0 -138
  224. package/dist/tools/docx/builders/utils.d.ts +0 -5
  225. package/dist/tools/docx/builders/utils.js +0 -18
  226. package/dist/tools/docx/constants.d.ts +0 -32
  227. package/dist/tools/docx/constants.js +0 -61
  228. package/dist/tools/docx/converters/markdown-to-html.d.ts +0 -17
  229. package/dist/tools/docx/converters/markdown-to-html.js +0 -111
  230. package/dist/tools/docx/create.d.ts +0 -21
  231. package/dist/tools/docx/create.js +0 -386
  232. package/dist/tools/docx/dom.d.ts +0 -139
  233. package/dist/tools/docx/dom.js +0 -448
  234. package/dist/tools/docx/errors.d.ts +0 -28
  235. package/dist/tools/docx/errors.js +0 -48
  236. package/dist/tools/docx/extractors/images.d.ts +0 -14
  237. package/dist/tools/docx/extractors/images.js +0 -40
  238. package/dist/tools/docx/extractors/metadata.d.ts +0 -14
  239. package/dist/tools/docx/extractors/metadata.js +0 -64
  240. package/dist/tools/docx/extractors/sections.d.ts +0 -14
  241. package/dist/tools/docx/extractors/sections.js +0 -61
  242. package/dist/tools/docx/html.d.ts +0 -17
  243. package/dist/tools/docx/html.js +0 -111
  244. package/dist/tools/docx/index.d.ts +0 -10
  245. package/dist/tools/docx/index.js +0 -10
  246. package/dist/tools/docx/markdown.d.ts +0 -84
  247. package/dist/tools/docx/markdown.js +0 -507
  248. package/dist/tools/docx/modify.d.ts +0 -28
  249. package/dist/tools/docx/modify.js +0 -271
  250. package/dist/tools/docx/operations/handlers/index.d.ts +0 -39
  251. package/dist/tools/docx/operations/handlers/index.js +0 -152
  252. package/dist/tools/docx/operations/html-manipulator.d.ts +0 -24
  253. package/dist/tools/docx/operations/html-manipulator.js +0 -352
  254. package/dist/tools/docx/operations/index.d.ts +0 -14
  255. package/dist/tools/docx/operations/index.js +0 -61
  256. package/dist/tools/docx/operations/operation-handlers.d.ts +0 -3
  257. package/dist/tools/docx/operations/operation-handlers.js +0 -67
  258. package/dist/tools/docx/operations/preprocessor.d.ts +0 -14
  259. package/dist/tools/docx/operations/preprocessor.js +0 -44
  260. package/dist/tools/docx/operations/xml-replacer.d.ts +0 -9
  261. package/dist/tools/docx/operations/xml-replacer.js +0 -35
  262. package/dist/tools/docx/operations.d.ts +0 -13
  263. package/dist/tools/docx/operations.js +0 -13
  264. package/dist/tools/docx/ops/delete-paragraph-at-body-index.d.ts +0 -11
  265. package/dist/tools/docx/ops/delete-paragraph-at-body-index.js +0 -23
  266. package/dist/tools/docx/ops/header-replace-text-exact.d.ts +0 -13
  267. package/dist/tools/docx/ops/header-replace-text-exact.js +0 -55
  268. package/dist/tools/docx/ops/index.d.ts +0 -17
  269. package/dist/tools/docx/ops/index.js +0 -70
  270. package/dist/tools/docx/ops/insert-image-after-text.d.ts +0 -24
  271. package/dist/tools/docx/ops/insert-image-after-text.js +0 -128
  272. package/dist/tools/docx/ops/insert-paragraph-after-text.d.ts +0 -12
  273. package/dist/tools/docx/ops/insert-paragraph-after-text.js +0 -74
  274. package/dist/tools/docx/ops/insert-table-after-text.d.ts +0 -19
  275. package/dist/tools/docx/ops/insert-table-after-text.js +0 -57
  276. package/dist/tools/docx/ops/replace-hyperlink-url.d.ts +0 -12
  277. package/dist/tools/docx/ops/replace-hyperlink-url.js +0 -37
  278. package/dist/tools/docx/ops/replace-paragraph-at-body-index.d.ts +0 -9
  279. package/dist/tools/docx/ops/replace-paragraph-at-body-index.js +0 -25
  280. package/dist/tools/docx/ops/replace-paragraph-text-exact.d.ts +0 -21
  281. package/dist/tools/docx/ops/replace-paragraph-text-exact.js +0 -36
  282. package/dist/tools/docx/ops/replace-table-cell-text.d.ts +0 -25
  283. package/dist/tools/docx/ops/replace-table-cell-text.js +0 -85
  284. package/dist/tools/docx/ops/set-color-for-paragraph-exact.d.ts +0 -9
  285. package/dist/tools/docx/ops/set-color-for-paragraph-exact.js +0 -24
  286. package/dist/tools/docx/ops/set-color-for-style.d.ts +0 -13
  287. package/dist/tools/docx/ops/set-color-for-style.js +0 -31
  288. package/dist/tools/docx/ops/set-paragraph-style-at-body-index.d.ts +0 -8
  289. package/dist/tools/docx/ops/set-paragraph-style-at-body-index.js +0 -57
  290. package/dist/tools/docx/ops/table-set-cell-text.d.ts +0 -9
  291. package/dist/tools/docx/ops/table-set-cell-text.js +0 -40
  292. package/dist/tools/docx/parsers/image-extractor.d.ts +0 -18
  293. package/dist/tools/docx/parsers/image-extractor.js +0 -61
  294. package/dist/tools/docx/parsers/index.d.ts +0 -9
  295. package/dist/tools/docx/parsers/index.js +0 -9
  296. package/dist/tools/docx/parsers/paragraph-parser.d.ts +0 -2
  297. package/dist/tools/docx/parsers/paragraph-parser.js +0 -88
  298. package/dist/tools/docx/parsers/table-parser.d.ts +0 -9
  299. package/dist/tools/docx/parsers/table-parser.js +0 -72
  300. package/dist/tools/docx/parsers/xml-parser.d.ts +0 -25
  301. package/dist/tools/docx/parsers/xml-parser.js +0 -71
  302. package/dist/tools/docx/parsers/zip-reader.d.ts +0 -23
  303. package/dist/tools/docx/parsers/zip-reader.js +0 -52
  304. package/dist/tools/docx/read.d.ts +0 -27
  305. package/dist/tools/docx/read.js +0 -308
  306. package/dist/tools/docx/relationships.d.ts +0 -22
  307. package/dist/tools/docx/relationships.js +0 -76
  308. package/dist/tools/docx/structure.d.ts +0 -25
  309. package/dist/tools/docx/structure.js +0 -102
  310. package/dist/tools/docx/styled-html-parser.d.ts +0 -23
  311. package/dist/tools/docx/styled-html-parser.js +0 -1262
  312. package/dist/tools/docx/types.d.ts +0 -213
  313. package/dist/tools/docx/types.js +0 -5
  314. package/dist/tools/docx/utils/escaping.d.ts +0 -13
  315. package/dist/tools/docx/utils/escaping.js +0 -26
  316. package/dist/tools/docx/utils/images.d.ts +0 -9
  317. package/dist/tools/docx/utils/images.js +0 -26
  318. package/dist/tools/docx/utils/index.d.ts +0 -12
  319. package/dist/tools/docx/utils/index.js +0 -17
  320. package/dist/tools/docx/utils/markdown.d.ts +0 -13
  321. package/dist/tools/docx/utils/markdown.js +0 -32
  322. package/dist/tools/docx/utils/paths.d.ts +0 -15
  323. package/dist/tools/docx/utils/paths.js +0 -27
  324. package/dist/tools/docx/utils/versioning.d.ts +0 -25
  325. package/dist/tools/docx/utils/versioning.js +0 -55
  326. package/dist/tools/docx/utils.d.ts +0 -101
  327. package/dist/tools/docx/utils.js +0 -299
  328. package/dist/tools/docx/validate.d.ts +0 -33
  329. package/dist/tools/docx/validate.js +0 -49
  330. package/dist/tools/docx/validators.d.ts +0 -13
  331. package/dist/tools/docx/validators.js +0 -40
  332. package/dist/tools/docx/write.d.ts +0 -17
  333. package/dist/tools/docx/write.js +0 -88
  334. package/dist/tools/docx/xml-view-test.js +0 -63
  335. package/dist/tools/docx/xml-view.d.ts +0 -56
  336. package/dist/tools/docx/xml-view.js +0 -169
  337. package/dist/tools/docx/zip.d.ts +0 -21
  338. package/dist/tools/docx/zip.js +0 -35
  339. package/dist/tools/macos-control/ax-adapter.d.ts +0 -55
  340. package/dist/tools/macos-control/ax-adapter.js +0 -438
  341. package/dist/tools/macos-control/cdp-adapter.d.ts +0 -23
  342. package/dist/tools/macos-control/cdp-adapter.js +0 -402
  343. package/dist/tools/macos-control/orchestrator.d.ts +0 -77
  344. package/dist/tools/macos-control/orchestrator.js +0 -136
  345. package/dist/tools/macos-control/role-aliases.d.ts +0 -5
  346. package/dist/tools/macos-control/role-aliases.js +0 -34
  347. package/dist/tools/macos-control/types.d.ts +0 -129
  348. package/dist/tools/pdf-processor.d.ts +0 -1
  349. package/dist/tools/pdf-processor.js +0 -3
  350. package/dist/tools/search.d.ts +0 -32
  351. package/dist/tools/search.js +0 -202
  352. package/dist/ui/file-preview/src/app.js +0 -714
  353. package/dist/utils/crash-logger.d.ts +0 -18
  354. package/dist/utils/crash-logger.js +0 -44
  355. package/dist/utils/dedent.d.ts +0 -8
  356. package/dist/utils/dedent.js +0 -38
  357. /package/dist/ui/config-editor/{src/app.d.ts → app.d.ts} +0 -0
  358. /package/dist/{http-server-auto-tunnel.d.ts → ui/config-editor/main.d.ts} +0 -0
  359. /package/dist/ui/config-editor/src/{app.js → App.js} +0 -0
  360. /package/dist/{test-docx.d.ts → ui/file-preview/main.d.ts} +0 -0
  361. /package/dist/ui/file-preview/src/components/{toolbar.d.ts → Toolbar.d.ts} +0 -0
  362. /package/dist/ui/file-preview/src/components/{toolbar.js → Toolbar.js} +0 -0
  363. /package/dist/{tools/docx/xml-view-test.d.ts → ui/file-preview/src/model.js} +0 -0
  364. /package/dist/{tools/macos-control → ui/file-preview}/types.js +0 -0
@@ -0,0 +1,233 @@
1
+ import { escapeHtml } from './components/highlighting.js';
2
+ import { buildRenderPayload, extractToolText } from './payload-utils.js';
3
+ function parseDirectoryEntries(content) {
4
+ const lines = content.split('\n');
5
+ const hintLines = [];
6
+ const entryLines = [];
7
+ for (const line of lines) {
8
+ if (/^\[(DIR|FILE|DENIED|WARNING)\]/.test(line.trim())) {
9
+ entryLines.push(line.trim());
10
+ }
11
+ else if (entryLines.length === 0) {
12
+ hintLines.push(line);
13
+ }
14
+ }
15
+ const flat = [];
16
+ for (const line of entryLines) {
17
+ if (line.startsWith('[WARNING]')) {
18
+ const warnBody = line.replace(/^\[WARNING\]\s*/, '');
19
+ const colonIdx = warnBody.indexOf(':');
20
+ const dirName = colonIdx >= 0 ? warnBody.slice(0, colonIdx).trim() : '';
21
+ const msg = colonIdx >= 0 ? warnBody.slice(colonIdx + 1).trim() : warnBody;
22
+ const parts = dirName.replace(/\\/g, '/').split('/').filter(Boolean);
23
+ flat.push({
24
+ name: dirName,
25
+ fullPath: dirName,
26
+ isDir: false,
27
+ isDenied: false,
28
+ isWarning: true,
29
+ warningText: msg,
30
+ depth: parts.length,
31
+ });
32
+ continue;
33
+ }
34
+ const isDir = line.startsWith('[DIR]');
35
+ const isDenied = line.startsWith('[DENIED]');
36
+ const name = line.replace(/^\[(DIR|FILE|DENIED)\]\s*/, '');
37
+ const parts = name.replace(/\\/g, '/').split('/');
38
+ flat.push({
39
+ name,
40
+ fullPath: name,
41
+ isDir,
42
+ isDenied,
43
+ isWarning: false,
44
+ warningText: '',
45
+ depth: parts.length - 1,
46
+ });
47
+ }
48
+ const root = [];
49
+ const stack = [root];
50
+ for (const item of flat) {
51
+ const baseName = item.fullPath.replace(/\\/g, '/').split('/').pop() ?? item.fullPath;
52
+ const entry = {
53
+ name: baseName,
54
+ isDir: item.isDir,
55
+ isDenied: item.isDenied,
56
+ isWarning: item.isWarning,
57
+ warningText: item.warningText,
58
+ children: [],
59
+ relativePath: item.fullPath,
60
+ };
61
+ while (stack.length > item.depth + 1) {
62
+ stack.pop();
63
+ }
64
+ const parent = stack[stack.length - 1];
65
+ parent.push(entry);
66
+ if (item.isDir) {
67
+ stack.push(entry.children);
68
+ }
69
+ }
70
+ return { hint: hintLines.join('\n').trim(), entries: root };
71
+ }
72
+ let dirEntryIdCounter = 0;
73
+ function renderDirTree(entries, rootPath) {
74
+ if (entries.length === 0) {
75
+ return '<div class="dir-tree"><span class="dir-empty">Empty directory</span></div>';
76
+ }
77
+ function renderEntries(items) {
78
+ return items.map((item) => {
79
+ const id = `de-${dirEntryIdCounter++}`;
80
+ const fullPath = `${rootPath}/${item.relativePath.replace(/\\/g, '/')}`;
81
+ const escapedPath = escapeHtml(fullPath);
82
+ if (item.isWarning) {
83
+ return `<div class="dir-entry"><button class="dir-row dir-row-warning dir-load-more" data-loadpath="${escapedPath}"><span class="dir-warning-icon">⚠️</span> <span class="dir-warning-text">${escapeHtml(item.warningText)} — click to load all</span></button></div>`;
84
+ }
85
+ if (item.isDenied) {
86
+ return `<div class="dir-entry"><span class="dir-icon">🚫</span> <span class="dir-name-denied">${escapeHtml(item.name)}</span></div>`;
87
+ }
88
+ if (item.isDir) {
89
+ const hasChildren = item.children.length > 0;
90
+ const chevron = `<span class="dir-chevron${hasChildren ? ' expanded' : ''}">${hasChildren ? '▼' : '▶'}</span>`;
91
+ const openButton = `<button class="dir-open-btn" data-openpath="${escapedPath}" title="Open in Finder">📂</button>`;
92
+ const childrenHtml = hasChildren ? `<div class="dir-children" id="${id}-ch">${renderEntries(item.children)}</div>` : '';
93
+ return `<div class="dir-entry-group" id="${id}"><div class="dir-row dir-row-folder" data-path="${escapedPath}" data-eid="${id}" data-loaded="${hasChildren}">${chevron} <span class="dir-icon">📁</span> <span class="dir-name">${escapeHtml(item.name)}</span>${openButton}</div>${childrenHtml}</div>`;
94
+ }
95
+ return `<div class="dir-entry"><div class="dir-row dir-row-file" data-path="${escapedPath}"><span class="file-icon">📄</span> <span class="file-name">${escapeHtml(item.name)}</span></div></div>`;
96
+ }).join('');
97
+ }
98
+ return `<div class="dir-tree">${renderEntries(entries)}</div>`;
99
+ }
100
+ export function renderDirectoryBody(content, rootPath) {
101
+ dirEntryIdCounter = 0;
102
+ const { hint, entries } = parseDirectoryEntries(content);
103
+ return {
104
+ notice: hint || undefined,
105
+ html: `<div class="panel-content directory-content">${renderDirTree(entries, rootPath)}</div>`,
106
+ };
107
+ }
108
+ export function attachDirectoryHandlers(options) {
109
+ const tree = options.container.querySelector('.dir-tree');
110
+ if (!tree) {
111
+ return;
112
+ }
113
+ tree.addEventListener('click', async (event) => {
114
+ const openBtn = event.target.closest('.dir-open-btn');
115
+ if (openBtn) {
116
+ event.stopPropagation();
117
+ const openPath = openBtn.dataset.openpath;
118
+ if (!openPath) {
119
+ return;
120
+ }
121
+ const command = options.buildOpenInFolderCommand(openPath);
122
+ if (command) {
123
+ try {
124
+ await options.callTool?.('start_process', { command, timeout_ms: 12000 });
125
+ }
126
+ catch {
127
+ // Keep UI stable if opening folder fails.
128
+ }
129
+ }
130
+ return;
131
+ }
132
+ const loadMoreBtn = event.target.closest('.dir-load-more');
133
+ if (loadMoreBtn) {
134
+ event.stopPropagation();
135
+ const loadPath = loadMoreBtn.dataset.loadpath;
136
+ if (!loadPath) {
137
+ return;
138
+ }
139
+ loadMoreBtn.querySelector('.dir-warning-text').textContent = 'Loading…';
140
+ loadMoreBtn.disabled = true;
141
+ try {
142
+ const result = await options.callTool?.('list_directory', { path: loadPath, depth: 1 });
143
+ const text = extractToolText(result) ?? '';
144
+ if (text) {
145
+ const parsed = parseDirectoryEntries(text);
146
+ const html = renderDirTree(parsed.entries, loadPath);
147
+ const parentChildren = loadMoreBtn.closest('.dir-children');
148
+ if (parentChildren) {
149
+ const temp = document.createElement('div');
150
+ temp.innerHTML = html;
151
+ const inner = temp.querySelector('.dir-tree');
152
+ parentChildren.innerHTML = inner ? inner.innerHTML : '';
153
+ }
154
+ }
155
+ }
156
+ catch {
157
+ loadMoreBtn.querySelector('.dir-warning-text').textContent = 'Failed to load';
158
+ loadMoreBtn.disabled = false;
159
+ }
160
+ return;
161
+ }
162
+ const target = event.target.closest('.dir-row');
163
+ if (!target) {
164
+ return;
165
+ }
166
+ const fullPath = target.dataset.path;
167
+ if (!fullPath) {
168
+ return;
169
+ }
170
+ if (target.classList.contains('dir-row-folder')) {
171
+ const entryId = target.dataset.eid;
172
+ if (!entryId) {
173
+ return;
174
+ }
175
+ const childrenEl = document.getElementById(`${entryId}-ch`);
176
+ const chevron = target.querySelector('.dir-chevron');
177
+ if (childrenEl) {
178
+ const hidden = childrenEl.classList.toggle('dir-collapsed');
179
+ chevron?.classList.toggle('expanded', !hidden);
180
+ if (chevron)
181
+ chevron.textContent = hidden ? '▶' : '▼';
182
+ return;
183
+ }
184
+ if (target.dataset.loaded === 'true') {
185
+ return;
186
+ }
187
+ if (chevron)
188
+ chevron.textContent = '⏳';
189
+ try {
190
+ const result = await options.callTool?.('list_directory', { path: fullPath, depth: 2 });
191
+ const text = extractToolText(result) ?? '';
192
+ if (text) {
193
+ target.dataset.loaded = 'true';
194
+ const parsed = parseDirectoryEntries(text);
195
+ const html = renderDirTree(parsed.entries, fullPath);
196
+ const wrapper = document.createElement('div');
197
+ wrapper.className = 'dir-children';
198
+ wrapper.id = `${entryId}-ch`;
199
+ const temp = document.createElement('div');
200
+ temp.innerHTML = html;
201
+ const inner = temp.querySelector('.dir-tree');
202
+ wrapper.innerHTML = inner ? inner.innerHTML : '<span class="dir-empty">Empty</span>';
203
+ target.parentElement?.appendChild(wrapper);
204
+ chevron?.classList.add('expanded');
205
+ if (chevron)
206
+ chevron.textContent = '▼';
207
+ }
208
+ }
209
+ catch {
210
+ if (chevron)
211
+ chevron.textContent = '⚠';
212
+ }
213
+ return;
214
+ }
215
+ if (target.classList.contains('dir-row-file')) {
216
+ target.classList.add('dir-loading');
217
+ try {
218
+ const result = await options.callTool?.('read_file', { path: fullPath });
219
+ if (!result || typeof result !== 'object' || result === null) {
220
+ return;
221
+ }
222
+ const structuredContent = result.structuredContent;
223
+ if (structuredContent && typeof structuredContent === 'object') {
224
+ const text = extractToolText(result) ?? '';
225
+ options.onOpenPayload(buildRenderPayload(structuredContent, text));
226
+ }
227
+ }
228
+ catch {
229
+ target.classList.remove('dir-loading');
230
+ }
231
+ }
232
+ });
233
+ }
@@ -0,0 +1,20 @@
1
+ import type { FileTypeCapabilities, MarkdownWorkspaceState, RenderBodyResult, RenderPayload } from './model.js';
2
+ export declare function buildDocumentLayout(options: {
3
+ payload: RenderPayload;
4
+ body: RenderBodyResult;
5
+ capabilities: FileTypeCapabilities;
6
+ fileExtension: string;
7
+ htmlMode: 'rendered' | 'source';
8
+ currentDisplayMode: string | null;
9
+ isExpanded: boolean;
10
+ hideSummaryRow: boolean;
11
+ markdownWorkspace?: MarkdownWorkspaceState;
12
+ canGoFullscreen: boolean;
13
+ isMarkdownUndoAvailable: boolean;
14
+ defaultMarkdownEditorName?: string;
15
+ markdownEditorAppIcon: string;
16
+ hasDirectoryBackButton: boolean;
17
+ }): {
18
+ html: string;
19
+ effectiveExpanded: boolean;
20
+ };
@@ -0,0 +1,109 @@
1
+ import { renderCompactRow } from '../../shared/compact-row.js';
2
+ import { escapeHtml } from '../../shared/escape-html.js';
3
+ import { parseReadRange, stripReadStatusLine } from './document-workspace.js';
4
+ import { renderMarkdownCopyButton, renderMarkdownModeToggle } from './markdown/editor.js';
5
+ import { buildBreadcrumb, countContentLines } from './payload-utils.js';
6
+ function renderCopyIcon() {
7
+ return '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>';
8
+ }
9
+ function renderFolderIcon() {
10
+ return '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg>';
11
+ }
12
+ function renderUndoIcon() {
13
+ return '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 14 4 9l5-5"/><path d="M4 9h11a5 5 0 1 1 0 10h-1"/></svg>';
14
+ }
15
+ function renderExpandIcon() {
16
+ return '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 3 21 3 21 9"/><polyline points="9 21 3 21 3 15"/><line x1="21" y1="3" x2="14" y2="10"/><line x1="3" y1="21" x2="10" y2="14"/></svg>';
17
+ }
18
+ function renderMarkdownSaveStatus(workspace) {
19
+ if (workspace.fileDeleted) {
20
+ return '<span class="panel-save-status panel-save-status--saved">File deleted</span>';
21
+ }
22
+ if (workspace.saveIndicator !== 'saved') {
23
+ return '';
24
+ }
25
+ const variant = workspace.saving ? 'saving' : 'saved';
26
+ return `<span class="panel-save-status panel-save-status--${variant}">Saved</span>`;
27
+ }
28
+ export function buildDocumentLayout(options) {
29
+ const range = parseReadRange(options.payload.content);
30
+ const notice = options.body.notice ? `<div class="notice">${options.body.notice}</div>` : '';
31
+ const breadcrumb = buildBreadcrumb(options.payload.filePath);
32
+ const lineCount = range ? range.toLine - range.fromLine + 1 : countContentLines(options.payload.content);
33
+ const fileTypeLabel = options.payload.fileType === 'markdown' ? 'MARKDOWN'
34
+ : options.payload.fileType === 'html' ? 'HTML'
35
+ : options.payload.fileType === 'image' ? 'IMAGE'
36
+ : options.payload.fileType === 'directory' ? 'DIRECTORY'
37
+ : options.fileExtension !== 'none' ? options.fileExtension.toUpperCase()
38
+ : 'TEXT';
39
+ const compactLabel = range?.isPartial
40
+ ? `View lines ${range.fromLine}–${range.toLine}`
41
+ : options.payload.fileType === 'directory' ? 'View directory'
42
+ : 'View file';
43
+ let footerLabel = range?.isPartial
44
+ ? `${fileTypeLabel} • LINES ${range.fromLine}–${range.toLine} OF ${range.totalLines}`
45
+ : `${fileTypeLabel} • ${lineCount} LINE${lineCount !== 1 ? 'S' : ''}`;
46
+ if (options.markdownWorkspace) {
47
+ const source = stripReadStatusLine(options.markdownWorkspace.draftContent);
48
+ const markdownWordCount = source.trim().split(/\s+/).filter(Boolean).length;
49
+ const markdownLineCount = countContentLines(source);
50
+ footerLabel = `${fileTypeLabel} • EDIT MODE • ${markdownLineCount} LINES • ${markdownWordCount} WORDS`;
51
+ }
52
+ const isFullscreen = options.currentDisplayMode === 'fullscreen';
53
+ const htmlToggle = options.payload.fileType === 'html'
54
+ ? `<button class="panel-action" id="toggle-html-mode">${options.htmlMode === 'rendered' ? 'Source' : 'Rendered'}</button>`
55
+ : '';
56
+ const backButton = options.hasDirectoryBackButton && options.payload.fileType !== 'directory'
57
+ ? '<button class="panel-action dir-back-btn" id="dir-back" title="Back to directory">← Back</button>'
58
+ : '';
59
+ const isMarkdown = options.payload.fileType === 'markdown';
60
+ const isMarkdownEdit = isMarkdown && !!options.markdownWorkspace;
61
+ const revertDisabled = isMarkdownEdit && (options.markdownWorkspace.fileDeleted || options.markdownWorkspace.loadingDocument || !options.isMarkdownUndoAvailable);
62
+ const fileDeleted = isMarkdownEdit && options.markdownWorkspace.fileDeleted;
63
+ const hasMissingBefore = range?.isPartial && range.fromLine > 1;
64
+ const hasMissingAfter = range?.isPartial && range.toLine < range.totalLines && (range.totalLines - range.toLine) > 1;
65
+ const loadBeforeBanner = hasMissingBefore
66
+ ? `<button class="load-lines-banner" id="load-before">↑ Load lines 1–${range.fromLine - 1}</button>`
67
+ : '';
68
+ const loadAfterBanner = hasMissingAfter
69
+ ? `<button class="load-lines-banner" id="load-after">↓ Load lines ${range.toLine + 1}–${range.totalLines}</button>`
70
+ : '';
71
+ const effectiveExpanded = options.isExpanded || isFullscreen;
72
+ const canOpenInFolder = options.capabilities.canOpenInFolder;
73
+ const canCopy = options.capabilities.canCopy;
74
+ return {
75
+ effectiveExpanded,
76
+ html: `
77
+ <main id="tool-shell" class="shell tool-shell ${effectiveExpanded ? 'expanded' : 'collapsed'}${options.hideSummaryRow ? ' host-framed' : ''}${isFullscreen ? ' fullscreen' : ''}">
78
+ ${isFullscreen ? '' : renderCompactRow({ id: 'compact-toggle', label: compactLabel, filename: options.payload.fileName, variant: 'ready', expandable: true, expanded: options.isExpanded, interactive: true })}
79
+ <section class="panel">
80
+ <div class="panel-topbar">
81
+ ${backButton}
82
+ ${options.hideSummaryRow ? '' : `<span class="panel-breadcrumb" title="${escapeHtml(options.payload.filePath)}">${breadcrumb}</span>`}
83
+ <span class="panel-topbar-actions">
84
+ ${isMarkdownEdit ? renderMarkdownSaveStatus(options.markdownWorkspace) : ''}
85
+ ${htmlToggle}
86
+ ${isMarkdownEdit && isFullscreen ? renderMarkdownModeToggle(options.markdownWorkspace.editorView) : ''}
87
+ ${isMarkdown && !isFullscreen && options.canGoFullscreen ? `<button class="panel-action" id="expand-fullscreen" title="Expand" aria-label="Expand">${renderExpandIcon()}</button>` : ''}
88
+ ${isMarkdownEdit ? `<button class="panel-action" id="revert-markdown" ${isFullscreen ? '' : 'title="Undo" aria-label="Undo" '}${revertDisabled ? 'disabled' : ''}>${renderUndoIcon()}${isFullscreen ? ' Undo' : ''}</button>` : ''}
89
+ ${isMarkdownEdit && isFullscreen ? renderMarkdownCopyButton() : ''}
90
+ ${isMarkdown && !isFullscreen ? `<button class="panel-action" id="copy-active-markdown" title="Copy" aria-label="Copy">${renderCopyIcon()}</button>` : ''}
91
+ ${canCopy && options.capabilities.supportsPreview && !isMarkdown ? `<button class="panel-action" id="copy-source" title="Copy source" aria-label="Copy source">${renderCopyIcon()}</button>` : ''}
92
+ ${canOpenInFolder && isMarkdownEdit && isFullscreen ? `<button class="panel-action" id="open-in-editor" ${fileDeleted ? 'disabled' : ''}>${options.markdownEditorAppIcon} Open in ${escapeHtml(options.defaultMarkdownEditorName ?? 'editor')}</button>` : ''}
93
+ ${canOpenInFolder && !(isMarkdownEdit && isFullscreen) ? `<button class="panel-action" id="open-in-folder" title="Open in folder" aria-label="Open in folder" ${isMarkdownEdit && fileDeleted ? 'disabled' : ''}>${renderFolderIcon()}</button>` : ''}
94
+ </span>
95
+ </div>
96
+ ${notice}
97
+ <div class="panel-content-wrapper">
98
+ ${loadBeforeBanner}
99
+ ${options.body.html}
100
+ ${loadAfterBanner}
101
+ </div>
102
+ <div class="panel-footer">
103
+ <span>${footerLabel}</span>
104
+ </div>
105
+ </section>
106
+ </main>
107
+ `,
108
+ };
109
+ }
@@ -0,0 +1,17 @@
1
+ export interface DocumentOutlineItem {
2
+ id: string;
3
+ text: string;
4
+ level: number;
5
+ line?: number;
6
+ }
7
+ export interface DocumentOutlineHandle {
8
+ dispose: () => void;
9
+ refresh: (outline: DocumentOutlineItem[], activeHeadingId?: string | null) => void;
10
+ }
11
+ export declare function renderDocumentOutline(outline: DocumentOutlineItem[], activeHeadingId?: string | null): string;
12
+ export declare function attachDocumentOutline(options: {
13
+ shell: HTMLElement;
14
+ outline: DocumentOutlineItem[];
15
+ scrollContainer: HTMLElement;
16
+ onSelect: (headingId: string) => void;
17
+ }): DocumentOutlineHandle | null;
@@ -0,0 +1,97 @@
1
+ import { escapeHtml } from '../../shared/escape-html.js';
2
+ function setActiveItem(nav, activeId) {
3
+ const buttons = Array.from(nav.querySelectorAll('[data-toc-id]'));
4
+ buttons.forEach((button) => {
5
+ const isActive = button.dataset.tocId === activeId;
6
+ button.classList.toggle('is-active', isActive);
7
+ button.setAttribute('aria-current', isActive ? 'location' : 'false');
8
+ });
9
+ }
10
+ function renderDocumentOutlineItems(outline, activeHeadingId) {
11
+ return outline.map((item) => {
12
+ const activeClass = item.id === activeHeadingId ? ' is-active' : '';
13
+ return `<button class="document-outline-link markdown-toc-link${activeClass}" type="button" data-toc-id="${escapeHtml(item.id)}" data-level="${item.level}" aria-current="${item.id === activeHeadingId ? 'location' : 'false'}">${escapeHtml(item.text)}</button>`;
14
+ }).join('');
15
+ }
16
+ function renderCollapseIcon() {
17
+ return '<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg>';
18
+ }
19
+ function renderExpandIcon() {
20
+ return '<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg>';
21
+ }
22
+ export function renderDocumentOutline(outline, activeHeadingId) {
23
+ if (outline.length === 0) {
24
+ return '';
25
+ }
26
+ return `
27
+ <aside class="document-outline-shell markdown-toc-shell" aria-label="Table of contents">
28
+ <div class="document-outline-header markdown-toc-header">
29
+ <span class="document-outline-title markdown-toc-title">Contents</span>
30
+ <button class="document-outline-toggle" id="toc-toggle" type="button" title="Collapse sidebar" aria-label="Collapse sidebar">${renderCollapseIcon()}</button>
31
+ </div>
32
+ <nav class="document-outline-nav markdown-toc-nav">${renderDocumentOutlineItems(outline, activeHeadingId)}</nav>
33
+ </aside>
34
+ `;
35
+ }
36
+ export function attachDocumentOutline(options) {
37
+ const nav = options.shell.querySelector('.document-outline-nav');
38
+ if (!nav) {
39
+ return null;
40
+ }
41
+ let currentOutline = options.outline;
42
+ const handleClick = (event) => {
43
+ const target = event.target;
44
+ const button = target?.closest('[data-toc-id]');
45
+ const headingId = button?.dataset.tocId;
46
+ if (!headingId) {
47
+ return;
48
+ }
49
+ options.onSelect(headingId);
50
+ setActiveItem(nav, headingId);
51
+ };
52
+ const updateActiveHeading = () => {
53
+ const headings = currentOutline
54
+ .map((item) => {
55
+ const element = document.getElementById(item.id);
56
+ return element ? { item, element } : null;
57
+ })
58
+ .filter((entry) => entry !== null);
59
+ if (headings.length === 0) {
60
+ return;
61
+ }
62
+ const scrollTop = options.scrollContainer.scrollTop;
63
+ const nextActive = headings.reduce((activeId, current) => {
64
+ if (current.element.offsetTop - scrollTop <= 96) {
65
+ return current.item.id;
66
+ }
67
+ return activeId;
68
+ }, headings[0].item.id);
69
+ setActiveItem(nav, nextActive);
70
+ };
71
+ const toggleButton = options.shell.querySelector('#toc-toggle');
72
+ const handleToggle = () => {
73
+ const isCollapsed = options.shell.classList.toggle('markdown-toc-collapsed');
74
+ if (toggleButton) {
75
+ toggleButton.innerHTML = isCollapsed ? renderExpandIcon() : renderCollapseIcon();
76
+ toggleButton.title = isCollapsed ? 'Expand sidebar' : 'Collapse sidebar';
77
+ toggleButton.setAttribute('aria-label', isCollapsed ? 'Expand sidebar' : 'Collapse sidebar');
78
+ }
79
+ };
80
+ toggleButton?.addEventListener('click', handleToggle);
81
+ nav.addEventListener('click', handleClick);
82
+ options.scrollContainer.addEventListener('scroll', updateActiveHeading, { passive: true });
83
+ updateActiveHeading();
84
+ return {
85
+ dispose: () => {
86
+ nav.removeEventListener('click', handleClick);
87
+ options.scrollContainer.removeEventListener('scroll', updateActiveHeading);
88
+ toggleButton?.removeEventListener('click', handleToggle);
89
+ },
90
+ refresh: (outline, activeHeadingId) => {
91
+ currentOutline = outline;
92
+ nav.innerHTML = renderDocumentOutlineItems(currentOutline, activeHeadingId);
93
+ setActiveItem(nav, activeHeadingId ?? null);
94
+ updateActiveHeading();
95
+ },
96
+ };
97
+ }
@@ -0,0 +1,19 @@
1
+ export interface ReadRange {
2
+ fromLine: number;
3
+ toLine: number;
4
+ totalLines: number;
5
+ isPartial: boolean;
6
+ /** 0-based offset for read_file calls. "from start" → 0, "from line N" → N. */
7
+ readOffset: number;
8
+ }
9
+ export declare function stripReadStatusLine(content: string): string;
10
+ export declare function parseReadRange(content: string): ReadRange | undefined;
11
+ export declare function getDocumentFullscreenAvailability(options: {
12
+ availableDisplayModes?: string[];
13
+ }): {
14
+ canFullscreen: true;
15
+ } | {
16
+ canFullscreen: false;
17
+ reason: string;
18
+ };
19
+ export declare function shouldAutoLoadDocumentOnEnterFullscreen(content: string): boolean;
@@ -0,0 +1,33 @@
1
+ export function stripReadStatusLine(content) {
2
+ return content.replace(/^\[Reading [^\]]+\]\r?\n(?:\r?\n)?/, '');
3
+ }
4
+ export function parseReadRange(content) {
5
+ const match = content.match(/^\[Reading (\d+) lines from (?:line )?(\d+|start) \(total: (\d+) lines/);
6
+ if (!match) {
7
+ return undefined;
8
+ }
9
+ const count = Number.parseInt(match[1], 10);
10
+ const isFromStart = match[2] === 'start';
11
+ const readOffset = isFromStart ? 0 : Number.parseInt(match[2], 10);
12
+ const fromLine = isFromStart ? 1 : readOffset;
13
+ const totalLines = Number.parseInt(match[3], 10);
14
+ return {
15
+ fromLine,
16
+ toLine: fromLine + count - 1,
17
+ totalLines,
18
+ isPartial: count < totalLines,
19
+ readOffset,
20
+ };
21
+ }
22
+ export function getDocumentFullscreenAvailability(options) {
23
+ if (!options.availableDisplayModes?.includes('fullscreen')) {
24
+ return {
25
+ canFullscreen: false,
26
+ reason: 'Fullscreen editing is unavailable in this host.',
27
+ };
28
+ }
29
+ return { canFullscreen: true };
30
+ }
31
+ export function shouldAutoLoadDocumentOnEnterFullscreen(content) {
32
+ return parseReadRange(content)?.isPartial === true;
33
+ }
@@ -0,0 +1,10 @@
1
+ import type { FileTypeCapabilities, RenderBodyResult, RenderPayload } from './model.js';
2
+ import type { MarkdownController } from './markdown/controller.js';
3
+ import type { HtmlPreviewMode } from './types.js';
4
+ export declare function getFileTypeCapabilities(payload: RenderPayload): FileTypeCapabilities;
5
+ export declare function renderPayloadBody(options: {
6
+ payload: RenderPayload;
7
+ htmlMode: HtmlPreviewMode;
8
+ startLine: number;
9
+ markdownController: MarkdownController;
10
+ }): RenderBodyResult;
@@ -0,0 +1,98 @@
1
+ import { formatJsonIfPossible, inferLanguageFromPath, renderCodeViewer } from './components/code-viewer.js';
2
+ import { escapeHtml } from './components/highlighting.js';
3
+ import { renderHtmlPreview } from './components/html-renderer.js';
4
+ import { renderDirectoryBody } from './directory-controller.js';
5
+ import { stripReadStatusLine } from './document-workspace.js';
6
+ import { isAllowedImageMimeType, normalizeImageMimeType } from './image-preview.js';
7
+ import { isLikelyUrl } from './payload-utils.js';
8
+ function renderRawFallback(source) {
9
+ return `<pre class="code-viewer"><code class="hljs language-text">${escapeHtml(source)}</code></pre>`;
10
+ }
11
+ function renderImageBody(payload) {
12
+ const mimeType = normalizeImageMimeType(payload.mimeType);
13
+ if (!isAllowedImageMimeType(mimeType)) {
14
+ return {
15
+ notice: 'Preview is unavailable for this image format.',
16
+ html: '<div class="panel-content source-content"></div>',
17
+ };
18
+ }
19
+ if (!payload.imageData || payload.imageData.trim().length === 0) {
20
+ return {
21
+ notice: 'Preview is unavailable because image data is missing.',
22
+ html: '<div class="panel-content source-content"></div>',
23
+ };
24
+ }
25
+ const src = `data:${mimeType};base64,${payload.imageData}`;
26
+ return {
27
+ html: `<div class="panel-content image-content"><div class="image-preview"><img src="${escapeHtml(src)}" alt="${escapeHtml(payload.fileName)}" loading="eager" decoding="async"></div></div>`,
28
+ };
29
+ }
30
+ function buildPreviewCapabilities(payload, canCopy) {
31
+ return {
32
+ supportsPreview: true,
33
+ canCopy,
34
+ canOpenInFolder: !isLikelyUrl(payload.filePath),
35
+ };
36
+ }
37
+ const handlerRegistry = {
38
+ directory: {
39
+ getCapabilities: (payload) => buildPreviewCapabilities(payload, false),
40
+ renderBody: ({ payload }) => renderDirectoryBody(stripReadStatusLine(payload.content), payload.filePath),
41
+ },
42
+ html: {
43
+ getCapabilities: (payload) => buildPreviewCapabilities(payload, true),
44
+ renderBody: ({ payload, htmlMode }) => renderHtmlPreview(stripReadStatusLine(payload.content), htmlMode),
45
+ },
46
+ image: {
47
+ getCapabilities: (payload) => buildPreviewCapabilities(payload, false),
48
+ renderBody: ({ payload }) => renderImageBody(payload),
49
+ },
50
+ markdown: {
51
+ getCapabilities: (payload) => buildPreviewCapabilities(payload, false),
52
+ renderBody: ({ payload, markdownController }) => {
53
+ try {
54
+ return markdownController.buildBody(payload);
55
+ }
56
+ catch {
57
+ return {
58
+ notice: 'Markdown renderer failed. Showing raw source instead.',
59
+ html: `<div class="panel-content source-content">${renderRawFallback(stripReadStatusLine(payload.content))}</div>`,
60
+ };
61
+ }
62
+ },
63
+ },
64
+ text: {
65
+ getCapabilities: (payload) => buildPreviewCapabilities(payload, true),
66
+ renderBody: ({ payload, startLine }) => {
67
+ const cleanedContent = stripReadStatusLine(payload.content);
68
+ const detectedLanguage = inferLanguageFromPath(payload.filePath);
69
+ const formatted = formatJsonIfPossible(cleanedContent, payload.filePath);
70
+ return {
71
+ notice: formatted.notice,
72
+ html: `<div class="panel-content source-content">${renderCodeViewer(formatted.content, detectedLanguage, startLine)}</div>`,
73
+ };
74
+ },
75
+ },
76
+ unsupported: {
77
+ getCapabilities: () => ({
78
+ supportsPreview: false,
79
+ canCopy: false,
80
+ canOpenInFolder: true,
81
+ }),
82
+ renderBody: () => ({
83
+ notice: 'Preview is not available for this file type.',
84
+ html: '<div class="panel-content source-content"></div>',
85
+ }),
86
+ },
87
+ };
88
+ export function getFileTypeCapabilities(payload) {
89
+ return handlerRegistry[payload.fileType]?.getCapabilities(payload) ?? {
90
+ supportsPreview: false,
91
+ canCopy: false,
92
+ canOpenInFolder: !isLikelyUrl(payload.filePath),
93
+ };
94
+ }
95
+ export function renderPayloadBody(options) {
96
+ const handler = handlerRegistry[options.payload.fileType] ?? handlerRegistry.text;
97
+ return handler.renderBody(options);
98
+ }