@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
@@ -5,6 +5,22 @@ import { mkdir } from 'fs/promises';
5
5
  import os from 'os';
6
6
  import { VERSION } from './version.js';
7
7
  import { CONFIG_FILE } from './config.js';
8
+ export function normalizeTelemetryEnabledValue(value) {
9
+ if (typeof value !== 'string') {
10
+ return value;
11
+ }
12
+ const normalized = value.trim().toLowerCase();
13
+ if (normalized === 'true') {
14
+ return true;
15
+ }
16
+ if (normalized === 'false') {
17
+ return false;
18
+ }
19
+ return value;
20
+ }
21
+ export function isTelemetryDisabledValue(value) {
22
+ return normalizeTelemetryEnabledValue(value) === false;
23
+ }
8
24
  /**
9
25
  * Singleton config manager for the server
10
26
  */
@@ -154,12 +170,16 @@ class ConfigManager {
154
170
  */
155
171
  async setValue(key, value) {
156
172
  await this.init();
173
+ if (key === 'telemetryEnabled') {
174
+ value = normalizeTelemetryEnabledValue(value);
175
+ }
157
176
  // Special handling for telemetry opt-out
158
- if (key === 'telemetryEnabled' && value === false) {
177
+ if (key === 'telemetryEnabled' && isTelemetryDisabledValue(value)) {
159
178
  // Get the current value before changing it
160
179
  const currentValue = this.config[key];
180
+ const telemetryAlreadyDisabled = isTelemetryDisabledValue(currentValue);
161
181
  // Only capture the opt-out event if telemetry was previously enabled
162
- if (currentValue !== false) {
182
+ if (!telemetryAlreadyDisabled) {
163
183
  // Import the capture function dynamically to avoid circular dependencies
164
184
  const { capture } = await import('./utils/capture.js');
165
185
  // Send a final telemetry event noting that the user has opted out
@@ -1,4 +1,9 @@
1
1
  import { ServerResult } from '../types.js';
2
+ /**
3
+ * Resolve a file path to an absolute path for use in structured content.
4
+ * This ensures "Open in folder" always has a valid absolute path.
5
+ */
6
+ export declare function resolveAbsolutePath(filePath: string): string;
2
7
  /**
3
8
  * Handle read_file command
4
9
  */
@@ -5,7 +5,6 @@ import { configManager } from '../config-manager.js';
5
5
  import { ReadFileArgsSchema, ReadMultipleFilesArgsSchema, WriteFileArgsSchema, CreateDirectoryArgsSchema, ListDirectoryArgsSchema, MoveFileArgsSchema, GetFileInfoArgsSchema, WritePdfArgsSchema } from '../tools/schemas.js';
6
6
  import path from 'path';
7
7
  import os from 'os';
8
- import { buildUiToolMeta, FILE_PREVIEW_RESOURCE_URI } from '../ui/contracts.js';
9
8
  import { resolvePreviewFileType } from '../ui/file-preview/shared/preview-file-types.js';
10
9
  /**
11
10
  * Expand home directory (~) in a file path
@@ -20,7 +19,7 @@ function expandHome(filePath) {
20
19
  * Resolve a file path to an absolute path for use in structured content.
21
20
  * This ensures "Open in folder" always has a valid absolute path.
22
21
  */
23
- function resolveAbsolutePath(filePath) {
22
+ export function resolveAbsolutePath(filePath) {
24
23
  const expanded = expandHome(filePath);
25
24
  return path.isAbsolute(expanded)
26
25
  ? path.resolve(expanded)
@@ -100,9 +99,7 @@ export async function handleReadFile(args) {
100
99
  fileName: path.basename(resolvedFilePath),
101
100
  filePath: resolvedFilePath,
102
101
  fileType: 'unsupported',
103
- content: ''
104
102
  },
105
- _meta: buildUiToolMeta(FILE_PREVIEW_RESOURCE_URI, true)
106
103
  };
107
104
  }
108
105
  // Handle image files
@@ -124,28 +121,26 @@ export async function handleReadFile(args) {
124
121
  fileName: path.basename(resolvedFilePath),
125
122
  filePath: resolvedFilePath,
126
123
  fileType: 'image',
127
- content: imageSummary,
128
124
  imageData,
129
125
  mimeType: fileResult.mimeType
130
- },
131
- _meta: buildUiToolMeta(FILE_PREVIEW_RESOURCE_URI, true)
126
+ }
132
127
  };
133
128
  }
134
129
  else {
135
- // For all other files, return as text
130
+ // For all other files, return as text.
131
+ // structuredContent carries only file metadata (no content duplication);
132
+ // the widget reads text from the MCP content array.
136
133
  const textContent = typeof fileResult.content === 'string'
137
134
  ? fileResult.content
138
135
  : fileResult.content.toString('utf8');
139
- const previewFileType = resolvePreviewFileType(resolvedFilePath);
136
+ const fileType = fileResult.metadata?.isDirectory ? 'directory' : resolvePreviewFileType(resolvedFilePath);
140
137
  return {
141
138
  content: [{ type: "text", text: textContent }],
142
139
  structuredContent: {
143
140
  fileName: path.basename(resolvedFilePath),
144
141
  filePath: resolvedFilePath,
145
- fileType: previewFileType,
146
- content: textContent
142
+ fileType,
147
143
  },
148
- _meta: buildUiToolMeta(FILE_PREVIEW_RESOURCE_URI, true)
149
144
  };
150
145
  }
151
146
  };
@@ -241,11 +236,17 @@ export async function handleWriteFile(args) {
241
236
  await writeFile(parsed.path, parsed.content, parsed.mode);
242
237
  // Provide more informative message based on mode
243
238
  const modeMessage = parsed.mode === 'append' ? 'appended to' : 'wrote to';
239
+ const resolvedWritePath = resolveAbsolutePath(parsed.path);
244
240
  return {
245
241
  content: [{
246
242
  type: "text",
247
243
  text: `Successfully ${modeMessage} ${parsed.path} (${lineCount} lines) ${errorMessage}`
248
244
  }],
245
+ structuredContent: {
246
+ fileName: path.basename(resolvedWritePath),
247
+ filePath: resolvedWritePath,
248
+ fileType: resolvePreviewFileType(resolvedWritePath),
249
+ },
249
250
  };
250
251
  }
251
252
  catch (error) {
@@ -279,8 +280,14 @@ export async function handleListDirectory(args) {
279
280
  const entries = await listDirectory(parsed.path, parsed.depth);
280
281
  const duration = Date.now() - startTime;
281
282
  const resultText = entries.join('\n');
283
+ const resolvedPath = resolveAbsolutePath(parsed.path);
282
284
  return {
283
285
  content: [{ type: "text", text: resultText }],
286
+ structuredContent: {
287
+ fileName: path.basename(resolvedPath),
288
+ filePath: resolvedPath,
289
+ fileType: 'directory',
290
+ },
284
291
  };
285
292
  }
286
293
  catch (error) {
@@ -76,7 +76,7 @@ export class DesktopCommanderIntegration {
76
76
  // We can't run it directly as it's an stdio MCP server that waits for input
77
77
  const whichCommand = process.platform === 'win32' ? 'where' : 'which';
78
78
  console.debug('[DEBUG] Using platform command:', whichCommand, 'on platform:', process.platform);
79
- const check = spawn(whichCommand, [commandName]);
79
+ const check = spawn(whichCommand, [commandName], { windowsHide: true }); // Prevent visible console windows on Windows
80
80
  check.on('error', (err) => {
81
81
  console.debug('[DEBUG] Spawn error for', whichCommand, ':', err.message);
82
82
  reject(err);
@@ -126,7 +126,7 @@ export class RemoteChannel {
126
126
  console.debug(`⏳ Subscribing to tool call channel...`);
127
127
  // Create and subscribe to the channel
128
128
  console.debug('[DEBUG] Calling createChannel()');
129
- // ! Ignore silently in Inialization to reconnect after
129
+ // ! Ignore silently in Initialization to reconnect after
130
130
  await this.createChannel().catch((error) => {
131
131
  console.debug('[DEBUG] Failed to create channel, will retry after socket reconnect', error);
132
132
  });
@@ -33,7 +33,7 @@ import PizZip from 'pizzip';
33
33
  throw new Error(`Failed to locate ripgrep binary: ${err instanceof Error ? err.message : String(err)}`);
34
34
  }
35
35
  // Start ripgrep process
36
- const rgProcess = spawn(rgPath, args);
36
+ const rgProcess = spawn(rgPath, args, { windowsHide: true }); // Prevent visible console windows on Windows
37
37
  if (!rgProcess.pid) {
38
38
  throw new Error('Failed to start ripgrep process');
39
39
  }
@@ -94,7 +94,8 @@ import PizZip from 'pizzip';
94
94
  const shouldSearchExcel = options.searchType === 'content' &&
95
95
  this.shouldIncludeExcelSearch(options.filePattern, validPath);
96
96
  if (shouldSearchExcel) {
97
- this.searchExcelFiles(validPath, options.pattern, options.ignoreCase !== false, options.maxResults, options.filePattern // Pass filePattern to filter Excel files too
97
+ this.searchExcelFiles(validPath, options.pattern, options.ignoreCase !== false, options.maxResults, options.filePattern, // Pass filePattern to filter Excel files too
98
+ options.literalSearch // Respect literalSearch flag for Office files
98
99
  ).then(excelResults => {
99
100
  // Add Excel results to session (merged after initial response)
100
101
  for (const result of excelResults) {
@@ -110,7 +111,8 @@ import PizZip from 'pizzip';
110
111
  const shouldSearchDocx = options.searchType === 'content' &&
111
112
  this.shouldIncludeDocxSearch(options.filePattern, validPath);
112
113
  if (shouldSearchDocx) {
113
- this.searchDocxFiles(validPath, options.pattern, options.ignoreCase !== false, options.maxResults, options.filePattern).then(docxResults => {
114
+ this.searchDocxFiles(validPath, options.pattern, options.ignoreCase !== false, options.maxResults, options.filePattern, options.literalSearch // Respect literalSearch flag for Office files
115
+ ).then(docxResults => {
114
116
  for (const result of docxResults) {
115
117
  session.results.push(result);
116
118
  session.totalMatches++;
@@ -223,19 +225,11 @@ import PizZip from 'pizzip';
223
225
  * and inject into SearchManager, similar to how file handlers are structured in src/utils/files/
224
226
  * This would allow adding other file type searches (PDF, etc.) without bloating search-manager.ts
225
227
  */
226
- async searchExcelFiles(rootPath, pattern, ignoreCase, maxResults, filePattern) {
228
+ async searchExcelFiles(rootPath, pattern, ignoreCase, maxResults, filePattern, _literalSearch) {
227
229
  const results = [];
228
- // Build regex for matching content
229
- const flags = ignoreCase ? 'i' : '';
230
- let regex;
231
- try {
232
- regex = new RegExp(pattern, flags);
233
- }
234
- catch {
235
- // If pattern is not valid regex, escape it for literal matching
236
- const escaped = pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
237
- regex = new RegExp(escaped, flags);
238
- }
230
+ // Office file search always uses literal matching to prevent ReDoS.
231
+ // Regex patterns are treated as literal strings — this is intentional.
232
+ const searchTerm = ignoreCase ? pattern.toLowerCase() : pattern;
239
233
  // Find Excel files recursively
240
234
  let excelFiles = await this.findExcelFiles(rootPath);
241
235
  // Filter by filePattern if provided
@@ -246,7 +240,13 @@ import PizZip from 'pizzip';
246
240
  return patterns.some(pat => {
247
241
  // Support glob-like patterns
248
242
  if (pat.includes('*')) {
249
- const regexPat = pat.replace(/\./g, '\\.').replace(/\*/g, '.*');
243
+ // Escape all regex metacharacters first (preserving * for glob expansion),
244
+ // then convert the remaining * wildcards to .* for glob matching.
245
+ // Without this, patterns like report(2024).xlsx or [draft].xlsx would be
246
+ // misinterpreted as regex groups/character-classes.
247
+ const regexPat = pat
248
+ .replace(/[.+^${}()|[\]\\]/g, '\\$&') // escape metacharacters except *
249
+ .replace(/\*/g, '.*'); // glob * → regex .*
250
250
  return new RegExp(`^${regexPat}$`, 'i').test(fileName);
251
251
  }
252
252
  // Exact match (case-insensitive)
@@ -300,12 +300,10 @@ import PizZip from 'pizzip';
300
300
  });
301
301
  // Join all cell values with space for cross-column matching
302
302
  const rowText = rowValues.join(' ');
303
- if (regex.test(rowText)) {
304
- // Extract the matching portion for display
305
- const match = rowText.match(regex);
306
- const matchContext = match
307
- ? this.getMatchContext(rowText, match.index || 0, match[0].length)
308
- : rowText.substring(0, 150);
303
+ const textToSearch = ignoreCase ? rowText.toLowerCase() : rowText;
304
+ const matchIndex = textToSearch.indexOf(searchTerm);
305
+ if (matchIndex !== -1) {
306
+ const matchContext = this.getMatchContext(rowText, matchIndex, searchTerm.length);
309
307
  results.push({
310
308
  file: `${filePath}:${sheetName}!Row${rowNumber}`,
311
309
  line: rowNumber,
@@ -386,17 +384,11 @@ import PizZip from 'pizzip';
386
384
  * Search DOCX files for content matches
387
385
  * Extracts <w:t> text from document.xml and searches it
388
386
  */
389
- async searchDocxFiles(rootPath, pattern, ignoreCase, maxResults, filePattern) {
387
+ async searchDocxFiles(rootPath, pattern, ignoreCase, maxResults, filePattern, _literalSearch) {
390
388
  const results = [];
391
- const flags = ignoreCase ? 'i' : '';
392
- let regex;
393
- try {
394
- regex = new RegExp(pattern, flags);
395
- }
396
- catch {
397
- const escaped = pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
398
- regex = new RegExp(escaped, flags);
399
- }
389
+ // Office file search always uses literal matching to prevent ReDoS.
390
+ // Regex patterns are treated as literal strings — this is intentional.
391
+ const searchTerm = ignoreCase ? pattern.toLowerCase() : pattern;
400
392
  let docxFiles = await this.findDocxFiles(rootPath);
401
393
  if (filePattern) {
402
394
  const patterns = filePattern.split('|').map(p => p.trim()).filter(Boolean);
@@ -404,7 +396,9 @@ import PizZip from 'pizzip';
404
396
  const fileName = path.basename(filePath);
405
397
  return patterns.some(pat => {
406
398
  if (pat.includes('*')) {
407
- const regexPat = pat.replace(/\./g, '\\.').replace(/\*/g, '.*');
399
+ const regexPat = pat
400
+ .replace(/[.+^${}()|[\]\\]/g, '\\$&') // escape metacharacters except *
401
+ .replace(/\*/g, '.*'); // glob * → regex .*
408
402
  return new RegExp(`^${regexPat}$`, 'i').test(fileName);
409
403
  }
410
404
  return fileName.toLowerCase() === pat.toLowerCase();
@@ -438,11 +432,10 @@ import PizZip from 'pizzip';
438
432
  if (!text || !text.trim())
439
433
  continue;
440
434
  lineNum++;
441
- if (regex.test(text)) {
442
- const match = text.match(regex);
443
- const matchContext = match
444
- ? this.getMatchContext(text, match.index || 0, match[0].length)
445
- : text.substring(0, 150);
435
+ const textToSearch = ignoreCase ? text.toLowerCase() : text;
436
+ const matchIndex = textToSearch.indexOf(searchTerm);
437
+ if (matchIndex !== -1) {
438
+ const matchContext = this.getMatchContext(text, matchIndex, searchTerm.length);
446
439
  const partName = xmlPath === 'word/document.xml' ? '' : `:${xmlPath.replace('word/', '')}`;
447
440
  results.push({
448
441
  file: `${filePath}${partName}`,
package/dist/server.js CHANGED
@@ -21,7 +21,7 @@ import { handleWelcomePageOnboarding } from './utils/welcome-onboarding.js';
21
21
  import { VERSION } from './version.js';
22
22
  import { capture, capture_call_tool } from "./utils/capture.js";
23
23
  import { logToStderr, logger } from './utils/logger.js';
24
- import { buildUiToolMeta, FILE_PREVIEW_RESOURCE_URI } from './ui/contracts.js';
24
+ import { buildUiToolMeta, CONFIG_EDITOR_RESOURCE_URI, FILE_PREVIEW_RESOURCE_URI } from './ui/contracts.js';
25
25
  import { listUiResources, readUiResource } from './ui/resources.js';
26
26
  // Store startup messages to send after initialization
27
27
  const deferredMessages = [];
@@ -137,9 +137,11 @@ deferLog('info', 'Setting up request handlers...');
137
137
  * Check if a tool should be included based on current client
138
138
  */
139
139
  function shouldIncludeTool(toolName) {
140
- // Exclude give_feedback_to_desktop_commander for desktop-commander client
141
- if (toolName === 'give_feedback_to_desktop_commander' && currentClient?.name === 'desktop-commander') {
142
- return false;
140
+ // Exclude these tools for desktop-commander client (DC-specific meta-tools not useful when DC itself is the client)
141
+ if (currentClient?.name === 'desktop-commander-app') {
142
+ if (toolName === 'give_feedback_to_desktop_commander' || toolName === 'get_prompts') {
143
+ return false;
144
+ }
143
145
  }
144
146
  // Add more conditional tool logic here as needed
145
147
  // Example: if (toolName === 'some_tool' && currentClient?.name === 'some_client') return false;
@@ -167,6 +169,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
167
169
  - systemInfo (operating system and environment details)
168
170
  ${CMD_PREFIX_DESCRIPTION}`,
169
171
  inputSchema: zodToJsonSchema(GetConfigArgsSchema),
172
+ _meta: buildUiToolMeta(CONFIG_EDITOR_RESOURCE_URI, true),
170
173
  annotations: {
171
174
  title: "Get Configuration",
172
175
  readOnlyHint: true,
@@ -327,6 +330,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
327
330
  ${PATH_GUIDANCE}
328
331
  ${CMD_PREFIX_DESCRIPTION}`,
329
332
  inputSchema: zodToJsonSchema(WriteFileArgsSchema),
333
+ _meta: buildUiToolMeta(FILE_PREVIEW_RESOURCE_URI, true),
330
334
  annotations: {
331
335
  title: "Write File",
332
336
  readOnlyHint: false,
@@ -446,6 +450,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
446
450
  ${PATH_GUIDANCE}
447
451
  ${CMD_PREFIX_DESCRIPTION}`,
448
452
  inputSchema: zodToJsonSchema(ListDirectoryArgsSchema),
453
+ _meta: buildUiToolMeta(FILE_PREVIEW_RESOURCE_URI, true),
449
454
  annotations: {
450
455
  title: "List Directory Contents",
451
456
  readOnlyHint: true,
@@ -704,6 +709,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
704
709
  ${PATH_GUIDANCE}
705
710
  ${CMD_PREFIX_DESCRIPTION}`,
706
711
  inputSchema: zodToJsonSchema(EditBlockArgsSchema),
712
+ _meta: buildUiToolMeta(FILE_PREVIEW_RESOURCE_URI, true),
707
713
  annotations: {
708
714
  title: "Edit Block",
709
715
  readOnlyHint: false,
@@ -1104,6 +1110,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1104
1110
  }
1105
1111
  if (name === 'set_config_value' && args && typeof args === 'object' && 'key' in args) {
1106
1112
  telemetryData.set_config_value_key_name = args.key;
1113
+ telemetryData.call_origin = args.origin === 'ui' ? 'ui' : 'llm';
1107
1114
  }
1108
1115
  if (name === 'get_prompts' && args && typeof args === 'object') {
1109
1116
  const promptArgs = args;
@@ -119,7 +119,8 @@ export class TerminalManager {
119
119
  env: {
120
120
  ...process.env,
121
121
  TERM: 'xterm-256color' // Better terminal compatibility
122
- }
122
+ },
123
+ windowsHide: true // Prevent visible console windows on Windows
123
124
  };
124
125
  // Add shell option if needed (for unknown shells)
125
126
  if (spawnConfig.useShellOption) {
@@ -138,7 +139,8 @@ export class TerminalManager {
138
139
  env: {
139
140
  ...process.env,
140
141
  TERM: 'xterm-256color'
141
- }
142
+ },
143
+ windowsHide: true // Prevent visible console windows on Windows
142
144
  };
143
145
  }
144
146
  // Spawn the process with appropriate arguments
@@ -6,6 +6,77 @@ export declare function getConfig(): Promise<{
6
6
  type: string;
7
7
  text: string;
8
8
  }[];
9
+ structuredContent: {
10
+ config: {
11
+ currentClient: {
12
+ name: string;
13
+ version: string;
14
+ };
15
+ featureFlags: Record<string, any>;
16
+ systemInfo: {
17
+ memory: {
18
+ rss: string;
19
+ heapTotal: string;
20
+ heapUsed: string;
21
+ external: string;
22
+ arrayBuffers: string;
23
+ };
24
+ platform: string;
25
+ platformName: string;
26
+ defaultShell: string;
27
+ pathSeparator: string;
28
+ isWindows: boolean;
29
+ isMacOS: boolean;
30
+ isLinux: boolean;
31
+ docker: import("../utils/system-info.js").ContainerInfo;
32
+ isDXT: boolean;
33
+ nodeInfo?: {
34
+ version: string;
35
+ path: string;
36
+ npmVersion?: string;
37
+ };
38
+ pythonInfo?: {
39
+ available: boolean;
40
+ command: string;
41
+ version?: string;
42
+ };
43
+ processInfo: {
44
+ pid: number;
45
+ arch: string;
46
+ platform: string;
47
+ versions: NodeJS.ProcessVersions;
48
+ };
49
+ examplePaths: {
50
+ home: string;
51
+ temp: string;
52
+ absolute: string;
53
+ accessible?: string[];
54
+ };
55
+ };
56
+ blockedCommands?: string[];
57
+ defaultShell?: string;
58
+ allowedDirectories?: string[];
59
+ telemetryEnabled?: boolean;
60
+ fileWriteLineLimit?: number;
61
+ fileReadLineLimit?: number;
62
+ clientId?: string;
63
+ };
64
+ uiHints: {
65
+ availableShells: string[];
66
+ };
67
+ entries: {
68
+ key: "defaultShell" | "blockedCommands" | "allowedDirectories" | "telemetryEnabled" | "fileReadLineLimit" | "fileWriteLineLimit";
69
+ value: unknown;
70
+ valueType: "string" | "number" | "boolean" | "array";
71
+ editable: boolean;
72
+ }[];
73
+ };
74
+ } | {
75
+ content: {
76
+ type: string;
77
+ text: string;
78
+ }[];
79
+ structuredContent?: undefined;
9
80
  }>;
10
81
  /**
11
82
  * Set a specific config value
@@ -3,6 +3,74 @@ import { SetConfigValueArgsSchema } from './schemas.js';
3
3
  import { getSystemInfo } from '../utils/system-info.js';
4
4
  import { currentClient } from '../server.js';
5
5
  import { featureFlagManager } from '../utils/feature-flags.js';
6
+ import { access, readFile } from 'node:fs/promises';
7
+ import { constants as fsConstants } from 'node:fs';
8
+ import { CONFIG_FIELD_DEFINITIONS, CONFIG_FIELD_KEYS, isConfigFieldKey, } from '../config-field-definitions.js';
9
+ const ALLOWED_CONFIG_KEYS = new Set(CONFIG_FIELD_KEYS);
10
+ async function pathExists(pathValue) {
11
+ try {
12
+ await access(pathValue, fsConstants.X_OK);
13
+ return true;
14
+ }
15
+ catch {
16
+ return false;
17
+ }
18
+ }
19
+ async function detectAvailableShells(systemInfo) {
20
+ const detected = new Set();
21
+ const add = (shell) => {
22
+ if (shell.trim().length > 0) {
23
+ detected.add(shell.trim());
24
+ }
25
+ };
26
+ add(systemInfo.defaultShell);
27
+ if (systemInfo.isWindows) {
28
+ add(process.env.ComSpec ?? '');
29
+ const systemRoot = process.env.SystemRoot ?? 'C:\\Windows';
30
+ const candidates = [
31
+ `${systemRoot}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`,
32
+ `${systemRoot}\\System32\\cmd.exe`,
33
+ `${systemRoot}\\System32\\bash.exe`,
34
+ 'powershell.exe',
35
+ 'pwsh.exe',
36
+ 'cmd.exe',
37
+ 'bash.exe',
38
+ ];
39
+ for (const shell of candidates) {
40
+ if (shell.includes('\\')) {
41
+ if (await pathExists(shell)) {
42
+ add(shell);
43
+ }
44
+ }
45
+ else {
46
+ add(shell);
47
+ }
48
+ }
49
+ return [...detected];
50
+ }
51
+ add(process.env.SHELL ?? '');
52
+ const shellFiles = ['/etc/shells'];
53
+ for (const shellFile of shellFiles) {
54
+ try {
55
+ const content = await readFile(shellFile, 'utf8');
56
+ content
57
+ .split(/\r?\n/)
58
+ .map((line) => line.trim())
59
+ .filter((line) => line.length > 0 && !line.startsWith('#'))
60
+ .forEach(add);
61
+ }
62
+ catch {
63
+ // Best-effort discovery only.
64
+ }
65
+ }
66
+ const fallbackCandidates = ['/bin/zsh', '/bin/bash', '/bin/sh', '/usr/bin/fish'];
67
+ for (const shell of fallbackCandidates) {
68
+ if (await pathExists(shell)) {
69
+ add(shell);
70
+ }
71
+ }
72
+ return [...detected];
73
+ }
6
74
  /**
7
75
  * Get the entire config including system information
8
76
  */
@@ -30,12 +98,29 @@ export async function getConfig() {
30
98
  memory
31
99
  }
32
100
  };
101
+ const availableShells = await detectAvailableShells(systemInfo);
33
102
  console.error(`getConfig result: ${JSON.stringify(configWithSystemInfo, null, 2)}`);
34
103
  return {
35
104
  content: [{
36
105
  type: "text",
37
106
  text: `Current configuration:\n${JSON.stringify(configWithSystemInfo, null, 2)}`
38
107
  }],
108
+ structuredContent: {
109
+ config: configWithSystemInfo,
110
+ uiHints: {
111
+ availableShells,
112
+ },
113
+ entries: CONFIG_FIELD_KEYS.map((key) => {
114
+ const definition = CONFIG_FIELD_DEFINITIONS[key];
115
+ const value = configWithSystemInfo[key];
116
+ return {
117
+ key,
118
+ value,
119
+ valueType: definition.valueType,
120
+ editable: true,
121
+ };
122
+ }),
123
+ },
39
124
  };
40
125
  }
41
126
  catch (error) {
@@ -67,7 +152,17 @@ export async function setConfigValue(args) {
67
152
  isError: true
68
153
  };
69
154
  }
155
+ if (!isConfigFieldKey(parsed.data.key)) {
156
+ return {
157
+ content: [{
158
+ type: "text",
159
+ text: `Key "${parsed.data.key}" is not configurable via this tool. Allowed keys: ${[...ALLOWED_CONFIG_KEYS].join(', ')}`
160
+ }],
161
+ isError: true
162
+ };
163
+ }
70
164
  try {
165
+ const fieldDefinition = CONFIG_FIELD_DEFINITIONS[parsed.data.key];
71
166
  // Parse string values that should be arrays or objects
72
167
  let valueToStore = parsed.data.value;
73
168
  // If the value is a string that looks like an array or object, try to parse it
@@ -82,8 +177,7 @@ export async function setConfigValue(args) {
82
177
  }
83
178
  }
84
179
  // Special handling for known array configuration keys
85
- if ((parsed.data.key === 'allowedDirectories' || parsed.data.key === 'blockedCommands') &&
86
- !Array.isArray(valueToStore)) {
180
+ if (fieldDefinition.valueType === 'array' && !Array.isArray(valueToStore)) {
87
181
  if (typeof valueToStore === 'string') {
88
182
  const originalString = valueToStore;
89
183
  try {
@@ -108,6 +202,27 @@ export async function setConfigValue(args) {
108
202
  valueToStore = [String(valueToStore)];
109
203
  }
110
204
  }
205
+ // Harden boolean fields against stringly-typed inputs like "false".
206
+ if (fieldDefinition.valueType === 'boolean') {
207
+ if (typeof valueToStore === 'string') {
208
+ const normalized = valueToStore.trim().toLowerCase();
209
+ if (normalized === 'true') {
210
+ valueToStore = true;
211
+ }
212
+ else if (normalized === 'false') {
213
+ valueToStore = false;
214
+ }
215
+ }
216
+ if (typeof valueToStore !== 'boolean') {
217
+ return {
218
+ content: [{
219
+ type: "text",
220
+ text: `Value for ${parsed.data.key} must be boolean true/false.`
221
+ }],
222
+ isError: true
223
+ };
224
+ }
225
+ }
111
226
  await configManager.setValue(parsed.data.key, valueToStore);
112
227
  // Get the updated configuration to show the user
113
228
  const updatedConfig = await configManager.getConfig();