@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,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
+ }