@wonderwhy-er/desktop-commander 0.2.37 → 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 (383) hide show
  1. package/README.md +290 -100
  2. package/dist/command-manager.js +6 -3
  3. package/dist/config-field-definitions.d.ts +41 -0
  4. package/dist/config-field-definitions.js +37 -0
  5. package/dist/config-manager.d.ts +2 -0
  6. package/dist/config-manager.js +22 -2
  7. package/dist/handlers/filesystem-handlers.d.ts +5 -0
  8. package/dist/handlers/filesystem-handlers.js +19 -12
  9. package/dist/remote-device/desktop-commander-integration.js +1 -1
  10. package/dist/remote-device/remote-channel.js +1 -1
  11. package/dist/search-manager.js +31 -38
  12. package/dist/server.js +11 -4
  13. package/dist/terminal-manager.js +4 -2
  14. package/dist/tools/config.d.ts +71 -0
  15. package/dist/tools/config.js +117 -2
  16. package/dist/tools/edit.js +34 -1
  17. package/dist/tools/filesystem.js +91 -3
  18. package/dist/tools/improved-process-tools.js +2 -1
  19. package/dist/tools/schemas.d.ts +3 -0
  20. package/dist/tools/schemas.js +1 -0
  21. package/dist/types.d.ts +0 -1
  22. package/dist/ui/config-editor/app.d.ts +43 -0
  23. package/dist/ui/config-editor/app.js +840 -0
  24. package/dist/ui/config-editor/array-modal.d.ts +19 -0
  25. package/dist/ui/config-editor/array-modal.js +185 -0
  26. package/dist/ui/config-editor/config-editor-runtime.js +150 -0
  27. package/dist/ui/config-editor/index.html +13 -0
  28. package/dist/ui/config-editor/main.js +2 -0
  29. package/dist/ui/config-editor/src/App.d.ts +43 -0
  30. package/dist/ui/config-editor/src/App.js +840 -0
  31. package/dist/ui/config-editor/src/array-modal.d.ts +19 -0
  32. package/dist/ui/config-editor/src/array-modal.js +185 -0
  33. package/dist/ui/config-editor/src/components/layout.d.ts +4 -0
  34. package/dist/ui/config-editor/src/components/layout.js +83 -0
  35. package/dist/ui/config-editor/src/components/toolbar.d.ts +1 -0
  36. package/dist/ui/config-editor/src/components/toolbar.js +21 -0
  37. package/dist/ui/config-editor/src/config-values.d.ts +6 -0
  38. package/dist/ui/config-editor/src/config-values.js +61 -0
  39. package/dist/ui/config-editor/src/contracts.d.ts +14 -0
  40. package/dist/ui/config-editor/src/contracts.js +3 -0
  41. package/dist/ui/config-editor/src/directory-browser.d.ts +6 -0
  42. package/dist/ui/config-editor/src/directory-browser.js +71 -0
  43. package/dist/ui/config-editor/src/layout.d.ts +5 -0
  44. package/dist/ui/config-editor/src/layout.js +90 -0
  45. package/dist/ui/config-editor/src/main.js +2 -0
  46. package/dist/ui/config-editor/src/parsing.d.ts +5 -0
  47. package/dist/ui/config-editor/src/parsing.js +50 -0
  48. package/dist/ui/config-editor/src/toolbar.d.ts +1 -0
  49. package/dist/ui/config-editor/src/toolbar.js +18 -0
  50. package/dist/ui/config-editor/src/types.d.ts +17 -0
  51. package/dist/ui/config-editor/src/types.js +3 -0
  52. package/dist/ui/config-editor/src/utils/config-values.d.ts +9 -0
  53. package/dist/ui/config-editor/src/utils/config-values.js +61 -0
  54. package/dist/ui/config-editor/src/utils/directory-browser.d.ts +31 -0
  55. package/dist/ui/config-editor/src/utils/directory-browser.js +201 -0
  56. package/dist/ui/config-editor/src/utils/parsing.d.ts +8 -0
  57. package/dist/ui/config-editor/src/utils/parsing.js +50 -0
  58. package/dist/ui/config-editor/styles.css +587 -0
  59. package/dist/ui/file-preview/app.d.ts +8 -0
  60. package/dist/ui/file-preview/app.js +2020 -0
  61. package/dist/ui/file-preview/components/code-viewer.d.ts +6 -0
  62. package/dist/ui/file-preview/components/code-viewer.js +73 -0
  63. package/dist/ui/file-preview/components/highlighting.d.ts +2 -0
  64. package/dist/ui/file-preview/components/highlighting.js +54 -0
  65. package/dist/ui/file-preview/components/html-renderer.d.ts +5 -0
  66. package/dist/ui/file-preview/components/html-renderer.js +47 -0
  67. package/dist/ui/file-preview/components/markdown-renderer.d.ts +1 -0
  68. package/dist/ui/file-preview/components/markdown-renderer.js +67 -0
  69. package/dist/ui/file-preview/components/toolbar.d.ts +6 -0
  70. package/dist/ui/file-preview/components/toolbar.js +75 -0
  71. package/dist/ui/file-preview/image-preview.d.ts +3 -0
  72. package/dist/ui/file-preview/image-preview.js +21 -0
  73. package/dist/ui/file-preview/main.js +5 -0
  74. package/dist/ui/file-preview/markdown/editor.d.ts +36 -0
  75. package/dist/ui/file-preview/markdown/editor.js +643 -0
  76. package/dist/ui/file-preview/markdown/linking.d.ts +9 -0
  77. package/dist/ui/file-preview/markdown/linking.js +210 -0
  78. package/dist/ui/file-preview/markdown/outline.d.ts +7 -0
  79. package/dist/ui/file-preview/markdown/outline.js +40 -0
  80. package/dist/ui/file-preview/markdown/preview.d.ts +8 -0
  81. package/dist/ui/file-preview/markdown/preview.js +33 -0
  82. package/dist/ui/file-preview/markdown/slugify.d.ts +3 -0
  83. package/dist/ui/file-preview/markdown/slugify.js +31 -0
  84. package/dist/ui/file-preview/markdown/toc.d.ts +11 -0
  85. package/dist/ui/file-preview/markdown/toc.js +75 -0
  86. package/dist/ui/file-preview/markdown/utils.d.ts +1 -0
  87. package/dist/ui/file-preview/markdown/utils.js +15 -0
  88. package/dist/ui/file-preview/markdown/workspace-controller.d.ts +25 -0
  89. package/dist/ui/file-preview/markdown/workspace-controller.js +40 -0
  90. package/dist/ui/file-preview/preview-runtime.js +399 -13969
  91. package/dist/ui/file-preview/shared/preview-file-types.d.ts +1 -1
  92. package/dist/ui/file-preview/shared/preview-file-types.js +3 -1
  93. package/dist/ui/file-preview/src/App.d.ts +4 -0
  94. package/dist/ui/file-preview/src/App.js +564 -0
  95. package/dist/ui/file-preview/src/components/CodeViewer.d.ts +6 -0
  96. package/dist/ui/file-preview/src/components/CodeViewer.js +60 -0
  97. package/dist/ui/file-preview/src/components/HtmlRenderer.d.ts +8 -0
  98. package/dist/ui/file-preview/src/components/HtmlRenderer.js +45 -0
  99. package/dist/ui/file-preview/src/components/MarkdownRenderer.d.ts +1 -0
  100. package/dist/ui/file-preview/src/components/MarkdownRenderer.js +15 -0
  101. package/dist/ui/file-preview/src/components/editor-toolbar.d.ts +15 -0
  102. package/dist/ui/file-preview/src/components/editor-toolbar.js +384 -0
  103. package/dist/ui/file-preview/src/components/html-renderer.d.ts +1 -5
  104. package/dist/ui/file-preview/src/components/html-renderer.js +11 -27
  105. package/dist/ui/file-preview/src/components/markdown-editor.d.ts +29 -0
  106. package/dist/ui/file-preview/src/components/markdown-editor.js +535 -0
  107. package/dist/ui/file-preview/src/components/markdown-renderer.js +47 -9
  108. package/dist/ui/file-preview/src/directory-controller.d.ts +8 -0
  109. package/dist/ui/file-preview/src/directory-controller.js +233 -0
  110. package/dist/ui/file-preview/src/document-layout.d.ts +20 -0
  111. package/dist/ui/file-preview/src/document-layout.js +109 -0
  112. package/dist/ui/file-preview/src/document-outline.d.ts +17 -0
  113. package/dist/ui/file-preview/src/document-outline.js +97 -0
  114. package/dist/ui/file-preview/src/document-workspace.d.ts +19 -0
  115. package/dist/ui/file-preview/src/document-workspace.js +33 -0
  116. package/dist/ui/file-preview/src/file-type-handlers.d.ts +10 -0
  117. package/dist/ui/file-preview/src/file-type-handlers.js +98 -0
  118. package/dist/ui/file-preview/src/host/external-actions.d.ts +19 -0
  119. package/dist/ui/file-preview/src/host/external-actions.js +94 -0
  120. package/dist/ui/file-preview/src/host/selection-context.d.ts +9 -0
  121. package/dist/ui/file-preview/src/host/selection-context.js +106 -0
  122. package/dist/ui/file-preview/src/markdown/block-merge.d.ts +25 -0
  123. package/dist/ui/file-preview/src/markdown/block-merge.js +86 -0
  124. package/dist/ui/file-preview/src/markdown/conflict-dialog.d.ts +40 -0
  125. package/dist/ui/file-preview/src/markdown/conflict-dialog.js +163 -0
  126. package/dist/ui/file-preview/src/markdown/controller.d.ts +38 -0
  127. package/dist/ui/file-preview/src/markdown/controller.js +921 -0
  128. package/dist/ui/file-preview/src/markdown/editor.d.ts +35 -0
  129. package/dist/ui/file-preview/src/markdown/editor.js +691 -0
  130. package/dist/ui/file-preview/src/markdown/link-modal.d.ts +13 -0
  131. package/dist/ui/file-preview/src/markdown/link-modal.js +213 -0
  132. package/dist/ui/file-preview/src/markdown/linking.d.ts +16 -0
  133. package/dist/ui/file-preview/src/markdown/linking.js +228 -0
  134. package/dist/ui/file-preview/src/markdown/outline.d.ts +2 -0
  135. package/dist/ui/file-preview/src/markdown/outline.js +16 -0
  136. package/dist/ui/file-preview/src/markdown/parser.d.ts +30 -0
  137. package/dist/ui/file-preview/src/markdown/parser.js +38 -0
  138. package/dist/ui/file-preview/src/markdown/preview.d.ts +1 -0
  139. package/dist/ui/file-preview/src/markdown/preview.js +20 -0
  140. package/dist/ui/file-preview/src/markdown/raw-editor.d.ts +8 -0
  141. package/dist/ui/file-preview/src/markdown/raw-editor.js +61 -0
  142. package/dist/ui/file-preview/src/markdown/selection-toolbar.d.ts +14 -0
  143. package/dist/ui/file-preview/src/markdown/selection-toolbar.js +128 -0
  144. package/dist/ui/file-preview/src/markdown/slugify.d.ts +3 -0
  145. package/dist/ui/file-preview/src/markdown/slugify.js +31 -0
  146. package/dist/ui/file-preview/src/markdown/toc.d.ts +11 -0
  147. package/dist/ui/file-preview/src/markdown/toc.js +75 -0
  148. package/dist/ui/file-preview/src/markdown/utils.d.ts +1 -0
  149. package/dist/ui/file-preview/src/markdown/utils.js +15 -0
  150. package/dist/ui/file-preview/src/markdown-workspace/editor.d.ts +36 -0
  151. package/dist/ui/file-preview/src/markdown-workspace/editor.js +643 -0
  152. package/dist/ui/file-preview/src/markdown-workspace/linking.d.ts +9 -0
  153. package/dist/ui/file-preview/src/markdown-workspace/linking.js +210 -0
  154. package/dist/ui/file-preview/src/markdown-workspace/outline.d.ts +7 -0
  155. package/dist/ui/file-preview/src/markdown-workspace/outline.js +40 -0
  156. package/dist/ui/file-preview/src/markdown-workspace/preview.d.ts +8 -0
  157. package/dist/ui/file-preview/src/markdown-workspace/preview.js +33 -0
  158. package/dist/ui/file-preview/src/markdown-workspace/slugify.d.ts +3 -0
  159. package/dist/ui/file-preview/src/markdown-workspace/slugify.js +31 -0
  160. package/dist/ui/file-preview/src/markdown-workspace/toc.d.ts +11 -0
  161. package/dist/ui/file-preview/src/markdown-workspace/toc.js +75 -0
  162. package/dist/ui/file-preview/src/markdown-workspace/utils.d.ts +1 -0
  163. package/dist/ui/file-preview/src/markdown-workspace/utils.js +15 -0
  164. package/dist/ui/file-preview/src/markdown-workspace/workspace-controller.d.ts +25 -0
  165. package/dist/ui/file-preview/src/markdown-workspace/workspace-controller.js +40 -0
  166. package/dist/ui/file-preview/src/model.d.ts +34 -0
  167. package/dist/ui/file-preview/src/panel-actions.d.ts +17 -0
  168. package/dist/ui/file-preview/src/panel-actions.js +182 -0
  169. package/dist/ui/file-preview/src/path-utils.d.ts +6 -0
  170. package/dist/ui/file-preview/src/path-utils.js +64 -0
  171. package/dist/ui/file-preview/src/payload-utils.d.ts +11 -0
  172. package/dist/ui/file-preview/src/payload-utils.js +94 -0
  173. package/dist/ui/file-preview/styles.css +1144 -277
  174. package/dist/ui/file-preview/types.d.ts +1 -0
  175. package/dist/ui/file-preview/types.js +1 -0
  176. package/dist/ui/resources.d.ts +7 -0
  177. package/dist/ui/resources.js +16 -2
  178. package/dist/ui/server-integration.d.ts +13 -0
  179. package/dist/ui/server-integration.js +31 -0
  180. package/dist/ui/shared/ToolHeader.d.ts +9 -0
  181. package/dist/ui/shared/ToolHeader.js +29 -0
  182. package/dist/ui/shared/app-bootstrap.d.ts +9 -0
  183. package/dist/ui/shared/app-bootstrap.js +15 -0
  184. package/dist/ui/shared/compact-row.d.ts +11 -0
  185. package/dist/ui/shared/compact-row.js +18 -0
  186. package/dist/ui/shared/guards.d.ts +1 -0
  187. package/dist/ui/shared/guards.js +3 -0
  188. package/dist/ui/shared/host-context.d.ts +15 -0
  189. package/dist/ui/shared/host-context.js +51 -0
  190. package/dist/ui/shared/host-lifecycle.d.ts +1 -0
  191. package/dist/ui/shared/host-lifecycle.js +8 -2
  192. package/dist/ui/shared/tool-bridge.d.ts +30 -0
  193. package/dist/ui/shared/tool-bridge.js +137 -0
  194. package/dist/ui/shared/tool-shell.d.ts +9 -0
  195. package/dist/ui/shared/tool-shell.js +46 -4
  196. package/dist/ui/shared/ui-event-tracker.d.ts +9 -0
  197. package/dist/ui/shared/ui-event-tracker.js +27 -0
  198. package/dist/ui/shared/widget-state.d.ts +6 -1
  199. package/dist/ui/shared/widget-state.js +102 -4
  200. package/dist/utils/capture.js +3 -3
  201. package/dist/utils/files/base.d.ts +2 -0
  202. package/dist/utils/open-browser.js +1 -1
  203. package/dist/utils/ui-call-context.d.ts +8 -0
  204. package/dist/utils/ui-call-context.js +72 -0
  205. package/dist/version.d.ts +1 -1
  206. package/dist/version.js +1 -1
  207. package/package.json +13 -4
  208. package/dist/data/spec-kit-prompts.json +0 -123
  209. package/dist/handlers/node-handlers.d.ts +0 -6
  210. package/dist/handlers/node-handlers.js +0 -73
  211. package/dist/handlers/test-crash-handler.d.ts +0 -11
  212. package/dist/handlers/test-crash-handler.js +0 -26
  213. package/dist/http-index.d.ts +0 -45
  214. package/dist/http-index.js +0 -51
  215. package/dist/http-server-auto-tunnel.js +0 -667
  216. package/dist/http-server-named-tunnel.d.ts +0 -2
  217. package/dist/http-server-named-tunnel.js +0 -167
  218. package/dist/http-server-tunnel.d.ts +0 -2
  219. package/dist/http-server-tunnel.js +0 -111
  220. package/dist/http-server.d.ts +0 -2
  221. package/dist/http-server.js +0 -270
  222. package/dist/index-oauth.d.ts +0 -2
  223. package/dist/index-oauth.js +0 -201
  224. package/dist/oauth/auth-middleware.d.ts +0 -20
  225. package/dist/oauth/auth-middleware.js +0 -62
  226. package/dist/oauth/index.d.ts +0 -3
  227. package/dist/oauth/index.js +0 -3
  228. package/dist/oauth/oauth-manager.d.ts +0 -80
  229. package/dist/oauth/oauth-manager.js +0 -179
  230. package/dist/oauth/oauth-routes.d.ts +0 -3
  231. package/dist/oauth/oauth-routes.js +0 -377
  232. package/dist/oauth/provider.d.ts +0 -22
  233. package/dist/oauth/provider.js +0 -124
  234. package/dist/oauth/server.d.ts +0 -18
  235. package/dist/oauth/server.js +0 -160
  236. package/dist/oauth/types.d.ts +0 -54
  237. package/dist/oauth/types.js +0 -2
  238. package/dist/remote-device/templates/auth-success.d.ts +0 -1
  239. package/dist/remote-device/templates/auth-success.js +0 -30
  240. package/dist/setup.log +0 -275
  241. package/dist/test-setup.js +0 -14
  242. package/dist/tools/docx/builders/html-builder.d.ts +0 -17
  243. package/dist/tools/docx/builders/html-builder.js +0 -92
  244. package/dist/tools/docx/builders/image.d.ts +0 -14
  245. package/dist/tools/docx/builders/image.js +0 -84
  246. package/dist/tools/docx/builders/index.d.ts +0 -11
  247. package/dist/tools/docx/builders/index.js +0 -11
  248. package/dist/tools/docx/builders/markdown-builder.d.ts +0 -2
  249. package/dist/tools/docx/builders/markdown-builder.js +0 -260
  250. package/dist/tools/docx/builders/paragraph.d.ts +0 -12
  251. package/dist/tools/docx/builders/paragraph.js +0 -29
  252. package/dist/tools/docx/builders/table.d.ts +0 -10
  253. package/dist/tools/docx/builders/table.js +0 -138
  254. package/dist/tools/docx/builders/utils.d.ts +0 -5
  255. package/dist/tools/docx/builders/utils.js +0 -18
  256. package/dist/tools/docx/constants.d.ts +0 -32
  257. package/dist/tools/docx/constants.js +0 -61
  258. package/dist/tools/docx/converters/markdown-to-html.d.ts +0 -17
  259. package/dist/tools/docx/converters/markdown-to-html.js +0 -111
  260. package/dist/tools/docx/create.d.ts +0 -21
  261. package/dist/tools/docx/create.js +0 -386
  262. package/dist/tools/docx/dom.d.ts +0 -139
  263. package/dist/tools/docx/dom.js +0 -448
  264. package/dist/tools/docx/errors.d.ts +0 -28
  265. package/dist/tools/docx/errors.js +0 -48
  266. package/dist/tools/docx/extractors/images.d.ts +0 -14
  267. package/dist/tools/docx/extractors/images.js +0 -40
  268. package/dist/tools/docx/extractors/metadata.d.ts +0 -14
  269. package/dist/tools/docx/extractors/metadata.js +0 -64
  270. package/dist/tools/docx/extractors/sections.d.ts +0 -14
  271. package/dist/tools/docx/extractors/sections.js +0 -61
  272. package/dist/tools/docx/html.d.ts +0 -17
  273. package/dist/tools/docx/html.js +0 -111
  274. package/dist/tools/docx/index.d.ts +0 -10
  275. package/dist/tools/docx/index.js +0 -10
  276. package/dist/tools/docx/markdown.d.ts +0 -84
  277. package/dist/tools/docx/markdown.js +0 -507
  278. package/dist/tools/docx/modify.d.ts +0 -28
  279. package/dist/tools/docx/modify.js +0 -271
  280. package/dist/tools/docx/operations/handlers/index.d.ts +0 -39
  281. package/dist/tools/docx/operations/handlers/index.js +0 -152
  282. package/dist/tools/docx/operations/html-manipulator.d.ts +0 -24
  283. package/dist/tools/docx/operations/html-manipulator.js +0 -352
  284. package/dist/tools/docx/operations/index.d.ts +0 -14
  285. package/dist/tools/docx/operations/index.js +0 -61
  286. package/dist/tools/docx/operations/operation-handlers.d.ts +0 -3
  287. package/dist/tools/docx/operations/operation-handlers.js +0 -67
  288. package/dist/tools/docx/operations/preprocessor.d.ts +0 -14
  289. package/dist/tools/docx/operations/preprocessor.js +0 -44
  290. package/dist/tools/docx/operations/xml-replacer.d.ts +0 -9
  291. package/dist/tools/docx/operations/xml-replacer.js +0 -35
  292. package/dist/tools/docx/operations.d.ts +0 -13
  293. package/dist/tools/docx/operations.js +0 -13
  294. package/dist/tools/docx/ops/delete-paragraph-at-body-index.d.ts +0 -11
  295. package/dist/tools/docx/ops/delete-paragraph-at-body-index.js +0 -23
  296. package/dist/tools/docx/ops/header-replace-text-exact.d.ts +0 -13
  297. package/dist/tools/docx/ops/header-replace-text-exact.js +0 -55
  298. package/dist/tools/docx/ops/index.d.ts +0 -17
  299. package/dist/tools/docx/ops/index.js +0 -70
  300. package/dist/tools/docx/ops/insert-image-after-text.d.ts +0 -24
  301. package/dist/tools/docx/ops/insert-image-after-text.js +0 -128
  302. package/dist/tools/docx/ops/insert-paragraph-after-text.d.ts +0 -12
  303. package/dist/tools/docx/ops/insert-paragraph-after-text.js +0 -74
  304. package/dist/tools/docx/ops/insert-table-after-text.d.ts +0 -19
  305. package/dist/tools/docx/ops/insert-table-after-text.js +0 -57
  306. package/dist/tools/docx/ops/replace-hyperlink-url.d.ts +0 -12
  307. package/dist/tools/docx/ops/replace-hyperlink-url.js +0 -37
  308. package/dist/tools/docx/ops/replace-paragraph-at-body-index.d.ts +0 -9
  309. package/dist/tools/docx/ops/replace-paragraph-at-body-index.js +0 -25
  310. package/dist/tools/docx/ops/replace-paragraph-text-exact.d.ts +0 -21
  311. package/dist/tools/docx/ops/replace-paragraph-text-exact.js +0 -36
  312. package/dist/tools/docx/ops/replace-table-cell-text.d.ts +0 -25
  313. package/dist/tools/docx/ops/replace-table-cell-text.js +0 -85
  314. package/dist/tools/docx/ops/set-color-for-paragraph-exact.d.ts +0 -9
  315. package/dist/tools/docx/ops/set-color-for-paragraph-exact.js +0 -24
  316. package/dist/tools/docx/ops/set-color-for-style.d.ts +0 -13
  317. package/dist/tools/docx/ops/set-color-for-style.js +0 -31
  318. package/dist/tools/docx/ops/set-paragraph-style-at-body-index.d.ts +0 -8
  319. package/dist/tools/docx/ops/set-paragraph-style-at-body-index.js +0 -57
  320. package/dist/tools/docx/ops/table-set-cell-text.d.ts +0 -9
  321. package/dist/tools/docx/ops/table-set-cell-text.js +0 -40
  322. package/dist/tools/docx/parsers/image-extractor.d.ts +0 -18
  323. package/dist/tools/docx/parsers/image-extractor.js +0 -61
  324. package/dist/tools/docx/parsers/index.d.ts +0 -9
  325. package/dist/tools/docx/parsers/index.js +0 -9
  326. package/dist/tools/docx/parsers/paragraph-parser.d.ts +0 -2
  327. package/dist/tools/docx/parsers/paragraph-parser.js +0 -88
  328. package/dist/tools/docx/parsers/table-parser.d.ts +0 -9
  329. package/dist/tools/docx/parsers/table-parser.js +0 -72
  330. package/dist/tools/docx/parsers/xml-parser.d.ts +0 -25
  331. package/dist/tools/docx/parsers/xml-parser.js +0 -71
  332. package/dist/tools/docx/parsers/zip-reader.d.ts +0 -23
  333. package/dist/tools/docx/parsers/zip-reader.js +0 -52
  334. package/dist/tools/docx/read.d.ts +0 -27
  335. package/dist/tools/docx/read.js +0 -308
  336. package/dist/tools/docx/relationships.d.ts +0 -22
  337. package/dist/tools/docx/relationships.js +0 -76
  338. package/dist/tools/docx/structure.d.ts +0 -25
  339. package/dist/tools/docx/structure.js +0 -102
  340. package/dist/tools/docx/styled-html-parser.d.ts +0 -23
  341. package/dist/tools/docx/styled-html-parser.js +0 -1262
  342. package/dist/tools/docx/types.d.ts +0 -213
  343. package/dist/tools/docx/types.js +0 -5
  344. package/dist/tools/docx/utils/escaping.d.ts +0 -13
  345. package/dist/tools/docx/utils/escaping.js +0 -26
  346. package/dist/tools/docx/utils/images.d.ts +0 -9
  347. package/dist/tools/docx/utils/images.js +0 -26
  348. package/dist/tools/docx/utils/index.d.ts +0 -12
  349. package/dist/tools/docx/utils/index.js +0 -17
  350. package/dist/tools/docx/utils/markdown.d.ts +0 -13
  351. package/dist/tools/docx/utils/markdown.js +0 -32
  352. package/dist/tools/docx/utils/paths.d.ts +0 -15
  353. package/dist/tools/docx/utils/paths.js +0 -27
  354. package/dist/tools/docx/utils/versioning.d.ts +0 -25
  355. package/dist/tools/docx/utils/versioning.js +0 -55
  356. package/dist/tools/docx/utils.d.ts +0 -101
  357. package/dist/tools/docx/utils.js +0 -299
  358. package/dist/tools/docx/validate.d.ts +0 -33
  359. package/dist/tools/docx/validate.js +0 -49
  360. package/dist/tools/docx/validators.d.ts +0 -13
  361. package/dist/tools/docx/validators.js +0 -40
  362. package/dist/tools/docx/write.d.ts +0 -17
  363. package/dist/tools/docx/write.js +0 -88
  364. package/dist/tools/docx/xml-view-test.js +0 -63
  365. package/dist/tools/docx/xml-view.d.ts +0 -56
  366. package/dist/tools/docx/xml-view.js +0 -169
  367. package/dist/tools/docx/zip.d.ts +0 -21
  368. package/dist/tools/docx/zip.js +0 -35
  369. package/dist/tools/pdf-processor.js +0 -3
  370. package/dist/tools/search.d.ts +0 -32
  371. package/dist/tools/search.js +0 -202
  372. package/dist/ui/file-preview/src/app.d.ts +0 -4
  373. package/dist/ui/file-preview/src/app.js +0 -800
  374. package/dist/utils/crash-logger.d.ts +0 -18
  375. package/dist/utils/crash-logger.js +0 -44
  376. package/dist/utils/dedent.d.ts +0 -8
  377. package/dist/utils/dedent.js +0 -38
  378. /package/dist/{http-server-auto-tunnel.d.ts → ui/config-editor/main.d.ts} +0 -0
  379. /package/dist/{test-docx.d.ts → ui/config-editor/src/main.d.ts} +0 -0
  380. /package/dist/{tools/docx/xml-view-test.d.ts → ui/file-preview/main.d.ts} +0 -0
  381. /package/dist/ui/file-preview/src/components/{toolbar.d.ts → Toolbar.d.ts} +0 -0
  382. /package/dist/ui/file-preview/src/components/{toolbar.js → Toolbar.js} +0 -0
  383. /package/dist/{tools/pdf-processor.d.ts → ui/file-preview/src/model.js} +0 -0
@@ -0,0 +1,840 @@
1
+ import { App } from '@modelcontextprotocol/ext-apps';
2
+ import { createToolBridge } from '../../shared/tool-bridge.js';
3
+ import { createCompactRowShellController } from '../../shared/tool-shell.js';
4
+ import { renderCompactRow } from '../../shared/compact-row.js';
5
+ import { escapeHtml } from '../../shared/escape-html.js';
6
+ import { createWidgetStateStorage } from '../../shared/widget-state.js';
7
+ import { connectWithSharedHostContext, isObjectRecord } from '../../shared/host-context.js';
8
+ import { createUiEventTracker } from '../../shared/ui-event-tracker.js';
9
+ import { createArrayModalController, renderArrayModalMarkup } from './array-modal.js';
10
+ import { CONFIG_FIELD_DEFINITIONS, isConfigFieldKey } from '../../../config-field-definitions.js';
11
+ let shellController;
12
+ const CONFIG_EDITOR_COMPONENT = 'config_editor';
13
+ const GET_CONFIG_TOOL_NAME = 'get_config';
14
+ const MAX_TELEMETRY_MESSAGE_LENGTH = 180;
15
+ function sanitizeTelemetryErrorMessage(message) {
16
+ // Keep error signal useful while removing path-like data and bounding payload size.
17
+ const collapsed = message.replace(/\s+/g, ' ').trim();
18
+ const withoutPaths = collapsed
19
+ .replace(/(?:\/|\\)[\w\d_.\-/\\]+/g, '[PATH]')
20
+ .replace(/[A-Za-z]:\\[\w\d_.\-/\\]+/g, '[PATH]');
21
+ if (withoutPaths.length === 0) {
22
+ return 'Unknown error';
23
+ }
24
+ if (withoutPaths.length <= MAX_TELEMETRY_MESSAGE_LENGTH) {
25
+ return withoutPaths;
26
+ }
27
+ return `${withoutPaths.slice(0, MAX_TELEMETRY_MESSAGE_LENGTH - 3)}...`;
28
+ }
29
+ function buildConfigUpdateTelemetryParams(args) {
30
+ const base = {
31
+ config_key: args.configKey,
32
+ value_type: args.valueType,
33
+ };
34
+ if (args.errorStage) {
35
+ base.error_stage = args.errorStage;
36
+ }
37
+ if (args.errorMessage) {
38
+ base.error_message = sanitizeTelemetryErrorMessage(args.errorMessage);
39
+ }
40
+ return base;
41
+ }
42
+ function isConfigEditorPayload(value) {
43
+ return isObjectRecord(value) && Array.isArray(value.entries);
44
+ }
45
+ function stringifyValueForInput(value) {
46
+ if (Array.isArray(value)) {
47
+ return value.map((item) => String(item)).join('\n');
48
+ }
49
+ if (typeof value === 'string') {
50
+ return value;
51
+ }
52
+ if (typeof value === 'number' || typeof value === 'boolean') {
53
+ return String(value);
54
+ }
55
+ if (value === null) {
56
+ return 'null';
57
+ }
58
+ try {
59
+ return JSON.stringify(value);
60
+ }
61
+ catch {
62
+ return String(value);
63
+ }
64
+ }
65
+ function formatKeyLabel(key) {
66
+ return key
67
+ .replace(/([a-z0-9])([A-Z])/g, '$1 $2')
68
+ .replace(/[_-]+/g, ' ')
69
+ .trim()
70
+ .split(/\s+/)
71
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
72
+ .join(' ');
73
+ }
74
+ function getConfigFieldMetadata(key) {
75
+ if (!isConfigFieldKey(key)) {
76
+ return undefined;
77
+ }
78
+ return {
79
+ label: CONFIG_FIELD_DEFINITIONS[key].label,
80
+ description: CONFIG_FIELD_DEFINITIONS[key].description,
81
+ };
82
+ }
83
+ function extractPayload(result) {
84
+ if (!isObjectRecord(result)) {
85
+ return null;
86
+ }
87
+ const structured = result.structuredContent;
88
+ if (!isObjectRecord(structured) || !Array.isArray(structured.entries)) {
89
+ return null;
90
+ }
91
+ const entries = structured.entries
92
+ .filter((entry) => isObjectRecord(entry))
93
+ .filter((entry) => typeof entry.key === 'string')
94
+ .map((entry) => {
95
+ const key = entry.key;
96
+ const metadata = getConfigFieldMetadata(key);
97
+ return {
98
+ key,
99
+ label: metadata?.label,
100
+ description: metadata?.description,
101
+ value: entry.value,
102
+ valueType: typeof entry.valueType === 'string' ? entry.valueType : 'string',
103
+ editable: entry.editable !== false,
104
+ };
105
+ });
106
+ return {
107
+ config: isObjectRecord(structured.config) ? structured.config : undefined,
108
+ uiHints: isObjectRecord(structured.uiHints)
109
+ ? {
110
+ availableShells: Array.isArray(structured.uiHints.availableShells)
111
+ ? structured.uiHints.availableShells.filter((value) => typeof value === 'string')
112
+ : undefined,
113
+ }
114
+ : undefined,
115
+ entries,
116
+ };
117
+ }
118
+ function extractToolText(result) {
119
+ if (!isObjectRecord(result) || !Array.isArray(result.content)) {
120
+ return undefined;
121
+ }
122
+ for (const item of result.content) {
123
+ if (!isObjectRecord(item)) {
124
+ continue;
125
+ }
126
+ if (item.type === 'text' && typeof item.text === 'string' && item.text.trim().length > 0) {
127
+ return item.text;
128
+ }
129
+ }
130
+ return undefined;
131
+ }
132
+ function isToolErrorResult(result) {
133
+ return isObjectRecord(result) && result.isError === true;
134
+ }
135
+ function parseDraftValue(rawValue, valueType) {
136
+ if (valueType === 'string') {
137
+ return { ok: true, value: rawValue.replace(/\r?\n/g, ' ') };
138
+ }
139
+ if (valueType === 'number') {
140
+ if (rawValue.trim() === '') {
141
+ return { ok: false, message: 'Enter a valid number.' };
142
+ }
143
+ const numeric = Number(rawValue);
144
+ if (!Number.isFinite(numeric)) {
145
+ return { ok: false, message: 'Enter a valid number.' };
146
+ }
147
+ return { ok: true, value: numeric };
148
+ }
149
+ if (valueType === 'boolean') {
150
+ const normalized = rawValue.trim().toLowerCase();
151
+ if (normalized !== 'true' && normalized !== 'false') {
152
+ return { ok: false, message: 'Boolean values must be true or false.' };
153
+ }
154
+ return { ok: true, value: normalized === 'true' };
155
+ }
156
+ if (valueType === 'null') {
157
+ if (rawValue.trim().toLowerCase() !== 'null') {
158
+ return { ok: false, message: 'Null values must be exactly null.' };
159
+ }
160
+ return { ok: true, value: null };
161
+ }
162
+ if (valueType === 'array') {
163
+ const trimmed = rawValue.trim();
164
+ if (trimmed.length === 0) {
165
+ return { ok: true, value: [] };
166
+ }
167
+ if (!trimmed.startsWith('[')) {
168
+ const items = rawValue
169
+ .split(/\r?\n/)
170
+ .map((item) => item.trim())
171
+ .filter((item) => item.length > 0);
172
+ return { ok: true, value: items };
173
+ }
174
+ try {
175
+ const parsed = JSON.parse(trimmed);
176
+ if (!Array.isArray(parsed)) {
177
+ return { ok: false, message: 'Array values must be valid JSON arrays.' };
178
+ }
179
+ if (!parsed.every((item) => typeof item === 'string')) {
180
+ return { ok: false, message: 'Array values must contain only strings.' };
181
+ }
182
+ return { ok: true, value: parsed };
183
+ }
184
+ catch {
185
+ return { ok: false, message: 'Array values must be valid JSON arrays.' };
186
+ }
187
+ }
188
+ return { ok: true, value: rawValue };
189
+ }
190
+ function areConfigValuesEqual(left, right) {
191
+ if (Object.is(left, right)) {
192
+ return true;
193
+ }
194
+ if (Array.isArray(left) && Array.isArray(right)) {
195
+ if (left.length !== right.length) {
196
+ return false;
197
+ }
198
+ for (let index = 0; index < left.length; index += 1) {
199
+ if (!Object.is(left[index], right[index])) {
200
+ return false;
201
+ }
202
+ }
203
+ return true;
204
+ }
205
+ return false;
206
+ }
207
+ function parseDraftArrayValues(draft) {
208
+ const trimmed = draft.trim();
209
+ if (!trimmed) {
210
+ return [];
211
+ }
212
+ if (trimmed.startsWith('[')) {
213
+ try {
214
+ const parsed = JSON.parse(trimmed);
215
+ if (Array.isArray(parsed)) {
216
+ return parsed.filter((item) => typeof item === 'string');
217
+ }
218
+ }
219
+ catch {
220
+ // fallback below
221
+ }
222
+ }
223
+ return draft
224
+ .split(/\r?\n/)
225
+ .map((line) => line.trim())
226
+ .filter((line) => line.length > 0);
227
+ }
228
+ function getSettingSummary(entry) {
229
+ if (entry.key !== 'blockedCommands' && entry.key !== 'allowedDirectories') {
230
+ return null;
231
+ }
232
+ const values = Array.isArray(entry.value)
233
+ ? entry.value.filter((item) => typeof item === 'string' && item.trim().length > 0)
234
+ : [];
235
+ const count = values.length;
236
+ if (entry.key === 'blockedCommands') {
237
+ return `${count} command${count === 1 ? '' : 's'} blocked`;
238
+ }
239
+ if (count === 0) {
240
+ return 'All folders allowed (no restriction)';
241
+ }
242
+ return `${count} folder${count === 1 ? '' : 's'} allowed`;
243
+ }
244
+ function getShellOptions(payload, currentShell) {
245
+ const hintedShells = Array.isArray(payload?.uiHints?.availableShells)
246
+ ? payload.uiHints.availableShells.filter((shell) => typeof shell === 'string' && shell.trim().length > 0)
247
+ : [];
248
+ const config = payload?.config;
249
+ const systemInfo = isObjectRecord(config?.systemInfo) ? config.systemInfo : null;
250
+ const isWindows = Boolean(systemInfo && systemInfo.isWindows === true);
251
+ const isMacOS = Boolean(systemInfo && systemInfo.isMacOS === true);
252
+ const baseOptions = hintedShells.length > 0
253
+ ? hintedShells
254
+ : isWindows
255
+ ? ['powershell.exe', 'pwsh.exe', 'cmd.exe', 'bash.exe']
256
+ : isMacOS
257
+ ? ['/bin/zsh', '/bin/bash', '/bin/sh', '/usr/bin/fish', 'zsh', 'bash', 'sh', 'fish']
258
+ : ['/bin/bash', '/bin/sh', '/usr/bin/fish', '/bin/zsh', 'bash', 'sh', 'fish', 'zsh'];
259
+ const options = new Set();
260
+ for (const shell of baseOptions) {
261
+ options.add(shell);
262
+ }
263
+ if (currentShell.trim().length > 0) {
264
+ options.add(currentShell);
265
+ }
266
+ return [...options];
267
+ }
268
+ export function createConfigEditorController(callTool, trackConfigUiEvent) {
269
+ const state = {
270
+ payload: null,
271
+ selectedKey: null,
272
+ draftValue: '',
273
+ };
274
+ const getSelectedEntry = () => {
275
+ if (!state.payload || !state.selectedKey) {
276
+ return undefined;
277
+ }
278
+ return state.payload.entries.find((entry) => entry.key === state.selectedKey);
279
+ };
280
+ const setPayload = (payload) => {
281
+ state.payload = payload;
282
+ if (!payload || payload.entries.length === 0) {
283
+ state.selectedKey = null;
284
+ state.draftValue = '';
285
+ return;
286
+ }
287
+ if (!state.selectedKey || !payload.entries.some((entry) => entry.key === state.selectedKey)) {
288
+ state.selectedKey = payload.entries[0].key;
289
+ }
290
+ const current = getSelectedEntry();
291
+ state.draftValue = current ? stringifyValueForInput(current.value) : '';
292
+ };
293
+ const setSelection = (key) => {
294
+ state.selectedKey = key;
295
+ const selected = getSelectedEntry();
296
+ state.draftValue = selected ? stringifyValueForInput(selected.value) : '';
297
+ };
298
+ const setDraftValue = (value) => {
299
+ state.draftValue = value;
300
+ };
301
+ const apply = async () => {
302
+ const selected = getSelectedEntry();
303
+ if (!selected) {
304
+ return {
305
+ ok: false,
306
+ tooltip: {
307
+ message: 'Select a config key before applying.',
308
+ tone: 'error',
309
+ },
310
+ };
311
+ }
312
+ if (!selected.editable) {
313
+ return {
314
+ ok: false,
315
+ tooltip: {
316
+ message: `The selected key (${selected.key}) is read-only.`,
317
+ tone: 'error',
318
+ },
319
+ };
320
+ }
321
+ const parsed = parseDraftValue(state.draftValue, selected.valueType);
322
+ if (!parsed.ok) {
323
+ return {
324
+ ok: false,
325
+ tooltip: {
326
+ message: parsed.message,
327
+ tone: 'error',
328
+ },
329
+ };
330
+ }
331
+ if (areConfigValuesEqual(parsed.value, selected.value)) {
332
+ state.draftValue = stringifyValueForInput(selected.value);
333
+ return { ok: false };
334
+ }
335
+ try {
336
+ const setResult = await callTool('set_config_value', {
337
+ key: selected.key,
338
+ value: parsed.value,
339
+ origin: 'ui',
340
+ });
341
+ if (isToolErrorResult(setResult)) {
342
+ const errorMessage = extractToolText(setResult) ?? `Failed to update ${selected.key}.`;
343
+ trackConfigUiEvent?.('config_update_failed', {
344
+ tool_name: 'set_config_value',
345
+ ...buildConfigUpdateTelemetryParams({
346
+ configKey: selected.key,
347
+ valueType: selected.valueType,
348
+ errorMessage,
349
+ errorStage: 'set_config_value',
350
+ }),
351
+ });
352
+ return {
353
+ ok: false,
354
+ tooltip: {
355
+ message: errorMessage,
356
+ tone: 'error',
357
+ },
358
+ };
359
+ }
360
+ trackConfigUiEvent?.('config_update_success', {
361
+ tool_name: 'set_config_value',
362
+ ...buildConfigUpdateTelemetryParams({
363
+ configKey: selected.key,
364
+ valueType: selected.valueType,
365
+ }),
366
+ });
367
+ const refreshed = await callTool('get_config', {});
368
+ if (isToolErrorResult(refreshed)) {
369
+ const errorMessage = extractToolText(refreshed) ?? 'Value was updated but config refresh failed.';
370
+ return {
371
+ ok: false,
372
+ tooltip: {
373
+ message: errorMessage,
374
+ tone: 'error',
375
+ },
376
+ };
377
+ }
378
+ const refreshedPayload = extractPayload(refreshed);
379
+ if (refreshedPayload) {
380
+ setPayload(refreshedPayload);
381
+ if (state.selectedKey === selected.key) {
382
+ const updatedSelected = getSelectedEntry();
383
+ state.draftValue = updatedSelected
384
+ ? stringifyValueForInput(updatedSelected.value)
385
+ : state.draftValue;
386
+ }
387
+ }
388
+ return {
389
+ ok: true,
390
+ };
391
+ }
392
+ catch (error) {
393
+ const errorMessage = `Failed to apply value: ${error instanceof Error ? error.message : String(error)}`;
394
+ trackConfigUiEvent?.('config_update_failed', {
395
+ tool_name: 'set_config_value',
396
+ ...buildConfigUpdateTelemetryParams({
397
+ configKey: selected.key,
398
+ valueType: selected.valueType,
399
+ errorMessage,
400
+ errorStage: 'transport',
401
+ }),
402
+ });
403
+ return {
404
+ ok: false,
405
+ tooltip: {
406
+ message: errorMessage,
407
+ tone: 'error',
408
+ },
409
+ };
410
+ }
411
+ };
412
+ return {
413
+ state,
414
+ callTool,
415
+ extractPayload,
416
+ setPayload,
417
+ setSelection,
418
+ setDraftValue,
419
+ apply,
420
+ };
421
+ }
422
+ function render(container, controller, chrome, hooks = {}) {
423
+ shellController?.dispose();
424
+ shellController = undefined;
425
+ const { state } = controller;
426
+ const entries = state.payload?.entries ?? [];
427
+ const shellClasses = [
428
+ 'shell',
429
+ 'tool-shell',
430
+ chrome.expanded ? 'expanded' : 'collapsed',
431
+ 'config-shell',
432
+ chrome.hideSummaryRow ? 'host-framed' : '',
433
+ chrome.compact ? 'compact' : '',
434
+ ].filter(Boolean).join(' ');
435
+ const settingsHtml = entries.map((entry, index) => {
436
+ const keyTitle = entry.label ?? formatKeyLabel(entry.key);
437
+ const description = entry.description ?? '';
438
+ const summary = getSettingSummary(entry);
439
+ let controlHtml;
440
+ if (entry.key === 'defaultShell') {
441
+ const currentShell = String(entry.value ?? '');
442
+ const shellOptions = getShellOptions(state.payload, currentShell);
443
+ const isCustomShell = !shellOptions.includes(currentShell);
444
+ const options = shellOptions
445
+ .map((shell) => `<option value="${escapeHtml(shell)}" ${shell === currentShell ? 'selected' : ''}>${escapeHtml(shell)}</option>`)
446
+ .join('');
447
+ controlHtml = `
448
+ <div class="setting-shell-control">
449
+ <select class="setting-inline-select" data-action="shell-select" data-key-index="${index}">
450
+ ${options}
451
+ <option value="__custom__" ${isCustomShell ? 'selected' : ''}>Custom...</option>
452
+ </select>
453
+ <input class="setting-inline-input setting-shell-custom${isCustomShell ? '' : ' hidden'}" data-action="shell-custom" data-key-index="${index}" type="text" value="${escapeHtml(currentShell)}" placeholder="Type custom shell path"/>
454
+ </div>
455
+ `;
456
+ }
457
+ else if (entry.valueType === 'boolean') {
458
+ const checked = String(entry.value) === 'true' ? 'checked' : '';
459
+ controlHtml = `<label class="setting-switch"><input type="checkbox" data-action="toggle-boolean" data-key-index="${index}" ${checked}/><span class="config-boolean-slider"></span></label>`;
460
+ }
461
+ else if (entry.valueType === 'number') {
462
+ controlHtml = `<input class="setting-inline-input" data-action="edit-number" data-key-index="${index}" type="number" step="any" value="${escapeHtml(String(entry.value ?? ''))}"/>`;
463
+ }
464
+ else if (entry.valueType === 'array') {
465
+ controlHtml = `<button class="setting-inline-action" data-action="open-array" data-key-index="${index}">Edit</button>`;
466
+ }
467
+ else if (entry.valueType === 'null') {
468
+ controlHtml = `<span class="setting-inline-static">null</span>`;
469
+ }
470
+ else {
471
+ controlHtml = `<input class="setting-inline-input" data-action="edit-string" data-key-index="${index}" type="text" value="${escapeHtml(String(entry.value ?? ''))}"/>`;
472
+ }
473
+ return `
474
+ <section class="setting-row">
475
+ <div class="setting-info">
476
+ <h3>${escapeHtml(keyTitle)}</h3>
477
+ ${description ? `<p>${escapeHtml(description)}</p>` : ''}
478
+ <p class="setting-summary${summary ? '' : ' hidden'}" data-setting-summary-key="${escapeHtml(entry.key)}">${summary ? escapeHtml(summary) : ''}</p>
479
+ </div>
480
+ <div class="setting-control">${controlHtml}</div>
481
+ </section>
482
+ `;
483
+ }).join('');
484
+ container.innerHTML = `
485
+ <main id="tool-shell" class="${shellClasses}">
486
+ ${renderCompactRow({ id: 'compact-toggle', label: 'View config', filename: 'Desktop Commander', variant: 'ready', expandable: true, expanded: chrome.expanded, interactive: true })}
487
+
488
+ <section class="panel config-card">
489
+ <div class="panel-content-wrapper">
490
+ <div class="settings-stack" aria-label="Desktop Commander settings">${settingsHtml}</div>
491
+ </div>
492
+ </section>
493
+
494
+ ${renderArrayModalMarkup('List Setting')}
495
+ </main>
496
+ <div id="config-tooltip" class="config-tooltip" role="status" aria-live="polite" hidden></div>
497
+ `;
498
+ const toolShell = container.querySelector('#tool-shell');
499
+ const compactRow = container.querySelector('.compact-row--ready');
500
+ const getUpdatedEntryByKey = (key) => {
501
+ return controller.state.payload?.entries.find((item) => item.key === key);
502
+ };
503
+ const refreshSettingSummary = (key) => {
504
+ const summaryElement = container.querySelector(`[data-setting-summary-key="${key}"]`);
505
+ if (!summaryElement) {
506
+ return;
507
+ }
508
+ const updatedEntry = getUpdatedEntryByKey(key);
509
+ const summary = updatedEntry ? getSettingSummary(updatedEntry) : null;
510
+ summaryElement.textContent = summary ?? '';
511
+ summaryElement.classList.toggle('hidden', !summary);
512
+ };
513
+ const emitConfigChanged = (key, fallbackValue) => {
514
+ const updatedEntry = getUpdatedEntryByKey(key);
515
+ refreshSettingSummary(key);
516
+ hooks.onConfigChanged?.({
517
+ key,
518
+ value: updatedEntry ? updatedEntry.value : fallbackValue,
519
+ });
520
+ };
521
+ const emitTooltip = (result) => {
522
+ if (result.tooltip) {
523
+ hooks.onTooltip?.(result.tooltip);
524
+ }
525
+ };
526
+ const arrayModal = createArrayModalController({
527
+ container,
528
+ parseEntryItems: (entry) => parseDraftArrayValues(stringifyValueForInput(entry.value)),
529
+ formatEntryTitle: (entry) => entry.label ?? formatKeyLabel(entry.key),
530
+ onSave: async (changedKey, items) => {
531
+ controller.setSelection(changedKey);
532
+ controller.setDraftValue(items.join('\n'));
533
+ const result = await controller.apply();
534
+ emitTooltip(result);
535
+ if (result.ok) {
536
+ emitConfigChanged(changedKey, items);
537
+ }
538
+ },
539
+ });
540
+ container.querySelectorAll('[data-action]').forEach((element) => {
541
+ const target = element;
542
+ const action = target.dataset.action;
543
+ const keyIndex = Number(target.dataset.keyIndex);
544
+ const entry = entries[keyIndex];
545
+ if (!entry) {
546
+ return;
547
+ }
548
+ if (action === 'toggle-boolean') {
549
+ target.addEventListener('change', async () => {
550
+ const input = target;
551
+ const previousChecked = input.checked;
552
+ controller.setSelection(entry.key);
553
+ controller.setDraftValue(input.checked ? 'true' : 'false');
554
+ const result = await controller.apply();
555
+ emitTooltip(result);
556
+ const updatedEntry = getUpdatedEntryByKey(entry.key);
557
+ if (updatedEntry && typeof updatedEntry.value === 'boolean') {
558
+ input.checked = updatedEntry.value;
559
+ }
560
+ else if (!result.ok) {
561
+ input.checked = !previousChecked;
562
+ }
563
+ if (result.ok) {
564
+ emitConfigChanged(entry.key, input.checked);
565
+ }
566
+ });
567
+ return;
568
+ }
569
+ if (action === 'edit-number') {
570
+ target.addEventListener('blur', async () => {
571
+ const input = target;
572
+ controller.setSelection(entry.key);
573
+ controller.setDraftValue(input.value);
574
+ const result = await controller.apply();
575
+ emitTooltip(result);
576
+ const updatedEntry = getUpdatedEntryByKey(entry.key);
577
+ input.value = String(updatedEntry?.value ?? controller.state.draftValue);
578
+ if (result.ok) {
579
+ emitConfigChanged(entry.key, input.value);
580
+ }
581
+ });
582
+ return;
583
+ }
584
+ if (action === 'shell-select') {
585
+ target.addEventListener('change', async () => {
586
+ const select = target;
587
+ const customInput = container.querySelector(`input[data-action="shell-custom"][data-key-index="${keyIndex}"]`);
588
+ if (select.value === '__custom__') {
589
+ customInput?.classList.remove('hidden');
590
+ customInput?.focus();
591
+ return;
592
+ }
593
+ customInput?.classList.add('hidden');
594
+ controller.setSelection(entry.key);
595
+ controller.setDraftValue(select.value);
596
+ const result = await controller.apply();
597
+ emitTooltip(result);
598
+ const updatedEntry = getUpdatedEntryByKey(entry.key);
599
+ const shellValue = String(updatedEntry?.value ?? select.value);
600
+ const shellCustomInput = container.querySelector(`input[data-action="shell-custom"][data-key-index="${keyIndex}"]`);
601
+ if (shellCustomInput) {
602
+ shellCustomInput.value = shellValue;
603
+ }
604
+ if (result.ok) {
605
+ emitConfigChanged(entry.key, shellValue);
606
+ }
607
+ });
608
+ return;
609
+ }
610
+ if (action === 'shell-custom') {
611
+ const commitCustomShell = async () => {
612
+ const input = target;
613
+ if (!input.value.trim()) {
614
+ return;
615
+ }
616
+ controller.setSelection(entry.key);
617
+ controller.setDraftValue(input.value.trim());
618
+ const result = await controller.apply();
619
+ emitTooltip(result);
620
+ const updatedEntry = getUpdatedEntryByKey(entry.key);
621
+ input.value = String(updatedEntry?.value ?? controller.state.draftValue);
622
+ if (result.ok) {
623
+ emitConfigChanged(entry.key, input.value);
624
+ }
625
+ };
626
+ target.addEventListener('blur', () => {
627
+ void commitCustomShell();
628
+ });
629
+ target.addEventListener('keydown', (event) => {
630
+ if (event.key !== 'Enter') {
631
+ return;
632
+ }
633
+ event.preventDefault();
634
+ void commitCustomShell();
635
+ });
636
+ return;
637
+ }
638
+ if (action === 'edit-string') {
639
+ target.addEventListener('keydown', async (event) => {
640
+ if (event.key !== 'Enter') {
641
+ return;
642
+ }
643
+ event.preventDefault();
644
+ const input = target;
645
+ controller.setSelection(entry.key);
646
+ controller.setDraftValue(input.value.replace(/\r?\n/g, ' '));
647
+ const result = await controller.apply();
648
+ emitTooltip(result);
649
+ const updatedEntry = getUpdatedEntryByKey(entry.key);
650
+ input.value = String(updatedEntry?.value ?? controller.state.draftValue);
651
+ if (result.ok) {
652
+ emitConfigChanged(entry.key, input.value);
653
+ }
654
+ });
655
+ return;
656
+ }
657
+ if (action === 'open-array') {
658
+ target.addEventListener('click', () => {
659
+ const latestEntry = getUpdatedEntryByKey(entry.key) ?? entry;
660
+ arrayModal.open(latestEntry);
661
+ });
662
+ }
663
+ });
664
+ shellController = createCompactRowShellController({
665
+ shell: toolShell,
666
+ compactRow,
667
+ initialExpanded: chrome.expanded,
668
+ onToggle: (expanded) => {
669
+ chrome.expanded = expanded;
670
+ hooks.onExpandedChanged?.(expanded);
671
+ },
672
+ });
673
+ }
674
+ function markReady() {
675
+ document.body.classList.add('dc-ready');
676
+ }
677
+ export function bootstrapConfigEditorApp() {
678
+ const container = document.getElementById('app');
679
+ if (!container) {
680
+ return;
681
+ }
682
+ const bridge = createToolBridge();
683
+ const trackConfigUiEvent = createUiEventTracker((name, args) => bridge.callTool(name, args), {
684
+ component: CONFIG_EDITOR_COMPONENT,
685
+ baseParams: { origin: 'ui' },
686
+ });
687
+ const controller = createConfigEditorController((name, args) => bridge.callTool(name, args), trackConfigUiEvent);
688
+ const widgetState = createWidgetStateStorage(isConfigEditorPayload);
689
+ const chrome = {
690
+ hideSummaryRow: false,
691
+ compact: false,
692
+ expanded: true,
693
+ };
694
+ let configEditorShownEventSent = false;
695
+ let quietContextSupported = true;
696
+ let tooltipHideTimer = null;
697
+ const clearTooltipTimer = () => {
698
+ if (tooltipHideTimer !== null) {
699
+ window.clearTimeout(tooltipHideTimer);
700
+ tooltipHideTimer = null;
701
+ }
702
+ };
703
+ const showTooltip = (tooltip) => {
704
+ const tooltipElement = container.querySelector('#config-tooltip');
705
+ if (!tooltipElement) {
706
+ return;
707
+ }
708
+ clearTooltipTimer();
709
+ tooltipElement.className = `config-tooltip config-tooltip--${tooltip.tone}`;
710
+ tooltipElement.textContent = tooltip.message;
711
+ tooltipElement.hidden = false;
712
+ tooltipHideTimer = window.setTimeout(() => {
713
+ tooltipElement.hidden = true;
714
+ tooltipElement.textContent = '';
715
+ tooltipElement.className = 'config-tooltip';
716
+ tooltipHideTimer = null;
717
+ }, 2600);
718
+ };
719
+ const syncModelContext = (reason, change) => {
720
+ if (!quietContextSupported || !change) {
721
+ return;
722
+ }
723
+ app.updateModelContext({
724
+ content: [{ type: 'text', text: `Updated ${change.key} to ${JSON.stringify(change.value)} (${reason}).` }],
725
+ structuredContent: {
726
+ reason,
727
+ changedKey: change.key,
728
+ changedValue: change.value,
729
+ },
730
+ }).catch(() => {
731
+ // Host may not support updateModelContext; avoid repeated failed calls.
732
+ quietContextSupported = false;
733
+ });
734
+ };
735
+ let renderFrameId = null;
736
+ const scheduleRender = () => {
737
+ if (renderFrameId !== null) {
738
+ return;
739
+ }
740
+ renderFrameId = window.requestAnimationFrame(() => {
741
+ renderFrameId = null;
742
+ render(container, controller, chrome, {
743
+ onConfigChanged: (change) => {
744
+ if (controller.state.payload) {
745
+ widgetState.write(controller.state.payload);
746
+ }
747
+ syncModelContext('widget-edit', change);
748
+ },
749
+ onTooltip: showTooltip,
750
+ onExpandedChanged: (expanded) => {
751
+ trackConfigUiEvent(expanded ? 'expand' : 'collapse', {
752
+ tool_name: GET_CONFIG_TOOL_NAME,
753
+ expanded,
754
+ });
755
+ },
756
+ });
757
+ markReady();
758
+ });
759
+ };
760
+ scheduleRender();
761
+ const app = new App({ name: 'Desktop Commander Config Editor', version: '1.0.0' }, {}, { autoResize: true });
762
+ app.onteardown = async () => {
763
+ shellController?.dispose();
764
+ if (renderFrameId !== null) {
765
+ window.cancelAnimationFrame(renderFrameId);
766
+ renderFrameId = null;
767
+ }
768
+ clearTooltipTimer();
769
+ return {};
770
+ };
771
+ const applyPayload = (payload) => {
772
+ controller.setPayload(payload);
773
+ widgetState.write(payload);
774
+ scheduleRender();
775
+ if (!configEditorShownEventSent) {
776
+ configEditorShownEventSent = true;
777
+ // One-shot impression event for get_config UI card visibility.
778
+ trackConfigUiEvent('config_editor_shown', {
779
+ tool_name: GET_CONFIG_TOOL_NAME,
780
+ entry_count: payload.entries.length,
781
+ });
782
+ }
783
+ };
784
+ const refreshConfigFromServer = async () => {
785
+ try {
786
+ const result = await bridge.callTool('get_config', {});
787
+ const payload = controller.extractPayload(result);
788
+ if (payload) {
789
+ applyPayload(payload);
790
+ }
791
+ }
792
+ catch {
793
+ // Best-effort refresh only
794
+ }
795
+ };
796
+ app.ontoolresult = (result) => {
797
+ const payload = controller.extractPayload(result);
798
+ if (payload) {
799
+ applyPayload(payload);
800
+ }
801
+ };
802
+ app.ontoolcancelled = (params) => {
803
+ showTooltip({
804
+ message: params.reason ?? 'Tool was cancelled.',
805
+ tone: 'error',
806
+ });
807
+ };
808
+ void connectWithSharedHostContext({
809
+ app,
810
+ chrome,
811
+ onContextApplied: () => {
812
+ // Config editor should default to expanded in all hosts unless the
813
+ // host forces framed mode.
814
+ if (!chrome.hideSummaryRow) {
815
+ chrome.expanded = true;
816
+ }
817
+ scheduleRender();
818
+ },
819
+ onConnected: async () => {
820
+ const cachedPayload = widgetState.read();
821
+ if (cachedPayload) {
822
+ controller.setPayload(cachedPayload);
823
+ }
824
+ scheduleRender();
825
+ await refreshConfigFromServer();
826
+ },
827
+ }).catch(() => {
828
+ scheduleRender();
829
+ window.setTimeout(() => {
830
+ showTooltip({
831
+ message: 'Failed to connect to host.',
832
+ tone: 'error',
833
+ });
834
+ }, 0);
835
+ });
836
+ window.addEventListener('beforeunload', () => {
837
+ shellController?.dispose();
838
+ clearTooltipTimer();
839
+ }, { once: true });
840
+ }