@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.
- package/README.md +53 -2
- package/dist/handlers/filesystem-handlers.d.ts +5 -0
- package/dist/handlers/filesystem-handlers.js +14 -2
- package/dist/remote-device/desktop-commander-integration.js +1 -1
- package/dist/search-manager.js +31 -38
- package/dist/server.js +8 -3
- package/dist/terminal-manager.js +4 -2
- package/dist/tools/edit.js +34 -1
- package/dist/tools/filesystem.js +91 -3
- package/dist/tools/improved-process-tools.js +2 -1
- package/dist/ui/config-editor/app.js +840 -0
- package/dist/ui/config-editor/array-modal.d.ts +19 -0
- package/dist/ui/config-editor/array-modal.js +185 -0
- package/dist/ui/config-editor/config-editor-runtime.js +65 -14096
- package/dist/ui/config-editor/main.js +2 -0
- package/dist/ui/config-editor/src/App.d.ts +43 -0
- package/dist/ui/config-editor/src/components/layout.d.ts +4 -0
- package/dist/ui/config-editor/src/components/layout.js +83 -0
- package/dist/ui/config-editor/src/components/toolbar.d.ts +1 -0
- package/dist/ui/config-editor/src/components/toolbar.js +21 -0
- package/dist/ui/config-editor/src/config-values.d.ts +6 -0
- package/dist/ui/config-editor/src/config-values.js +61 -0
- package/dist/ui/config-editor/src/contracts.d.ts +14 -0
- package/dist/ui/config-editor/src/contracts.js +3 -0
- package/dist/ui/config-editor/src/directory-browser.d.ts +6 -0
- package/dist/ui/config-editor/src/directory-browser.js +71 -0
- package/dist/ui/config-editor/src/layout.d.ts +5 -0
- package/dist/ui/config-editor/src/layout.js +90 -0
- package/dist/ui/config-editor/src/parsing.d.ts +5 -0
- package/dist/ui/config-editor/src/parsing.js +50 -0
- package/dist/ui/config-editor/src/toolbar.d.ts +1 -0
- package/dist/ui/config-editor/src/toolbar.js +18 -0
- package/dist/ui/config-editor/src/types.d.ts +17 -0
- package/dist/ui/config-editor/src/types.js +3 -0
- package/dist/ui/config-editor/src/utils/config-values.d.ts +9 -0
- package/dist/ui/config-editor/src/utils/config-values.js +61 -0
- package/dist/ui/config-editor/src/utils/directory-browser.d.ts +31 -0
- package/dist/ui/config-editor/src/utils/directory-browser.js +201 -0
- package/dist/ui/config-editor/src/utils/parsing.d.ts +8 -0
- package/dist/ui/config-editor/src/utils/parsing.js +50 -0
- package/dist/ui/config-editor/styles.css +2 -1
- package/dist/ui/file-preview/{src/app.d.ts → app.d.ts} +1 -1
- package/dist/ui/file-preview/app.js +2020 -0
- package/dist/ui/file-preview/components/code-viewer.d.ts +6 -0
- package/dist/ui/file-preview/components/code-viewer.js +73 -0
- package/dist/ui/file-preview/components/highlighting.d.ts +2 -0
- package/dist/ui/file-preview/components/highlighting.js +54 -0
- package/dist/ui/file-preview/components/html-renderer.d.ts +5 -0
- package/dist/ui/file-preview/components/html-renderer.js +47 -0
- package/dist/ui/file-preview/components/markdown-renderer.d.ts +1 -0
- package/dist/ui/file-preview/components/markdown-renderer.js +67 -0
- package/dist/ui/file-preview/components/toolbar.d.ts +6 -0
- package/dist/ui/file-preview/components/toolbar.js +75 -0
- package/dist/ui/file-preview/image-preview.d.ts +3 -0
- package/dist/ui/file-preview/image-preview.js +21 -0
- package/dist/ui/file-preview/main.js +5 -0
- package/dist/ui/file-preview/markdown/editor.d.ts +36 -0
- package/dist/ui/file-preview/markdown/editor.js +643 -0
- package/dist/ui/file-preview/markdown/linking.d.ts +9 -0
- package/dist/ui/file-preview/markdown/linking.js +210 -0
- package/dist/ui/file-preview/markdown/outline.d.ts +7 -0
- package/dist/ui/file-preview/markdown/outline.js +40 -0
- package/dist/ui/file-preview/markdown/preview.d.ts +8 -0
- package/dist/ui/file-preview/markdown/preview.js +33 -0
- package/dist/ui/file-preview/markdown/slugify.d.ts +3 -0
- package/dist/ui/file-preview/markdown/slugify.js +31 -0
- package/dist/ui/file-preview/markdown/toc.d.ts +11 -0
- package/dist/ui/file-preview/markdown/toc.js +75 -0
- package/dist/ui/file-preview/markdown/utils.d.ts +1 -0
- package/dist/ui/file-preview/markdown/utils.js +15 -0
- package/dist/ui/file-preview/markdown/workspace-controller.d.ts +25 -0
- package/dist/ui/file-preview/markdown/workspace-controller.js +40 -0
- package/dist/ui/file-preview/preview-runtime.js +384 -26533
- package/dist/ui/file-preview/shared/preview-file-types.d.ts +1 -1
- package/dist/ui/file-preview/src/App.d.ts +4 -0
- package/dist/ui/file-preview/src/App.js +564 -0
- package/dist/ui/file-preview/src/components/CodeViewer.d.ts +6 -0
- package/dist/ui/file-preview/src/components/CodeViewer.js +60 -0
- package/dist/ui/file-preview/src/components/HtmlRenderer.d.ts +8 -0
- package/dist/ui/file-preview/src/components/HtmlRenderer.js +45 -0
- package/dist/ui/file-preview/src/components/MarkdownRenderer.d.ts +1 -0
- package/dist/ui/file-preview/src/components/MarkdownRenderer.js +15 -0
- package/dist/ui/file-preview/src/components/editor-toolbar.d.ts +15 -0
- package/dist/ui/file-preview/src/components/editor-toolbar.js +384 -0
- package/dist/ui/file-preview/src/components/markdown-editor.d.ts +29 -0
- package/dist/ui/file-preview/src/components/markdown-editor.js +535 -0
- package/dist/ui/file-preview/src/components/markdown-renderer.js +47 -9
- package/dist/ui/file-preview/src/directory-controller.d.ts +8 -0
- package/dist/ui/file-preview/src/directory-controller.js +233 -0
- package/dist/ui/file-preview/src/document-layout.d.ts +20 -0
- package/dist/ui/file-preview/src/document-layout.js +109 -0
- package/dist/ui/file-preview/src/document-outline.d.ts +17 -0
- package/dist/ui/file-preview/src/document-outline.js +97 -0
- package/dist/ui/file-preview/src/document-workspace.d.ts +19 -0
- package/dist/ui/file-preview/src/document-workspace.js +33 -0
- package/dist/ui/file-preview/src/file-type-handlers.d.ts +10 -0
- package/dist/ui/file-preview/src/file-type-handlers.js +98 -0
- package/dist/ui/file-preview/src/host/external-actions.d.ts +19 -0
- package/dist/ui/file-preview/src/host/external-actions.js +94 -0
- package/dist/ui/file-preview/src/host/selection-context.d.ts +9 -0
- package/dist/ui/file-preview/src/host/selection-context.js +106 -0
- package/dist/ui/file-preview/src/markdown/block-merge.d.ts +25 -0
- package/dist/ui/file-preview/src/markdown/block-merge.js +86 -0
- package/dist/ui/file-preview/src/markdown/conflict-dialog.d.ts +40 -0
- package/dist/ui/file-preview/src/markdown/conflict-dialog.js +163 -0
- package/dist/ui/file-preview/src/markdown/controller.d.ts +38 -0
- package/dist/ui/file-preview/src/markdown/controller.js +921 -0
- package/dist/ui/file-preview/src/markdown/editor.d.ts +35 -0
- package/dist/ui/file-preview/src/markdown/editor.js +691 -0
- package/dist/ui/file-preview/src/markdown/link-modal.d.ts +13 -0
- package/dist/ui/file-preview/src/markdown/link-modal.js +213 -0
- package/dist/ui/file-preview/src/markdown/linking.d.ts +16 -0
- package/dist/ui/file-preview/src/markdown/linking.js +228 -0
- package/dist/ui/file-preview/src/markdown/outline.d.ts +2 -0
- package/dist/ui/file-preview/src/markdown/outline.js +16 -0
- package/dist/ui/file-preview/src/markdown/parser.d.ts +30 -0
- package/dist/ui/file-preview/src/markdown/parser.js +38 -0
- package/dist/ui/file-preview/src/markdown/preview.d.ts +1 -0
- package/dist/ui/file-preview/src/markdown/preview.js +20 -0
- package/dist/ui/file-preview/src/markdown/raw-editor.d.ts +8 -0
- package/dist/ui/file-preview/src/markdown/raw-editor.js +61 -0
- package/dist/ui/file-preview/src/markdown/selection-toolbar.d.ts +14 -0
- package/dist/ui/file-preview/src/markdown/selection-toolbar.js +128 -0
- package/dist/ui/file-preview/src/markdown/slugify.d.ts +3 -0
- package/dist/ui/file-preview/src/markdown/slugify.js +31 -0
- package/dist/ui/file-preview/src/markdown/toc.d.ts +11 -0
- package/dist/ui/file-preview/src/markdown/toc.js +75 -0
- package/dist/ui/file-preview/src/markdown/utils.d.ts +1 -0
- package/dist/ui/file-preview/src/markdown/utils.js +15 -0
- package/dist/ui/file-preview/src/markdown-workspace/editor.d.ts +36 -0
- package/dist/ui/file-preview/src/markdown-workspace/editor.js +643 -0
- package/dist/ui/file-preview/src/markdown-workspace/linking.d.ts +9 -0
- package/dist/ui/file-preview/src/markdown-workspace/linking.js +210 -0
- package/dist/ui/file-preview/src/markdown-workspace/outline.d.ts +7 -0
- package/dist/ui/file-preview/src/markdown-workspace/outline.js +40 -0
- package/dist/ui/file-preview/src/markdown-workspace/preview.d.ts +8 -0
- package/dist/ui/file-preview/src/markdown-workspace/preview.js +33 -0
- package/dist/ui/file-preview/src/markdown-workspace/slugify.d.ts +3 -0
- package/dist/ui/file-preview/src/markdown-workspace/slugify.js +31 -0
- package/dist/ui/file-preview/src/markdown-workspace/toc.d.ts +11 -0
- package/dist/ui/file-preview/src/markdown-workspace/toc.js +75 -0
- package/dist/ui/file-preview/src/markdown-workspace/utils.d.ts +1 -0
- package/dist/ui/file-preview/src/markdown-workspace/utils.js +15 -0
- package/dist/ui/file-preview/src/markdown-workspace/workspace-controller.d.ts +25 -0
- package/dist/ui/file-preview/src/markdown-workspace/workspace-controller.js +40 -0
- package/dist/ui/file-preview/src/model.d.ts +34 -0
- package/dist/ui/file-preview/src/panel-actions.d.ts +17 -0
- package/dist/ui/file-preview/src/panel-actions.js +182 -0
- package/dist/ui/file-preview/src/path-utils.d.ts +6 -0
- package/dist/ui/file-preview/src/path-utils.js +64 -0
- package/dist/ui/file-preview/src/payload-utils.d.ts +11 -0
- package/dist/ui/file-preview/src/payload-utils.js +94 -0
- package/dist/ui/file-preview/styles.css +1066 -233
- package/dist/ui/file-preview/types.d.ts +1 -0
- package/dist/ui/server-integration.d.ts +13 -0
- package/dist/ui/server-integration.js +31 -0
- package/dist/ui/shared/ToolHeader.d.ts +9 -0
- package/dist/ui/shared/ToolHeader.js +29 -0
- package/dist/ui/shared/app-bootstrap.d.ts +9 -0
- package/dist/ui/shared/app-bootstrap.js +15 -0
- package/dist/ui/shared/guards.d.ts +1 -0
- package/dist/ui/shared/guards.js +3 -0
- package/dist/ui/shared/host-lifecycle.d.ts +1 -0
- package/dist/ui/shared/host-lifecycle.js +8 -2
- package/dist/ui/shared/widget-state.d.ts +6 -1
- package/dist/ui/shared/widget-state.js +102 -4
- package/dist/utils/files/base.d.ts +2 -0
- package/dist/utils/open-browser.js +1 -1
- package/dist/utils/ui-call-context.d.ts +8 -0
- package/dist/utils/ui-call-context.js +72 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +6 -1
- package/dist/data/spec-kit-prompts.json +0 -123
- package/dist/handlers/macos-control-handlers.d.ts +0 -16
- package/dist/handlers/macos-control-handlers.js +0 -81
- package/dist/handlers/node-handlers.d.ts +0 -6
- package/dist/handlers/node-handlers.js +0 -73
- package/dist/handlers/test-crash-handler.d.ts +0 -11
- package/dist/handlers/test-crash-handler.js +0 -26
- package/dist/http-index.d.ts +0 -45
- package/dist/http-index.js +0 -51
- package/dist/http-server-auto-tunnel.js +0 -667
- package/dist/http-server-named-tunnel.d.ts +0 -2
- package/dist/http-server-named-tunnel.js +0 -167
- package/dist/http-server-tunnel.d.ts +0 -2
- package/dist/http-server-tunnel.js +0 -111
- package/dist/http-server.d.ts +0 -2
- package/dist/http-server.js +0 -270
- package/dist/index-oauth.d.ts +0 -2
- package/dist/index-oauth.js +0 -201
- package/dist/lib.d.ts +0 -10
- package/dist/lib.js +0 -10
- package/dist/oauth/auth-middleware.d.ts +0 -20
- package/dist/oauth/auth-middleware.js +0 -62
- package/dist/oauth/index.d.ts +0 -3
- package/dist/oauth/index.js +0 -3
- package/dist/oauth/oauth-manager.d.ts +0 -80
- package/dist/oauth/oauth-manager.js +0 -179
- package/dist/oauth/oauth-routes.d.ts +0 -3
- package/dist/oauth/oauth-routes.js +0 -377
- package/dist/oauth/provider.d.ts +0 -22
- package/dist/oauth/provider.js +0 -124
- package/dist/oauth/server.d.ts +0 -18
- package/dist/oauth/server.js +0 -160
- package/dist/oauth/types.d.ts +0 -54
- package/dist/oauth/types.js +0 -2
- package/dist/remote-device/templates/auth-success.d.ts +0 -1
- package/dist/remote-device/templates/auth-success.js +0 -30
- package/dist/setup.log +0 -275
- package/dist/test-setup.js +0 -14
- package/dist/tools/docx/builders/html-builder.d.ts +0 -17
- package/dist/tools/docx/builders/html-builder.js +0 -92
- package/dist/tools/docx/builders/image.d.ts +0 -14
- package/dist/tools/docx/builders/image.js +0 -84
- package/dist/tools/docx/builders/index.d.ts +0 -11
- package/dist/tools/docx/builders/index.js +0 -11
- package/dist/tools/docx/builders/markdown-builder.d.ts +0 -2
- package/dist/tools/docx/builders/markdown-builder.js +0 -260
- package/dist/tools/docx/builders/paragraph.d.ts +0 -12
- package/dist/tools/docx/builders/paragraph.js +0 -29
- package/dist/tools/docx/builders/table.d.ts +0 -10
- package/dist/tools/docx/builders/table.js +0 -138
- package/dist/tools/docx/builders/utils.d.ts +0 -5
- package/dist/tools/docx/builders/utils.js +0 -18
- package/dist/tools/docx/constants.d.ts +0 -32
- package/dist/tools/docx/constants.js +0 -61
- package/dist/tools/docx/converters/markdown-to-html.d.ts +0 -17
- package/dist/tools/docx/converters/markdown-to-html.js +0 -111
- package/dist/tools/docx/create.d.ts +0 -21
- package/dist/tools/docx/create.js +0 -386
- package/dist/tools/docx/dom.d.ts +0 -139
- package/dist/tools/docx/dom.js +0 -448
- package/dist/tools/docx/errors.d.ts +0 -28
- package/dist/tools/docx/errors.js +0 -48
- package/dist/tools/docx/extractors/images.d.ts +0 -14
- package/dist/tools/docx/extractors/images.js +0 -40
- package/dist/tools/docx/extractors/metadata.d.ts +0 -14
- package/dist/tools/docx/extractors/metadata.js +0 -64
- package/dist/tools/docx/extractors/sections.d.ts +0 -14
- package/dist/tools/docx/extractors/sections.js +0 -61
- package/dist/tools/docx/html.d.ts +0 -17
- package/dist/tools/docx/html.js +0 -111
- package/dist/tools/docx/index.d.ts +0 -10
- package/dist/tools/docx/index.js +0 -10
- package/dist/tools/docx/markdown.d.ts +0 -84
- package/dist/tools/docx/markdown.js +0 -507
- package/dist/tools/docx/modify.d.ts +0 -28
- package/dist/tools/docx/modify.js +0 -271
- package/dist/tools/docx/operations/handlers/index.d.ts +0 -39
- package/dist/tools/docx/operations/handlers/index.js +0 -152
- package/dist/tools/docx/operations/html-manipulator.d.ts +0 -24
- package/dist/tools/docx/operations/html-manipulator.js +0 -352
- package/dist/tools/docx/operations/index.d.ts +0 -14
- package/dist/tools/docx/operations/index.js +0 -61
- package/dist/tools/docx/operations/operation-handlers.d.ts +0 -3
- package/dist/tools/docx/operations/operation-handlers.js +0 -67
- package/dist/tools/docx/operations/preprocessor.d.ts +0 -14
- package/dist/tools/docx/operations/preprocessor.js +0 -44
- package/dist/tools/docx/operations/xml-replacer.d.ts +0 -9
- package/dist/tools/docx/operations/xml-replacer.js +0 -35
- package/dist/tools/docx/operations.d.ts +0 -13
- package/dist/tools/docx/operations.js +0 -13
- package/dist/tools/docx/ops/delete-paragraph-at-body-index.d.ts +0 -11
- package/dist/tools/docx/ops/delete-paragraph-at-body-index.js +0 -23
- package/dist/tools/docx/ops/header-replace-text-exact.d.ts +0 -13
- package/dist/tools/docx/ops/header-replace-text-exact.js +0 -55
- package/dist/tools/docx/ops/index.d.ts +0 -17
- package/dist/tools/docx/ops/index.js +0 -70
- package/dist/tools/docx/ops/insert-image-after-text.d.ts +0 -24
- package/dist/tools/docx/ops/insert-image-after-text.js +0 -128
- package/dist/tools/docx/ops/insert-paragraph-after-text.d.ts +0 -12
- package/dist/tools/docx/ops/insert-paragraph-after-text.js +0 -74
- package/dist/tools/docx/ops/insert-table-after-text.d.ts +0 -19
- package/dist/tools/docx/ops/insert-table-after-text.js +0 -57
- package/dist/tools/docx/ops/replace-hyperlink-url.d.ts +0 -12
- package/dist/tools/docx/ops/replace-hyperlink-url.js +0 -37
- package/dist/tools/docx/ops/replace-paragraph-at-body-index.d.ts +0 -9
- package/dist/tools/docx/ops/replace-paragraph-at-body-index.js +0 -25
- package/dist/tools/docx/ops/replace-paragraph-text-exact.d.ts +0 -21
- package/dist/tools/docx/ops/replace-paragraph-text-exact.js +0 -36
- package/dist/tools/docx/ops/replace-table-cell-text.d.ts +0 -25
- package/dist/tools/docx/ops/replace-table-cell-text.js +0 -85
- package/dist/tools/docx/ops/set-color-for-paragraph-exact.d.ts +0 -9
- package/dist/tools/docx/ops/set-color-for-paragraph-exact.js +0 -24
- package/dist/tools/docx/ops/set-color-for-style.d.ts +0 -13
- package/dist/tools/docx/ops/set-color-for-style.js +0 -31
- package/dist/tools/docx/ops/set-paragraph-style-at-body-index.d.ts +0 -8
- package/dist/tools/docx/ops/set-paragraph-style-at-body-index.js +0 -57
- package/dist/tools/docx/ops/table-set-cell-text.d.ts +0 -9
- package/dist/tools/docx/ops/table-set-cell-text.js +0 -40
- package/dist/tools/docx/parsers/image-extractor.d.ts +0 -18
- package/dist/tools/docx/parsers/image-extractor.js +0 -61
- package/dist/tools/docx/parsers/index.d.ts +0 -9
- package/dist/tools/docx/parsers/index.js +0 -9
- package/dist/tools/docx/parsers/paragraph-parser.d.ts +0 -2
- package/dist/tools/docx/parsers/paragraph-parser.js +0 -88
- package/dist/tools/docx/parsers/table-parser.d.ts +0 -9
- package/dist/tools/docx/parsers/table-parser.js +0 -72
- package/dist/tools/docx/parsers/xml-parser.d.ts +0 -25
- package/dist/tools/docx/parsers/xml-parser.js +0 -71
- package/dist/tools/docx/parsers/zip-reader.d.ts +0 -23
- package/dist/tools/docx/parsers/zip-reader.js +0 -52
- package/dist/tools/docx/read.d.ts +0 -27
- package/dist/tools/docx/read.js +0 -308
- package/dist/tools/docx/relationships.d.ts +0 -22
- package/dist/tools/docx/relationships.js +0 -76
- package/dist/tools/docx/structure.d.ts +0 -25
- package/dist/tools/docx/structure.js +0 -102
- package/dist/tools/docx/styled-html-parser.d.ts +0 -23
- package/dist/tools/docx/styled-html-parser.js +0 -1262
- package/dist/tools/docx/types.d.ts +0 -213
- package/dist/tools/docx/types.js +0 -5
- package/dist/tools/docx/utils/escaping.d.ts +0 -13
- package/dist/tools/docx/utils/escaping.js +0 -26
- package/dist/tools/docx/utils/images.d.ts +0 -9
- package/dist/tools/docx/utils/images.js +0 -26
- package/dist/tools/docx/utils/index.d.ts +0 -12
- package/dist/tools/docx/utils/index.js +0 -17
- package/dist/tools/docx/utils/markdown.d.ts +0 -13
- package/dist/tools/docx/utils/markdown.js +0 -32
- package/dist/tools/docx/utils/paths.d.ts +0 -15
- package/dist/tools/docx/utils/paths.js +0 -27
- package/dist/tools/docx/utils/versioning.d.ts +0 -25
- package/dist/tools/docx/utils/versioning.js +0 -55
- package/dist/tools/docx/utils.d.ts +0 -101
- package/dist/tools/docx/utils.js +0 -299
- package/dist/tools/docx/validate.d.ts +0 -33
- package/dist/tools/docx/validate.js +0 -49
- package/dist/tools/docx/validators.d.ts +0 -13
- package/dist/tools/docx/validators.js +0 -40
- package/dist/tools/docx/write.d.ts +0 -17
- package/dist/tools/docx/write.js +0 -88
- package/dist/tools/docx/xml-view-test.js +0 -63
- package/dist/tools/docx/xml-view.d.ts +0 -56
- package/dist/tools/docx/xml-view.js +0 -169
- package/dist/tools/docx/zip.d.ts +0 -21
- package/dist/tools/docx/zip.js +0 -35
- package/dist/tools/macos-control/ax-adapter.d.ts +0 -55
- package/dist/tools/macos-control/ax-adapter.js +0 -438
- package/dist/tools/macos-control/cdp-adapter.d.ts +0 -23
- package/dist/tools/macos-control/cdp-adapter.js +0 -402
- package/dist/tools/macos-control/orchestrator.d.ts +0 -77
- package/dist/tools/macos-control/orchestrator.js +0 -136
- package/dist/tools/macos-control/role-aliases.d.ts +0 -5
- package/dist/tools/macos-control/role-aliases.js +0 -34
- package/dist/tools/macos-control/types.d.ts +0 -129
- package/dist/tools/pdf-processor.d.ts +0 -1
- package/dist/tools/pdf-processor.js +0 -3
- package/dist/tools/search.d.ts +0 -32
- package/dist/tools/search.js +0 -202
- package/dist/ui/file-preview/src/app.js +0 -714
- package/dist/utils/crash-logger.d.ts +0 -18
- package/dist/utils/crash-logger.js +0 -44
- package/dist/utils/dedent.d.ts +0 -8
- package/dist/utils/dedent.js +0 -38
- /package/dist/ui/config-editor/{src/app.d.ts → app.d.ts} +0 -0
- /package/dist/{http-server-auto-tunnel.d.ts → ui/config-editor/main.d.ts} +0 -0
- /package/dist/ui/config-editor/src/{app.js → App.js} +0 -0
- /package/dist/{test-docx.d.ts → ui/file-preview/main.d.ts} +0 -0
- /package/dist/ui/file-preview/src/components/{toolbar.d.ts → Toolbar.d.ts} +0 -0
- /package/dist/ui/file-preview/src/components/{toolbar.js → Toolbar.js} +0 -0
- /package/dist/{tools/docx/xml-view-test.d.ts → ui/file-preview/src/model.js} +0 -0
- /package/dist/{tools/macos-control → ui/file-preview}/types.js +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type PreviewFileType = 'markdown' | 'text' | 'html' | 'image' | 'unsupported';
|
|
1
|
+
export type PreviewFileType = 'markdown' | 'text' | 'html' | 'image' | 'directory' | 'unsupported';
|
|
2
2
|
export declare const MARKDOWN_PREVIEW_EXTENSIONS: Set<string>;
|
|
3
3
|
export declare const HTML_PREVIEW_EXTENSIONS: Set<string>;
|
|
4
4
|
export declare const TEXT_PREVIEW_EXTENSIONS: Set<string>;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { RenderPayload } from './model.js';
|
|
2
|
+
import type { HtmlPreviewMode } from './types.js';
|
|
3
|
+
export declare function renderApp(container: HTMLElement, payload?: RenderPayload, htmlMode?: HtmlPreviewMode, expandedState?: boolean): void;
|
|
4
|
+
export declare function bootstrapApp(): void;
|
|
@@ -0,0 +1,564 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composition root for the File Preview app. It wires host services, file-type handlers, and specialized controllers together without owning feature logic inline.
|
|
3
|
+
*/
|
|
4
|
+
import { App } from '@modelcontextprotocol/ext-apps';
|
|
5
|
+
import { createCompactRowShellController } from '../../shared/tool-shell.js';
|
|
6
|
+
import { createWidgetStateStorage } from '../../shared/widget-state.js';
|
|
7
|
+
import { renderCompactRow } from '../../shared/compact-row.js';
|
|
8
|
+
import { connectWithSharedHostContext } from '../../shared/host-context.js';
|
|
9
|
+
import { createUiEventTracker } from '../../shared/ui-event-tracker.js';
|
|
10
|
+
import { attachDirectoryHandlers } from './directory-controller.js';
|
|
11
|
+
import { buildDocumentLayout } from './document-layout.js';
|
|
12
|
+
import { getDocumentFullscreenAvailability, parseReadRange, stripReadStatusLine } from './document-workspace.js';
|
|
13
|
+
import { getFileTypeCapabilities, renderPayloadBody } from './file-type-handlers.js';
|
|
14
|
+
import { buildOpenInEditorCommand, buildOpenInFolderCommand, detectDefaultMarkdownEditor, renderMarkdownEditorAppIcon } from './host/external-actions.js';
|
|
15
|
+
import { attachSelectionContext } from './host/selection-context.js';
|
|
16
|
+
import { createMarkdownController } from './markdown/controller.js';
|
|
17
|
+
import { createConflictDialogController, renderConflictDialogMarkup, } from './markdown/conflict-dialog.js';
|
|
18
|
+
import { attachPanelActions } from './panel-actions.js';
|
|
19
|
+
import { extractRenderPayload, extractToolText, getFileExtensionForAnalytics, isLikelyUrl, isPreviewStructuredContent } from './payload-utils.js';
|
|
20
|
+
let isExpanded = false;
|
|
21
|
+
let hideSummaryRow = false;
|
|
22
|
+
let previewShownFired = false;
|
|
23
|
+
let onRender;
|
|
24
|
+
let trackUiEvent;
|
|
25
|
+
let conflictDialogController;
|
|
26
|
+
let rpcCallTool;
|
|
27
|
+
let rpcUpdateContext;
|
|
28
|
+
let openExternalLink;
|
|
29
|
+
let requestDisplayMode;
|
|
30
|
+
let shellController;
|
|
31
|
+
let currentPayload;
|
|
32
|
+
let currentHtmlMode = 'rendered';
|
|
33
|
+
let currentHostContext;
|
|
34
|
+
let rerenderCurrent;
|
|
35
|
+
let syncPayload;
|
|
36
|
+
let persistPayload;
|
|
37
|
+
let localPayloadOverride;
|
|
38
|
+
let hostPayload;
|
|
39
|
+
let inlinePayloadBeforeFullscreen;
|
|
40
|
+
let directoryBackPayload;
|
|
41
|
+
let selectionAbortController = null;
|
|
42
|
+
const markdownEditorAppCache = new Map();
|
|
43
|
+
const markdownEditorAppPending = new Set();
|
|
44
|
+
async function callToolIfReady(name, args) {
|
|
45
|
+
return rpcCallTool ? rpcCallTool(name, args) : undefined;
|
|
46
|
+
}
|
|
47
|
+
function getAvailableDisplayModes() {
|
|
48
|
+
const rawModes = currentHostContext?.availableDisplayModes;
|
|
49
|
+
if (!Array.isArray(rawModes)) {
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
52
|
+
return rawModes.filter((mode) => typeof mode === 'string');
|
|
53
|
+
}
|
|
54
|
+
function getCurrentDisplayMode() {
|
|
55
|
+
return typeof currentHostContext?.displayMode === 'string'
|
|
56
|
+
? currentHostContext.displayMode
|
|
57
|
+
: null;
|
|
58
|
+
}
|
|
59
|
+
function storePayloadOverride(payload) {
|
|
60
|
+
localPayloadOverride = payload;
|
|
61
|
+
currentPayload = payload;
|
|
62
|
+
persistPayload?.(payload);
|
|
63
|
+
}
|
|
64
|
+
function getEffectiveIncomingPayload(payload) {
|
|
65
|
+
if (!localPayloadOverride) {
|
|
66
|
+
return payload;
|
|
67
|
+
}
|
|
68
|
+
if (localPayloadOverride.filePath !== payload.filePath) {
|
|
69
|
+
localPayloadOverride = undefined;
|
|
70
|
+
return payload;
|
|
71
|
+
}
|
|
72
|
+
const incomingContent = stripReadStatusLine(payload.content);
|
|
73
|
+
const overriddenContent = stripReadStatusLine(localPayloadOverride.content);
|
|
74
|
+
if (incomingContent === overriddenContent) {
|
|
75
|
+
return payload;
|
|
76
|
+
}
|
|
77
|
+
return localPayloadOverride;
|
|
78
|
+
}
|
|
79
|
+
function updateSaveStatusDOM(label, statusClass) {
|
|
80
|
+
const existing = document.querySelector('.panel-save-status');
|
|
81
|
+
if (label) {
|
|
82
|
+
if (existing) {
|
|
83
|
+
existing.textContent = label;
|
|
84
|
+
existing.className = `panel-save-status panel-save-status--${statusClass}`;
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
const actions = document.querySelector('.panel-topbar-actions');
|
|
88
|
+
if (actions) {
|
|
89
|
+
const span = document.createElement('span');
|
|
90
|
+
span.className = `panel-save-status panel-save-status--${statusClass}`;
|
|
91
|
+
span.textContent = label;
|
|
92
|
+
actions.prepend(span);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
else if (existing) {
|
|
97
|
+
existing.remove();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
const markdownController = createMarkdownController({
|
|
101
|
+
callTool: callToolIfReady,
|
|
102
|
+
openExternalLink: async (url) => (openExternalLink ? openExternalLink(url) : undefined),
|
|
103
|
+
requestDisplayMode: async (mode) => (requestDisplayMode ? requestDisplayMode(mode) : undefined),
|
|
104
|
+
getAvailableDisplayModes,
|
|
105
|
+
getCurrentDisplayMode,
|
|
106
|
+
getCurrentPayload: () => currentPayload,
|
|
107
|
+
setExpanded: (expanded) => {
|
|
108
|
+
isExpanded = expanded;
|
|
109
|
+
},
|
|
110
|
+
syncPayload: (payload) => syncPayload?.(payload),
|
|
111
|
+
storePayloadOverride,
|
|
112
|
+
rerender: () => {
|
|
113
|
+
rerenderCurrent?.();
|
|
114
|
+
},
|
|
115
|
+
updateSaveStatus: updateSaveStatusDOM,
|
|
116
|
+
trackUiEvent: (event, params) => trackUiEvent?.(event, params),
|
|
117
|
+
showConflictDialog: (options) => {
|
|
118
|
+
if (conflictDialogController) {
|
|
119
|
+
conflictDialogController.open(options);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
// Dialog not yet initialized (would only happen if the save failure
|
|
123
|
+
// somehow fires before bootstrapApp). Fall back to the cancel callback
|
|
124
|
+
// so the editor still shows its inline note instead of silently no-op'ing.
|
|
125
|
+
console.warn('[file-preview] conflictDialogController not ready; firing onCancel fallback');
|
|
126
|
+
options.onCancel?.();
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
/**
|
|
130
|
+
* Check if a payload needs its file content to be read.
|
|
131
|
+
* Tool results from edit_block/write_file include structuredContent but
|
|
132
|
+
* their text is a success message, not file content. Detect this by
|
|
133
|
+
* checking for the absence of the read status line that read_file always includes.
|
|
134
|
+
* URL payloads are fetched remotely by read_file(isUrl:true); we can't
|
|
135
|
+
* re-fetch them from here (no isUrl flag on the refresh path), so skip.
|
|
136
|
+
*/
|
|
137
|
+
function needsContentRead(payload) {
|
|
138
|
+
if (payload.fileType === 'directory' || payload.fileType === 'image' || payload.fileType === 'unsupported') {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
if (/^https?:\/\//i.test(payload.filePath)) {
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
return !parseReadRange(payload.content);
|
|
145
|
+
}
|
|
146
|
+
async function readAndResolvePayload(payload, onReady) {
|
|
147
|
+
try {
|
|
148
|
+
const freshPayload = await markdownController.readPayload(payload.filePath);
|
|
149
|
+
if (freshPayload) {
|
|
150
|
+
onReady(freshPayload);
|
|
151
|
+
if (freshPayload.fileType === 'markdown') {
|
|
152
|
+
void markdownController.refreshFromDisk(freshPayload);
|
|
153
|
+
}
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
// Fall through to original payload.
|
|
159
|
+
}
|
|
160
|
+
onReady(payload);
|
|
161
|
+
}
|
|
162
|
+
function renderStatusState(container, message) {
|
|
163
|
+
container.innerHTML = `
|
|
164
|
+
<main class="shell">
|
|
165
|
+
${renderCompactRow({ label: message, variant: 'status', interactive: false })}
|
|
166
|
+
</main>
|
|
167
|
+
`;
|
|
168
|
+
document.body.classList.add('dc-ready');
|
|
169
|
+
}
|
|
170
|
+
function renderLoadingState(container) {
|
|
171
|
+
container.innerHTML = `
|
|
172
|
+
<main class="shell">
|
|
173
|
+
${renderCompactRow({ label: 'Preparing preview…', variant: 'loading', interactive: false })}
|
|
174
|
+
</main>
|
|
175
|
+
`;
|
|
176
|
+
document.body.classList.add('dc-ready');
|
|
177
|
+
}
|
|
178
|
+
export function renderApp(container, payload, htmlMode = 'rendered', expandedState = false) {
|
|
179
|
+
isExpanded = expandedState;
|
|
180
|
+
currentHtmlMode = htmlMode;
|
|
181
|
+
shellController?.dispose();
|
|
182
|
+
shellController = undefined;
|
|
183
|
+
if (!payload || payload.fileType !== 'markdown') {
|
|
184
|
+
markdownController.clear();
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
markdownController.disposeHandles();
|
|
188
|
+
}
|
|
189
|
+
if (!payload) {
|
|
190
|
+
selectionAbortController?.abort();
|
|
191
|
+
selectionAbortController = null;
|
|
192
|
+
currentPayload = undefined;
|
|
193
|
+
renderStatusState(container, 'No preview available for this response.');
|
|
194
|
+
onRender?.();
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
currentPayload = payload;
|
|
198
|
+
const capabilities = getFileTypeCapabilities(payload);
|
|
199
|
+
if (!capabilities.supportsPreview && hideSummaryRow) {
|
|
200
|
+
isExpanded = false;
|
|
201
|
+
}
|
|
202
|
+
const range = parseReadRange(payload.content);
|
|
203
|
+
const body = renderPayloadBody({
|
|
204
|
+
payload,
|
|
205
|
+
htmlMode,
|
|
206
|
+
startLine: range?.fromLine ?? 1,
|
|
207
|
+
markdownController,
|
|
208
|
+
});
|
|
209
|
+
const markdownWorkspace = payload.fileType === 'markdown' ? markdownController.getState(payload) : undefined;
|
|
210
|
+
const fileExtension = getFileExtensionForAnalytics(payload.filePath);
|
|
211
|
+
const isFullscreen = getCurrentDisplayMode() === 'fullscreen';
|
|
212
|
+
const canGoFullscreen = !isFullscreen && getDocumentFullscreenAvailability({
|
|
213
|
+
availableDisplayModes: getAvailableDisplayModes(),
|
|
214
|
+
}).canFullscreen;
|
|
215
|
+
const defaultMarkdownEditor = payload.fileType === 'markdown'
|
|
216
|
+
? markdownEditorAppCache.get(payload.filePath)
|
|
217
|
+
: undefined;
|
|
218
|
+
if (payload.fileType === 'markdown' && !defaultMarkdownEditor) {
|
|
219
|
+
void detectDefaultMarkdownEditor({
|
|
220
|
+
filePath: payload.filePath,
|
|
221
|
+
editorAppCache: markdownEditorAppCache,
|
|
222
|
+
editorAppPending: markdownEditorAppPending,
|
|
223
|
+
callTool: callToolIfReady,
|
|
224
|
+
extractToolText,
|
|
225
|
+
onDetected: () => {
|
|
226
|
+
rerenderCurrent?.();
|
|
227
|
+
},
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
const layout = buildDocumentLayout({
|
|
231
|
+
payload,
|
|
232
|
+
body,
|
|
233
|
+
capabilities,
|
|
234
|
+
fileExtension,
|
|
235
|
+
htmlMode,
|
|
236
|
+
currentDisplayMode: getCurrentDisplayMode(),
|
|
237
|
+
isExpanded,
|
|
238
|
+
hideSummaryRow,
|
|
239
|
+
markdownWorkspace,
|
|
240
|
+
canGoFullscreen,
|
|
241
|
+
isMarkdownUndoAvailable: markdownWorkspace ? markdownController.isUndoAvailable(markdownWorkspace) : false,
|
|
242
|
+
defaultMarkdownEditorName: defaultMarkdownEditor?.appName,
|
|
243
|
+
markdownEditorAppIcon: renderMarkdownEditorAppIcon(),
|
|
244
|
+
hasDirectoryBackButton: Boolean(directoryBackPayload),
|
|
245
|
+
});
|
|
246
|
+
container.innerHTML = layout.html;
|
|
247
|
+
document.body.classList.add('dc-ready');
|
|
248
|
+
attachPanelActions({
|
|
249
|
+
container,
|
|
250
|
+
payload,
|
|
251
|
+
htmlMode,
|
|
252
|
+
getIsExpanded: () => isExpanded,
|
|
253
|
+
callTool: callToolIfReady,
|
|
254
|
+
trackUiEvent,
|
|
255
|
+
getFileExtensionForAnalytics,
|
|
256
|
+
buildOpenInFolderCommand: (filePath) => buildOpenInFolderCommand(filePath, isLikelyUrl),
|
|
257
|
+
buildOpenInEditorCommand: (filePath) => buildOpenInEditorCommand(filePath, isLikelyUrl, markdownEditorAppCache),
|
|
258
|
+
render: (nextPayload, nextHtmlMode = 'rendered', nextExpanded = isExpanded) => {
|
|
259
|
+
renderApp(container, nextPayload, nextHtmlMode, nextExpanded);
|
|
260
|
+
},
|
|
261
|
+
updateSaveStatus: updateSaveStatusDOM,
|
|
262
|
+
markdownController,
|
|
263
|
+
});
|
|
264
|
+
if (payload.fileType === 'markdown') {
|
|
265
|
+
markdownController.attachHandlers(payload);
|
|
266
|
+
}
|
|
267
|
+
selectionAbortController = attachSelectionContext({
|
|
268
|
+
payload,
|
|
269
|
+
isMarkdownEditing: payload.fileType === 'markdown' && !!markdownWorkspace,
|
|
270
|
+
updateContext: rpcUpdateContext,
|
|
271
|
+
trackUiEvent,
|
|
272
|
+
getFileExtensionForAnalytics,
|
|
273
|
+
previousAbortController: selectionAbortController,
|
|
274
|
+
});
|
|
275
|
+
if (payload.fileType === 'directory') {
|
|
276
|
+
attachDirectoryHandlers({
|
|
277
|
+
container,
|
|
278
|
+
callTool: callToolIfReady,
|
|
279
|
+
buildOpenInFolderCommand: (filePath) => buildOpenInFolderCommand(filePath, isLikelyUrl),
|
|
280
|
+
onOpenPayload: (nextPayload) => {
|
|
281
|
+
directoryBackPayload = payload;
|
|
282
|
+
renderApp(container, nextPayload, 'rendered', true);
|
|
283
|
+
},
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
const backBtn = document.getElementById('dir-back');
|
|
287
|
+
if (backBtn && directoryBackPayload) {
|
|
288
|
+
const savedPayload = directoryBackPayload;
|
|
289
|
+
backBtn.addEventListener('click', () => {
|
|
290
|
+
directoryBackPayload = undefined;
|
|
291
|
+
renderApp(container, savedPayload, 'rendered', true);
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
if (payload.fileType === 'directory') {
|
|
295
|
+
directoryBackPayload = undefined;
|
|
296
|
+
}
|
|
297
|
+
const compactRow = document.getElementById('compact-toggle');
|
|
298
|
+
shellController = createCompactRowShellController({
|
|
299
|
+
shell: document.getElementById('tool-shell'),
|
|
300
|
+
compactRow,
|
|
301
|
+
initialExpanded: layout.effectiveExpanded,
|
|
302
|
+
onToggle: (expanded) => {
|
|
303
|
+
isExpanded = expanded;
|
|
304
|
+
trackUiEvent?.(expanded ? 'expand' : 'collapse', {
|
|
305
|
+
file_type: payload.fileType,
|
|
306
|
+
file_extension: fileExtension,
|
|
307
|
+
});
|
|
308
|
+
},
|
|
309
|
+
onScrollAfterExpand: () => {
|
|
310
|
+
trackUiEvent?.('scroll_after_expand', {
|
|
311
|
+
file_type: payload.fileType,
|
|
312
|
+
file_extension: fileExtension,
|
|
313
|
+
});
|
|
314
|
+
},
|
|
315
|
+
onRender,
|
|
316
|
+
});
|
|
317
|
+
onRender?.();
|
|
318
|
+
if (!previewShownFired) {
|
|
319
|
+
previewShownFired = true;
|
|
320
|
+
trackUiEvent?.('preview_shown', {
|
|
321
|
+
file_type: payload.fileType,
|
|
322
|
+
file_extension: fileExtension,
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
export function bootstrapApp() {
|
|
327
|
+
const container = document.getElementById('app');
|
|
328
|
+
if (!container) {
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
renderLoadingState(container);
|
|
332
|
+
// Mount the conflict dialog once at body level. It's position: fixed and
|
|
333
|
+
// must live outside the app container so that re-renders of the document
|
|
334
|
+
// body never wipe it while it's open.
|
|
335
|
+
if (!document.getElementById('md-conflict-modal')) {
|
|
336
|
+
const dialogHost = document.createElement('div');
|
|
337
|
+
dialogHost.innerHTML = renderConflictDialogMarkup();
|
|
338
|
+
const dialogRoot = dialogHost.firstElementChild;
|
|
339
|
+
if (dialogRoot) {
|
|
340
|
+
document.body.appendChild(dialogRoot);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
conflictDialogController = createConflictDialogController({ container: document });
|
|
344
|
+
const app = new App({ name: 'Desktop Commander File Preview', version: '1.0.0' }, { updateModelContext: { text: {} } }, { autoResize: true });
|
|
345
|
+
const chrome = {
|
|
346
|
+
expanded: isExpanded,
|
|
347
|
+
hideSummaryRow,
|
|
348
|
+
};
|
|
349
|
+
const syncChromeState = () => {
|
|
350
|
+
isExpanded = chrome.expanded;
|
|
351
|
+
hideSummaryRow = chrome.hideSummaryRow;
|
|
352
|
+
};
|
|
353
|
+
const widgetState = createWidgetStateStorage((value) => isPreviewStructuredContent(value) && typeof value.content === 'string');
|
|
354
|
+
const renderAndSync = (payload) => {
|
|
355
|
+
if (payload) {
|
|
356
|
+
widgetState.write(payload);
|
|
357
|
+
}
|
|
358
|
+
renderApp(container, payload, 'rendered', isExpanded);
|
|
359
|
+
};
|
|
360
|
+
const syncFromPersistedWidgetState = () => {
|
|
361
|
+
const persistedPayload = widgetState.read();
|
|
362
|
+
if (!persistedPayload) {
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
if (currentPayload
|
|
366
|
+
&& currentPayload.filePath === persistedPayload.filePath
|
|
367
|
+
&& stripReadStatusLine(currentPayload.content) === stripReadStatusLine(persistedPayload.content)) {
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
renderAndSync(persistedPayload);
|
|
371
|
+
};
|
|
372
|
+
syncPayload = renderAndSync;
|
|
373
|
+
persistPayload = (payload) => {
|
|
374
|
+
widgetState.write(payload);
|
|
375
|
+
};
|
|
376
|
+
rerenderCurrent = () => {
|
|
377
|
+
renderApp(container, currentPayload, currentHtmlMode, isExpanded);
|
|
378
|
+
};
|
|
379
|
+
let pendingCachedPayload;
|
|
380
|
+
let initialStateResolved = false;
|
|
381
|
+
const resolveInitialState = (payload, message) => {
|
|
382
|
+
if (initialStateResolved) {
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
initialStateResolved = true;
|
|
386
|
+
if (payload) {
|
|
387
|
+
hostPayload = payload;
|
|
388
|
+
renderAndSync(payload);
|
|
389
|
+
if (payload.fileType === 'markdown' && getCurrentDisplayMode() === 'fullscreen') {
|
|
390
|
+
void markdownController.requestEditMode(payload);
|
|
391
|
+
}
|
|
392
|
+
if (payload.fileType === 'markdown') {
|
|
393
|
+
void markdownController.refreshFromDisk(payload);
|
|
394
|
+
}
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
renderStatusState(container, message ?? 'No preview available for this response.');
|
|
398
|
+
onRender?.();
|
|
399
|
+
};
|
|
400
|
+
onRender = () => { };
|
|
401
|
+
rpcCallTool = (name, args) => (app.callServerTool({ name, arguments: args }));
|
|
402
|
+
rpcUpdateContext = (text) => {
|
|
403
|
+
const params = text
|
|
404
|
+
? { content: [{ type: 'text', text }] }
|
|
405
|
+
: { content: [] };
|
|
406
|
+
app.updateModelContext(params).catch(() => {
|
|
407
|
+
// Host may not support updateModelContext.
|
|
408
|
+
});
|
|
409
|
+
};
|
|
410
|
+
openExternalLink = async (url) => {
|
|
411
|
+
const result = await app.openLink({ url });
|
|
412
|
+
return result.isError !== true;
|
|
413
|
+
};
|
|
414
|
+
requestDisplayMode = async (mode) => {
|
|
415
|
+
const result = await app.requestDisplayMode({ mode });
|
|
416
|
+
return typeof result.mode === 'string' ? result.mode : null;
|
|
417
|
+
};
|
|
418
|
+
trackUiEvent = createUiEventTracker((name, args) => app.callServerTool({ name, arguments: args }), {
|
|
419
|
+
component: 'file_preview',
|
|
420
|
+
baseParams: { tool_name: 'read_file' },
|
|
421
|
+
});
|
|
422
|
+
app.ontoolinput = (params) => {
|
|
423
|
+
const requestedPath = typeof params.arguments?.path === 'string' ? params.arguments.path : undefined;
|
|
424
|
+
if (!initialStateResolved
|
|
425
|
+
&& pendingCachedPayload
|
|
426
|
+
&& requestedPath
|
|
427
|
+
&& pendingCachedPayload.filePath === requestedPath) {
|
|
428
|
+
const cached = pendingCachedPayload;
|
|
429
|
+
pendingCachedPayload = undefined;
|
|
430
|
+
resolveInitialState(cached);
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
renderLoadingState(container);
|
|
434
|
+
onRender?.();
|
|
435
|
+
};
|
|
436
|
+
app.ontoolresult = (result) => {
|
|
437
|
+
pendingCachedPayload = undefined;
|
|
438
|
+
const payload = extractRenderPayload(result);
|
|
439
|
+
const message = extractToolText(result);
|
|
440
|
+
if (!initialStateResolved) {
|
|
441
|
+
if (payload) {
|
|
442
|
+
if (needsContentRead(payload)) {
|
|
443
|
+
void readAndResolvePayload(payload, (p) => resolveInitialState(getEffectiveIncomingPayload(p)));
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
resolveInitialState(getEffectiveIncomingPayload(payload));
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
if (message) {
|
|
450
|
+
resolveInitialState(undefined, message);
|
|
451
|
+
}
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
if (payload) {
|
|
455
|
+
if (needsContentRead(payload)) {
|
|
456
|
+
renderLoadingState(container);
|
|
457
|
+
void readAndResolvePayload(payload, (p) => renderAndSync(getEffectiveIncomingPayload(p)));
|
|
458
|
+
}
|
|
459
|
+
else {
|
|
460
|
+
renderAndSync(getEffectiveIncomingPayload(payload));
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
else if (message) {
|
|
464
|
+
renderStatusState(container, message);
|
|
465
|
+
onRender?.();
|
|
466
|
+
}
|
|
467
|
+
};
|
|
468
|
+
app.ontoolcancelled = (params) => {
|
|
469
|
+
resolveInitialState(undefined, params.reason ?? 'Tool was cancelled.');
|
|
470
|
+
};
|
|
471
|
+
const handleVisibilitySync = () => {
|
|
472
|
+
if (document.visibilityState === 'visible') {
|
|
473
|
+
syncFromPersistedWidgetState();
|
|
474
|
+
}
|
|
475
|
+
};
|
|
476
|
+
const handleFocusSync = () => {
|
|
477
|
+
// Only sync cross-tab state if the page was hidden (tab switch).
|
|
478
|
+
// Simple focus changes within the same page should not trigger a re-render
|
|
479
|
+
// as it destroys the active editor.
|
|
480
|
+
if (document.visibilityState !== 'visible') {
|
|
481
|
+
syncFromPersistedWidgetState();
|
|
482
|
+
}
|
|
483
|
+
};
|
|
484
|
+
const teardown = () => {
|
|
485
|
+
shellController?.dispose();
|
|
486
|
+
shellController = undefined;
|
|
487
|
+
markdownController.disposeHandles();
|
|
488
|
+
selectionAbortController?.abort();
|
|
489
|
+
selectionAbortController = null;
|
|
490
|
+
document.removeEventListener('visibilitychange', handleVisibilitySync);
|
|
491
|
+
window.removeEventListener('focus', handleFocusSync);
|
|
492
|
+
};
|
|
493
|
+
document.addEventListener('visibilitychange', handleVisibilitySync);
|
|
494
|
+
window.addEventListener('focus', handleFocusSync);
|
|
495
|
+
app.onteardown = async () => {
|
|
496
|
+
teardown();
|
|
497
|
+
return {};
|
|
498
|
+
};
|
|
499
|
+
void connectWithSharedHostContext({
|
|
500
|
+
app,
|
|
501
|
+
chrome,
|
|
502
|
+
onContextApplied: () => {
|
|
503
|
+
const previousDisplayMode = getCurrentDisplayMode();
|
|
504
|
+
syncChromeState();
|
|
505
|
+
currentHostContext = app.getHostContext();
|
|
506
|
+
const nextDisplayMode = getCurrentDisplayMode();
|
|
507
|
+
const displayModeChanged = previousDisplayMode !== nextDisplayMode;
|
|
508
|
+
// Clicking a display-mode button blurs the editor first, and the
|
|
509
|
+
// editor's onBlur handler already persists dirty drafts, so there
|
|
510
|
+
// is nothing additional to save here.
|
|
511
|
+
if (previousDisplayMode === 'fullscreen'
|
|
512
|
+
&& nextDisplayMode === 'inline'
|
|
513
|
+
&& currentPayload?.fileType === 'markdown') {
|
|
514
|
+
isExpanded = true;
|
|
515
|
+
chrome.expanded = true;
|
|
516
|
+
const restorePayload = inlinePayloadBeforeFullscreen ?? hostPayload;
|
|
517
|
+
const restoreWasPartial = restorePayload ? parseReadRange(restorePayload.content)?.isPartial === true : false;
|
|
518
|
+
if (restoreWasPartial && restorePayload) {
|
|
519
|
+
localPayloadOverride = restorePayload;
|
|
520
|
+
currentPayload = restorePayload;
|
|
521
|
+
widgetState.write(restorePayload);
|
|
522
|
+
void markdownController.handleInlineExitFromFullscreen(restorePayload).then((freshPayload) => {
|
|
523
|
+
if (freshPayload) {
|
|
524
|
+
currentPayload = freshPayload;
|
|
525
|
+
localPayloadOverride = freshPayload;
|
|
526
|
+
widgetState.write(freshPayload);
|
|
527
|
+
rerenderCurrent?.();
|
|
528
|
+
}
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
else {
|
|
532
|
+
void markdownController.handleInlineExitFromFullscreen();
|
|
533
|
+
}
|
|
534
|
+
inlinePayloadBeforeFullscreen = undefined;
|
|
535
|
+
}
|
|
536
|
+
if (previousDisplayMode !== 'fullscreen'
|
|
537
|
+
&& nextDisplayMode === 'fullscreen'
|
|
538
|
+
&& currentPayload?.fileType === 'markdown') {
|
|
539
|
+
inlinePayloadBeforeFullscreen = currentPayload;
|
|
540
|
+
if (parseReadRange(currentPayload.content)?.isPartial) {
|
|
541
|
+
void markdownController.requestEditMode(currentPayload);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
if (initialStateResolved && displayModeChanged) {
|
|
545
|
+
rerenderCurrent?.();
|
|
546
|
+
}
|
|
547
|
+
},
|
|
548
|
+
onConnected: () => {
|
|
549
|
+
currentHostContext = app.getHostContext();
|
|
550
|
+
pendingCachedPayload = widgetState.read() ?? undefined;
|
|
551
|
+
window.setTimeout(() => {
|
|
552
|
+
if (!initialStateResolved) {
|
|
553
|
+
resolveInitialState(undefined, 'Preview unavailable after page refresh. Switch threads or re-run the tool.');
|
|
554
|
+
}
|
|
555
|
+
}, 8000);
|
|
556
|
+
},
|
|
557
|
+
}).catch(() => {
|
|
558
|
+
renderStatusState(container, 'Failed to connect to host.');
|
|
559
|
+
onRender?.();
|
|
560
|
+
});
|
|
561
|
+
window.addEventListener('beforeunload', () => {
|
|
562
|
+
teardown();
|
|
563
|
+
}, { once: true });
|
|
564
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function inferLanguageFromPath(filePath: string): string;
|
|
2
|
+
export declare function formatJsonIfPossible(content: string, filePath: string): {
|
|
3
|
+
content: string;
|
|
4
|
+
notice?: string;
|
|
5
|
+
};
|
|
6
|
+
export declare function renderCodeViewer(code: string, language?: string): string;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { highlightSource } from './highlighting.js';
|
|
2
|
+
const EXTENSION_LANGUAGE_MAP = {
|
|
3
|
+
js: 'javascript',
|
|
4
|
+
cjs: 'javascript',
|
|
5
|
+
mjs: 'javascript',
|
|
6
|
+
ts: 'typescript',
|
|
7
|
+
jsx: 'javascript',
|
|
8
|
+
tsx: 'typescript',
|
|
9
|
+
json: 'json',
|
|
10
|
+
yaml: 'yaml',
|
|
11
|
+
yml: 'yaml',
|
|
12
|
+
toml: 'toml',
|
|
13
|
+
ini: 'ini',
|
|
14
|
+
xml: 'xml',
|
|
15
|
+
html: 'html',
|
|
16
|
+
htm: 'html',
|
|
17
|
+
css: 'css',
|
|
18
|
+
scss: 'css',
|
|
19
|
+
less: 'css',
|
|
20
|
+
sh: 'bash',
|
|
21
|
+
bash: 'bash',
|
|
22
|
+
zsh: 'bash',
|
|
23
|
+
py: 'python',
|
|
24
|
+
rb: 'ruby',
|
|
25
|
+
java: 'java',
|
|
26
|
+
go: 'go',
|
|
27
|
+
rs: 'rust',
|
|
28
|
+
sql: 'sql',
|
|
29
|
+
md: 'markdown',
|
|
30
|
+
markdown: 'markdown'
|
|
31
|
+
};
|
|
32
|
+
function getFileExtension(filePath) {
|
|
33
|
+
const match = filePath.toLowerCase().match(/\.([a-z0-9]+)$/);
|
|
34
|
+
return match ? match[1] : '';
|
|
35
|
+
}
|
|
36
|
+
export function inferLanguageFromPath(filePath) {
|
|
37
|
+
const extension = getFileExtension(filePath);
|
|
38
|
+
return EXTENSION_LANGUAGE_MAP[extension] ?? 'text';
|
|
39
|
+
}
|
|
40
|
+
export function formatJsonIfPossible(content, filePath) {
|
|
41
|
+
if (inferLanguageFromPath(filePath) !== 'json') {
|
|
42
|
+
return { content };
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
return {
|
|
46
|
+
content: `${JSON.stringify(JSON.parse(content), null, 2)}\n`
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return {
|
|
51
|
+
content,
|
|
52
|
+
notice: 'Invalid JSON. Showing raw source.'
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export function renderCodeViewer(code, language = 'text') {
|
|
57
|
+
const normalizedLanguage = language || 'text';
|
|
58
|
+
const highlighted = highlightSource(code, normalizedLanguage);
|
|
59
|
+
return `<pre class="code-viewer"><code class="hljs language-${normalizedLanguage}">${highlighted}</code></pre>`;
|
|
60
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type HtmlPreviewMode = 'rendered' | 'source';
|
|
2
|
+
export interface HtmlRenderOptions {
|
|
3
|
+
allowUnsafeScripts?: boolean;
|
|
4
|
+
}
|
|
5
|
+
export declare function renderHtmlPreview(content: string, mode: HtmlPreviewMode, options?: HtmlRenderOptions): {
|
|
6
|
+
html: string;
|
|
7
|
+
notice?: string;
|
|
8
|
+
};
|