@hienlh/ppm 0.22.11 → 0.23.1
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/CHANGELOG.md +24 -1
- package/CLAUDE.md +14 -0
- package/THIRD-PARTY-NOTICES.md +1 -1
- package/assets/skills/ppm/SKILL.md +1 -1
- package/assets/skills/ppm/references/http-api.md +1 -1
- package/bun.lock +17 -0
- package/dist/web/assets/__vite-browser-external-CHpXvvmW.js +1 -0
- package/dist/web/assets/accounts-settings-section-BR7t8CEk.js +1 -0
- package/dist/web/assets/ai-resource-editor-BFVg2d2a.js +1 -0
- package/dist/web/assets/ai-settings-section-BJw7E_lM.js +1 -0
- package/dist/web/assets/ai-settings-section-CO-i3ghA.js +1 -0
- package/dist/web/assets/angular-html-D-rbk4zq.js +1 -0
- package/dist/web/assets/angular-ts-B_ldKah2.js +1 -0
- package/dist/web/assets/api-client-BgedDTvo.js +1 -0
- package/dist/web/assets/api-client-c8YOpTlT.js +1 -0
- package/dist/web/assets/api-settings-0s1Rfgcu.js +1 -0
- package/dist/web/assets/api-settings-Bnp28Ysw.js +1 -0
- package/dist/web/assets/api-themes-Pp-AZvwV.js +1 -0
- package/dist/web/assets/apl-19Dr02g6.js +1 -0
- package/dist/web/assets/appearance-settings-section-Ck_FPs9g.js +1 -0
- package/dist/web/assets/architecture-PBZL5I3N-B_n8ddB4.js +1 -0
- package/dist/web/assets/astro-1q5o0N64.js +1 -0
- package/dist/web/assets/audio-preview-DXtE1Lpz.js +1 -0
- package/dist/web/assets/blade-BNgXZCCk.js +1 -0
- package/dist/web/assets/branch-review-tab-CNVxMRuo.js +1 -0
- package/dist/web/assets/bsl-C5u8-gEq.js +1 -0
- package/dist/web/assets/button-CBehaXpV.js +1 -0
- package/dist/web/assets/c-Dko4ZphN.js +1 -0
- package/dist/web/assets/cairo-CrhmfCJH.js +1 -0
- package/dist/web/assets/chat-tab-DqLqcBci.js +1 -0
- package/dist/web/assets/chat-tab-MdU9Jr3F.js +15 -0
- package/dist/web/assets/cobol-BgRxrYyZ.js +1 -0
- package/dist/web/assets/code-editor-wEeCvvMR.js +7 -0
- package/dist/web/assets/codex-daily-guard-B21M4m-P.js +1 -0
- package/dist/web/assets/coffee-9hmEOIYs.js +1 -0
- package/dist/web/assets/conflict-editor-Cu-z_LdX.js +19 -0
- package/dist/web/assets/context-menu-CjYTq8DI.js +1 -0
- package/dist/web/assets/cpp-BntsLe3X.js +1 -0
- package/dist/web/assets/createLucideIcon-DBXq3G0e.js +1 -0
- package/dist/web/assets/crystal-CoXN2Gj8.js +1 -0
- package/dist/web/assets/css-DKuKlxIj.js +1 -0
- package/dist/web/assets/csv-preview-DHbBIqUu.js +2 -0
- package/dist/web/assets/data-grid-overlay-editor-2ERlh7_N.js +1 -0
- package/dist/web/assets/data-grid-types-DatI2Wee.js +1 -0
- package/dist/web/assets/database-viewer-_McYjRzc.js +1 -0
- package/dist/web/assets/design-export-client-SWCbGwwU.js +1 -0
- package/dist/web/assets/design-responsive-dialog-CcJETHO2.js +1 -0
- package/dist/web/assets/design-tab-C0TUD5g-.js +33 -0
- package/dist/web/assets/designs-sidebar-panel-XCAwSNtg.js +1 -0
- package/dist/web/assets/dialog-tzBRkGeW.js +1 -0
- package/dist/web/assets/diff-viewer-C4z-_68x.js +4 -0
- package/dist/web/assets/dist-CgtN5c7X.js +1 -0
- package/dist/web/assets/dist-wmDsBD_Z.js +1 -0
- package/dist/web/assets/docx-preview-C-UKGMXR.js +12 -0
- package/dist/web/assets/edge-gf7weBFr.js +1 -0
- package/dist/web/assets/edit-diff-preview-8nIct7kS.js +7 -0
- package/dist/web/assets/editor-language-service-D8hW_eew.js +1 -0
- package/dist/web/assets/elixir-DOEwBYus.js +1 -0
- package/dist/web/assets/elm-7yx1A5qt.js +1 -0
- package/dist/web/assets/erb-Bm_J_rBw.js +1 -0
- package/dist/web/assets/erlang-DgkAVj5y.js +1 -0
- package/dist/web/assets/esm-wquH4IhX.js +2 -0
- package/dist/web/assets/explorer-body-CdxolRQG.js +2 -0
- package/dist/web/assets/explorer-window-content-D1fkI_cL.js +1 -0
- package/dist/web/assets/extension-manager-section-CAaSoAuG.js +1 -0
- package/dist/web/assets/extension-webview-DmBZun_i.js +12 -0
- package/dist/web/assets/file-icons-BlOxPo3P.js +1 -0
- package/dist/web/assets/file-store-CTlJqj2m.js +1 -0
- package/dist/web/assets/files-settings-section-BFIzSuBh.js +1 -0
- package/dist/web/assets/format-date-BMtvCeb9.js +1 -0
- package/dist/web/assets/format-file-meta-DLaHgkdx.js +1 -0
- package/dist/web/assets/fortran-fixed-form-s8lQifxM.js +1 -0
- package/dist/web/assets/fs-api-RVc5RtTA.js +1 -0
- package/dist/web/assets/fsharp-D6bmDjka.js +1 -0
- package/dist/web/assets/gdresource-wPII3GWW.js +1 -0
- package/dist/web/assets/general-settings-section-BLLUvdhX.js +1 -0
- package/dist/web/assets/git-commit-DqLhxK6K.js +1 -0
- package/dist/web/assets/git-log-panel-Lq2Vkm8w.js +1 -0
- package/dist/web/assets/git-rebase-Cy0Mp9W1.js +1 -0
- package/dist/web/assets/git-repo-store-DFTJ5ngK.js +1 -0
- package/dist/web/assets/gitGraph-HDMCJU4V-w1WApLyy.js +1 -0
- package/dist/web/assets/glide-data-grid-CHdKFqis.js +141 -0
- package/dist/web/assets/glimmer-js-CmHFqq4N.js +1 -0
- package/dist/web/assets/glimmer-ts-vLmZC1JJ.js +1 -0
- package/dist/web/assets/glsl-DArPh0ws.js +1 -0
- package/dist/web/assets/graphql-B-_Ilekp.js +1 -0
- package/dist/web/assets/group-chat-tab-D2bluLme.js +1 -0
- package/dist/web/assets/hack-4KVRpwwM.js +1 -0
- package/dist/web/assets/haml-DoK94C5G.js +1 -0
- package/dist/web/assets/handlebars-D0_6yNlK.js +1 -0
- package/dist/web/assets/html-BOqZwhzR.js +1 -0
- package/dist/web/assets/html-derivative-If_2xbJ8.js +1 -0
- package/dist/web/assets/http-B6pQhqN4.js +1 -0
- package/dist/web/assets/hurl-BjW79rql.js +1 -0
- package/dist/web/assets/hxml-B1Yl76u6.js +1 -0
- package/dist/web/assets/icons-CO_II6D-.js +1 -0
- package/dist/web/assets/image-preview-78Fguk1f.js +1 -0
- package/dist/web/assets/index-CzYrKDUF.css +1 -0
- package/dist/web/assets/index-DSbUqWiH.js +52 -0
- package/dist/web/assets/info-3K5VOQVL-Bv1wKdPY.js +1 -0
- package/dist/web/assets/input-CP31LZnN.js +1 -0
- package/dist/web/assets/java-DPqGHyuh.js +1 -0
- package/dist/web/assets/javascript-D8x_R8ev.js +1 -0
- package/dist/web/assets/jinja-DOkXV84k.js +1 -0
- package/dist/web/assets/jira-watcher-section-BOe_ztas.js +1 -0
- package/dist/web/assets/jison-CGzlyBWT.js +1 -0
- package/dist/web/assets/json-kcFjaEWA.js +1 -0
- package/dist/web/assets/jsx-BzlJCumN.js +1 -0
- package/dist/web/assets/julia-CZrbm1Fa.js +1 -0
- package/dist/web/assets/just-bRG6zWI_.js +1 -0
- package/dist/web/assets/keybindings-store-DFPJBiXT.js +1 -0
- package/dist/web/assets/keyboard-shortcuts-section-CJubMhMq.js +1 -0
- package/dist/web/assets/latex-CZHLEkde.js +1 -0
- package/dist/web/assets/lib-KePrAxj7.js +4 -0
- package/dist/web/assets/liquid-Dcfq3Ccc.js +1 -0
- package/dist/web/assets/lua-Ggfu9EYp.js +1 -0
- package/dist/web/assets/markdown-renderer-6oU-L6RN.js +5 -0
- package/dist/web/assets/markdown-renderer-DxSQ4aqW.js +1 -0
- package/dist/web/assets/marko-BUwN_Iax.js +1 -0
- package/dist/web/assets/mdc-CIifdeNY.js +1 -0
- package/dist/web/assets/media-url-GqzhazJS.js +1 -0
- package/dist/web/assets/mobile-bottom-sheet-Cf4kV1hS.js +1 -0
- package/dist/web/assets/mobile-explorer-sheet-D0968cuP.js +1 -0
- package/dist/web/assets/monaco-dotenv-language-COsgiuQg.js +1 -0
- package/dist/web/assets/new-chat-provider-CJx_waY3.js +1 -0
- package/dist/web/assets/new-design-dialog-CbrMbKum.js +1 -0
- package/dist/web/assets/nextflow-DufnRZW1.js +1 -0
- package/dist/web/assets/nginx-DtUJGfad.js +1 -0
- package/dist/web/assets/nim-BeBPwibr.js +1 -0
- package/dist/web/assets/notification-store-BO3RInEL.js +1 -0
- package/dist/web/assets/notifications-settings-section-Bfxqz65i.js +1 -0
- package/dist/web/assets/number-overlay-editor-xzM7GhYV.js +9 -0
- package/dist/web/assets/onboarding-entry-CcvySZ_l.js +1 -0
- package/dist/web/assets/onboarding-quick-orientation-CT4PylG0.js +1 -0
- package/dist/web/assets/overview-panel-DshAIz6C.js +1 -0
- package/dist/web/assets/packet-RMMSAZCW-Scl5HE6U.js +1 -0
- package/dist/web/assets/panel-store-BUQ-CPsd.js +1 -0
- package/dist/web/assets/pdf-preview-BWim6mu1.js +1 -0
- package/dist/web/assets/perl-hV0EoLCp.js +1 -0
- package/dist/web/assets/php-N1YBqBhK.js +1 -0
- package/dist/web/assets/pie-UPGHQEXC-sY83O9qJ.js +1 -0
- package/dist/web/assets/portal-container-context-NFSuymMu.js +1 -0
- package/dist/web/assets/postgres-viewer-HwlL1UTJ.js +3 -0
- package/dist/web/assets/ppmbot-settings-section-CHr2FIDj.js +1 -0
- package/dist/web/assets/pptx-export-D6DOknBD.js +111 -0
- package/dist/web/assets/problems-panel-41z59l78.js +1 -0
- package/dist/web/assets/process-table-CVMEMJqQ.js +1 -0
- package/dist/web/assets/project-framework-store-XxFXcUpb.js +1 -0
- package/dist/web/assets/project-store-C5gJXkvb.js +1 -0
- package/dist/web/assets/proxy-settings-section-B4dkvCCx.js +1 -0
- package/dist/web/assets/pug-IMA1knL7.js +1 -0
- package/dist/web/assets/qml-DuwVuXga.js +1 -0
- package/dist/web/assets/query-audit-section-Cn11xqgz.js +1 -0
- package/dist/web/assets/r-DsXT2lmn.js +1 -0
- package/dist/web/assets/radar-KQ55EAFF-CNhm_kzj.js +1 -0
- package/dist/web/assets/razor-Be4LE-G0.js +1 -0
- package/dist/web/assets/react-CzUPVyyG.js +1 -0
- package/dist/web/assets/regexp-ztLDvplH.js +1 -0
- package/dist/web/assets/remote-desktop-clipboard-notice-Co4vEiiB.js +1 -0
- package/dist/web/assets/remote-desktop-mobile-sheet-Cv4yo7K4.js +2 -0
- package/dist/web/assets/remote-desktop-mobile-view-CcuulHIu.js +1 -0
- package/dist/web/assets/remote-desktop-readiness-gate-ouPRvBlu.js +1 -0
- package/dist/web/assets/remote-desktop-window-content-DmH3jBuG.js +1 -0
- package/dist/web/assets/rolldown-runtime-C5c2KzVm.js +1 -0
- package/dist/web/assets/rst-BdtOZUlL.js +1 -0
- package/dist/web/assets/ruby-DTna6e9n.js +1 -0
- package/dist/web/assets/run-in-terminal-SU9cwoZ4.js +1 -0
- package/dist/web/assets/sas-X50YKLBX.js +1 -0
- package/dist/web/assets/schedules-settings-section-Dy6hARk0.js +1 -0
- package/dist/web/assets/scroll-area-xAtds1T-.js +1 -0
- package/dist/web/assets/scss-cQk9zuqD.js +1 -0
- package/dist/web/assets/send-to-chat-TSKk3fI9.js +1 -0
- package/dist/web/assets/separator-D8SNZI6E.js +1 -0
- package/dist/web/assets/settings-body-CZSwxG0i.js +2 -0
- package/dist/web/assets/settings-store-DXmQug0m.js +2 -0
- package/dist/web/assets/settings-tab-B_WPC-y7.js +1 -0
- package/dist/web/assets/settings-window-content-CSWdwQn1.js +1 -0
- package/dist/web/assets/shaderlab-CSeOcwk6.js +1 -0
- package/dist/web/assets/shellscript-Dtzjnpp9.js +1 -0
- package/dist/web/assets/shellsession-AqADqsjv.js +1 -0
- package/dist/web/assets/soy-DeMex-y3.js +1 -0
- package/dist/web/assets/sparql-CDZTYDwx.js +1 -0
- package/dist/web/assets/sql-BS_vTOM8.js +1 -0
- package/dist/web/assets/sql-query-editor-6Ee_Zn5j.js +1 -0
- package/dist/web/assets/sqlite-viewer-Cj0S_m9V.js +1 -0
- package/dist/web/assets/stata-PkjbLwNy.js +1 -0
- package/dist/web/assets/surrealql-BJ6bKPXV.js +1 -0
- package/dist/web/assets/svelte-D4u1sGpe.js +1 -0
- package/dist/web/assets/system-monitor-body-PQqXdK4a.js +2 -0
- package/dist/web/assets/system-monitor-tab-BEjvgQuQ.js +1 -0
- package/dist/web/assets/system-monitor-window-content-DZwvvN-M.js +1 -0
- package/dist/web/assets/tab-host-window-content-CnV4Z4Yt.js +1 -0
- package/dist/web/assets/tab-store-DqeaGhhE.js +1 -0
- package/dist/web/assets/team-member-sheet-8EVCTM-X.js +2 -0
- package/dist/web/assets/team-member-window-content-Bc0ydBAn.js +1 -0
- package/dist/web/assets/templ-vtFoIgGG.js +1 -0
- package/dist/web/assets/terminal-tab-0b63-txz.js +3 -0
- package/dist/web/assets/tex-o6JLe3Qo.js +1 -0
- package/dist/web/assets/tool-cards-C09WknHl.js +9 -0
- package/dist/web/assets/treemap-KZPCXAKY-CfpX4ULx.js +1 -0
- package/dist/web/assets/ts-tags-DkmPnhIx.js +1 -0
- package/dist/web/assets/tsx-BUq9xm2T.js +1 -0
- package/dist/web/assets/twig-I9ja_Rk_.js +1 -0
- package/dist/web/assets/typescript-CP3RLBKz.js +1 -0
- package/dist/web/assets/use-blob-url-mZfScQdx.js +1 -0
- package/dist/web/assets/use-inline-blame-BuAc9IXE.js +16 -0
- package/dist/web/assets/use-is-mobile-CkO33jqU.js +1 -0
- package/dist/web/assets/use-lsp-DAtq1G0M.js +6 -0
- package/dist/web/assets/use-monaco-theme-Ch_znquJ.js +1 -0
- package/dist/web/assets/use-open-team-member-DHzZiJZw.js +1 -0
- package/dist/web/assets/use-visual-viewport-C307OVeV.js +1 -0
- package/dist/web/assets/use-websocket-DGEOad8p.js +1 -0
- package/dist/web/assets/vendor-markdown-QKPNiWEd.js +291 -0
- package/dist/web/assets/vendor-mermaid-eg2XWIjK.js +2921 -0
- package/dist/web/assets/vendor-ui-BHh12_0v.js +45 -0
- package/dist/web/assets/video-preview-DH3RtwVT.js +1 -0
- package/dist/web/assets/vue-DJf-APPD.js +1 -0
- package/dist/web/assets/vue-html-DUJ89Ycn.js +1 -0
- package/dist/web/assets/vue-vine-CWUFwuRE.js +1 -0
- package/dist/web/assets/window-pip-registry-DH07f_8k.js +1 -0
- package/dist/web/assets/window-store-B4cbZ5rr.js +1 -0
- package/dist/web/assets/ws-auth-B_y5rMfZ.js +1 -0
- package/dist/web/assets/xml-DshhaDKq.js +1 -0
- package/dist/web/assets/xsl-BlRNlmF7.js +1 -0
- package/dist/web/assets/yaml-seUOGdyI.js +1 -0
- package/dist/web/index.html +37 -36
- package/dist/web/sw.js +1 -1
- package/docs/architecture/workspace-and-ui.md +47 -0
- package/docs/project-roadmap.md +16 -0
- package/docs/system-architecture.md +11 -1
- package/package.json +4 -1
- package/scripts/gen-product-icons.ts +10 -0
- package/src/providers/claude-agent-sdk-query-options.ts +68 -1
- package/src/providers/claude-agent-sdk.ts +44 -15
- package/src/providers/codex-app-server/codex-event-mapper.ts +18 -1
- package/src/providers/codex-app-server/codex-jsonrpc-client.ts +4 -3
- package/src/providers/codex-app-server/codex-permission-map.ts +11 -1
- package/src/providers/codex-app-server/codex-protocol.ts +5 -0
- package/src/providers/codex-app-server/codex-provider.ts +32 -15
- package/src/providers/codex-app-server/codex-thread-params.ts +96 -0
- package/src/server/helpers/preview-asset-guard.ts +36 -0
- package/src/server/index.ts +15 -0
- package/src/server/routes/chat.ts +41 -4
- package/src/server/routes/design-check.ts +48 -0
- package/src/server/routes/design-comments.ts +63 -0
- package/src/server/routes/design-export.ts +84 -0
- package/src/server/routes/design-preview.ts +159 -0
- package/src/server/routes/design-route-helpers.ts +25 -0
- package/src/server/routes/design-style.ts +28 -0
- package/src/server/routes/design-tweaks.ts +38 -0
- package/src/server/routes/design-undo.ts +27 -0
- package/src/server/routes/designs.ts +101 -0
- package/src/server/routes/html-preview.ts +4 -24
- package/src/server/routes/project-scoped.ts +2 -0
- package/src/server/ws/chat.ts +8 -1
- package/src/server/ws/global.ts +22 -1
- package/src/services/chat.service.ts +64 -1
- package/src/services/db.service.ts +73 -4
- package/src/services/design/bridge/bridge-anchor-resolve.ts +96 -0
- package/src/services/design/bridge/bridge-core.ts +205 -0
- package/src/services/design/bridge/bridge-element-info.ts +180 -0
- package/src/services/design/bridge/bridge-extract-blocks.ts +115 -0
- package/src/services/design/bridge/bridge-extract-images.ts +96 -0
- package/src/services/design/bridge/bridge-extract-slides.ts +169 -0
- package/src/services/design/bridge/bridge-extract-text.ts +187 -0
- package/src/services/design/bridge/bridge-layout-boxes.ts +137 -0
- package/src/services/design/bridge/bridge-layout-check.ts +99 -0
- package/src/services/design/bridge/bridge-layout-grid.ts +165 -0
- package/src/services/design/bridge/bridge-layout-screenshot.ts +106 -0
- package/src/services/design/bridge/bridge-nav-guard.ts +61 -0
- package/src/services/design/bridge/bridge-picker-overlay.ts +54 -0
- package/src/services/design/bridge/bridge-picker.ts +174 -0
- package/src/services/design/bridge/bridge-pins.ts +157 -0
- package/src/services/design/bridge/bridge-script.ts +104 -0
- package/src/services/design/bridge/bridge-transform-math.ts +104 -0
- package/src/services/design/bridge/bridge-transform-overlay.ts +94 -0
- package/src/services/design/bridge/bridge-transform-style.ts +78 -0
- package/src/services/design/bridge/bridge-transform.ts +201 -0
- package/src/services/design/bridge/bridge-tweaks.ts +118 -0
- package/src/services/design/check/design-canvas-check-broker.ts +77 -0
- package/src/services/design/comments/design-comment-element-context.ts +81 -0
- package/src/services/design/comments/design-comments-store.ts +81 -0
- package/src/services/design/design-comments.service.ts +140 -0
- package/src/services/design/design-edit-undo-journal.ts +125 -0
- package/src/services/design/design-error.ts +19 -0
- package/src/services/design/design-events.ts +46 -0
- package/src/services/design/design-fs.ts +67 -0
- package/src/services/design/design-instructions.ts +97 -0
- package/src/services/design/design-lock.ts +74 -0
- package/src/services/design/design-manifest.ts +92 -0
- package/src/services/design/design-paths.ts +97 -0
- package/src/services/design/design-restore-journal.ts +143 -0
- package/src/services/design/design-restore.service.ts +77 -0
- package/src/services/design/design-safe-walk.ts +114 -0
- package/src/services/design/design-slug.ts +35 -0
- package/src/services/design/design-snapshot-history.ts +159 -0
- package/src/services/design/design-snapshots.service.ts +161 -0
- package/src/services/design/design-starter-template.ts +100 -0
- package/src/services/design/design-store.service.ts +156 -0
- package/src/services/design/design-style-patch.service.ts +83 -0
- package/src/services/design/design-tool-policy.ts +111 -0
- package/src/services/design/design-turn-snapshot.ts +80 -0
- package/src/services/design/design-tweaks-commit.service.ts +138 -0
- package/src/services/design/design-write-rate-limit.ts +51 -0
- package/src/services/design/export/css-url-inline.ts +130 -0
- package/src/services/design/export/design-export-asset-reader.ts +57 -0
- package/src/services/design/export/design-export-entry.ts +33 -0
- package/src/services/design/export/design-standalone-html.ts +167 -0
- package/src/services/design/export/design-zip-export.ts +106 -0
- package/src/services/design/mcp/design-mcp-access.ts +16 -0
- package/src/services/design/mcp/design-mcp-endpoint.ts +118 -0
- package/src/services/design/mcp/design-mcp-tokens.ts +82 -0
- package/src/services/design/mcp/design-mcp-tool.ts +41 -0
- package/src/services/design/preview/design-csp.ts +31 -0
- package/src/services/design/preview/design-preview-html.ts +98 -0
- package/src/services/design/preview/design-preview-scope.ts +66 -0
- package/src/services/design/preview/design-preview-tokens.ts +137 -0
- package/src/services/design/preview/expired-page.ts +30 -0
- package/src/services/design/preview/html-instrument.ts +119 -0
- package/src/services/design/preview/print-view.ts +62 -0
- package/src/services/design/source/css-root-selector.ts +20 -0
- package/src/services/design/source/css-root-vars-patch.ts +202 -0
- package/src/services/design/source/design-source-file.ts +62 -0
- package/src/services/design/source/design-style-sources.ts +101 -0
- package/src/services/design/source/element-source-range.ts +65 -0
- package/src/services/design/source/html-style-blocks.ts +87 -0
- package/src/services/design/source/inline-style-declarations.ts +131 -0
- package/src/services/design/source/inline-style-patch.ts +79 -0
- package/src/services/design/source/tweak-patch-plan.ts +143 -0
- package/src/services/file-watcher/ignore-rules.ts +9 -1
- package/src/services/server-listen-address.ts +25 -0
- package/src/shared/design-bridge-messages-check.ts +44 -0
- package/src/shared/design-bridge-messages-picker.ts +142 -0
- package/src/shared/design-bridge-messages-slides.ts +37 -0
- package/src/shared/design-bridge-messages-transform.ts +121 -0
- package/src/shared/design-bridge-messages-tweaks.ts +65 -0
- package/src/shared/design-bridge-protocol.ts +158 -0
- package/src/shared/design-canvas-check-format.ts +69 -0
- package/src/shared/design-canvas-check.ts +148 -0
- package/src/shared/design-cdn-hosts.ts +17 -0
- package/src/shared/design-comment-types.ts +111 -0
- package/src/shared/design-slide-doc-parse.ts +140 -0
- package/src/shared/design-slide-doc.ts +91 -0
- package/src/shared/design-system-init-prompt.ts +35 -0
- package/src/shared/design-tweaks.ts +175 -0
- package/src/shared/design-types.ts +63 -0
- package/src/shared/untrusted-text.ts +15 -0
- package/src/types/chat.ts +22 -0
- package/src/types/config.ts +1 -1
- package/src/web/components/chat/chat-history-bar.tsx +18 -15
- package/src/web/components/chat/chat-history-panel.tsx +3 -9
- package/src/web/components/chat/chat-tab.tsx +74 -40
- package/src/web/components/chat/message-input.tsx +11 -4
- package/src/web/components/chat/session-history-list.tsx +5 -9
- package/src/web/components/design/canvas/canvas-geometry.ts +47 -0
- package/src/web/components/design/canvas/design-canvas-pane.tsx +192 -0
- package/src/web/components/design/canvas/design-issues-badge.tsx +71 -0
- package/src/web/components/design/canvas/device-frame-presets.ts +37 -0
- package/src/web/components/design/canvas/use-design-bridge.ts +169 -0
- package/src/web/components/design/canvas/use-design-canvas-check.ts +110 -0
- package/src/web/components/design/canvas/use-design-canvas.ts +107 -0
- package/src/web/components/design/canvas/use-design-live-reload.ts +86 -0
- package/src/web/components/design/canvas/use-design-preview-url.ts +74 -0
- package/src/web/components/design/canvas/use-expanded-canvas-escape.ts +29 -0
- package/src/web/components/design/comments/comment-composer.tsx +107 -0
- package/src/web/components/design/comments/comment-overlay-geometry.ts +50 -0
- package/src/web/components/design/comments/comment-pins-overlay.tsx +70 -0
- package/src/web/components/design/comments/comments-panel.tsx +118 -0
- package/src/web/components/design/comments/comments-send-preview.tsx +43 -0
- package/src/web/components/design/comments/design-comments-layer.tsx +73 -0
- package/src/web/components/design/comments/element-action-bar.tsx +105 -0
- package/src/web/components/design/comments/use-comment-pins.ts +118 -0
- package/src/web/components/design/comments/use-design-comments-feature.ts +124 -0
- package/src/web/components/design/comments/use-design-comments.ts +89 -0
- package/src/web/components/design/comments/use-element-picker.ts +87 -0
- package/src/web/components/design/design-chat-pane.tsx +51 -0
- package/src/web/components/design/design-layout-controls.tsx +84 -0
- package/src/web/components/design/design-mobile-layout.tsx +34 -0
- package/src/web/components/design/design-split-layout.tsx +99 -0
- package/src/web/components/design/design-tab-context.ts +44 -0
- package/src/web/components/design/design-tab.tsx +116 -0
- package/src/web/components/design/design-toolbar-list.tsx +36 -0
- package/src/web/components/design/design-toolbar.tsx +200 -0
- package/src/web/components/design/designs-sidebar-panel.tsx +117 -0
- package/src/web/components/design/dialogs/delete-design-dialog.tsx +69 -0
- package/src/web/components/design/dialogs/design-responsive-dialog.tsx +48 -0
- package/src/web/components/design/dialogs/new-design-dialog.tsx +113 -0
- package/src/web/components/design/dialogs/rename-design-dialog.tsx +56 -0
- package/src/web/components/design/export/export-menu.tsx +108 -0
- package/src/web/components/design/export/export-warnings-sheet.tsx +35 -0
- package/src/web/components/design/export/pptx-export.ts +38 -0
- package/src/web/components/design/export/use-design-export.ts +142 -0
- package/src/web/components/design/history/design-history-panel.tsx +119 -0
- package/src/web/components/design/transform/design-undo-stack.ts +90 -0
- package/src/web/components/design/transform/transform-readout.tsx +50 -0
- package/src/web/components/design/transform/use-canvas-transform.ts +181 -0
- package/src/web/components/design/tweaks/tweak-control.tsx +94 -0
- package/src/web/components/design/tweaks/tweaks-panel.tsx +99 -0
- package/src/web/components/design/tweaks/use-design-tweaks.ts +151 -0
- package/src/web/components/design/use-design-auto-check.ts +94 -0
- package/src/web/components/design/use-design-layout.ts +55 -0
- package/src/web/components/design/use-design-summary.ts +63 -0
- package/src/web/components/layout/command-palette-design-commands.tsx +75 -0
- package/src/web/components/layout/command-palette.tsx +12 -4
- package/src/web/components/layout/editor-panel.tsx +4 -10
- package/src/web/components/layout/mobile-drawer.tsx +9 -2
- package/src/web/components/layout/mobile-nav.tsx +3 -2
- package/src/web/components/layout/mobile-tab-switcher-sheet.tsx +4 -5
- package/src/web/components/layout/sidebar.tsx +8 -1
- package/src/web/components/layout/tab-bar.tsx +3 -2
- package/src/web/components/layout/tab-content.tsx +5 -0
- package/src/web/components/layout/tab-pool.tsx +1 -0
- package/src/web/components/onboarding/onboarding-quick-orientation.tsx +1 -0
- package/src/web/hooks/use-chat.ts +8 -4
- package/src/web/hooks/use-design-session-redirect.ts +39 -0
- package/src/web/hooks/use-design-session-state.ts +94 -0
- package/src/web/hooks/use-global-events.ts +4 -1
- package/src/web/hooks/use-session-history.ts +4 -10
- package/src/web/hooks/use-url-sync.ts +10 -2
- package/src/web/lib/design/api-design-comments.ts +42 -0
- package/src/web/lib/design/api-design-edits.ts +62 -0
- package/src/web/lib/design/api-design-tweaks.ts +64 -0
- package/src/web/lib/design/api-designs.ts +81 -0
- package/src/web/lib/design/deliver-to-design-chat.ts +63 -0
- package/src/web/lib/design/design-auto-check-rounds.ts +32 -0
- package/src/web/lib/design/design-change-filter.ts +27 -0
- package/src/web/lib/design/design-comments-prompt.ts +55 -0
- package/src/web/lib/design/design-export-client.ts +101 -0
- package/src/web/lib/design/design-handoff-prompt.ts +48 -0
- package/src/web/lib/design/design-layout-mode.ts +79 -0
- package/src/web/lib/design/design-tab-metadata.ts +41 -0
- package/src/web/lib/design/design-transform-proposal.ts +62 -0
- package/src/web/lib/design/design-tweaks-model.ts +76 -0
- package/src/web/lib/design/design-ui-events.ts +25 -0
- package/src/web/lib/design/design-view-prefs.ts +90 -0
- package/src/web/lib/design/open-design-tab.ts +78 -0
- package/src/web/lib/design/pptx-slide-mapper.ts +118 -0
- package/src/web/lib/feature-badges.ts +2 -0
- package/src/web/lib/fluent-icon.tsx +38 -2
- package/src/web/lib/icons.generated.tsx +17 -1
- package/src/web/lib/patch-tab-metadata.ts +30 -0
- package/src/web/lib/send-to-chat.ts +16 -2
- package/src/web/lib/sidebar-tabs/tab-registry.ts +2 -0
- package/src/web/lib/tab-session-id.ts +16 -0
- package/src/web/lib/tab-type-icons.ts +2 -1
- package/src/web/stores/panel-store.ts +29 -1
- package/src/web/stores/panel-utils.ts +8 -1
- package/src/web/stores/settings-store.ts +2 -2
- package/src/web/stores/tab-store.ts +2 -1
- package/src/web/stores/window-panel-persistence.ts +1 -0
- package/dist/web/assets/accounts-settings-section-BDXYG6tT.js +0 -1
- package/dist/web/assets/ai-resource-editor-C3rKcZKN.js +0 -1
- package/dist/web/assets/ai-settings-section-ArqD8Nlg.js +0 -1
- package/dist/web/assets/ai-settings-section-DeWoAdLc.js +0 -1
- package/dist/web/assets/angular-html-DnrsWZqK.js +0 -1
- package/dist/web/assets/angular-ts-BXEqA9t1.js +0 -1
- package/dist/web/assets/api-client-Jn3njtNw.js +0 -1
- package/dist/web/assets/api-client-rSFnnCj4.js +0 -1
- package/dist/web/assets/api-settings-BZFSteM_.js +0 -1
- package/dist/web/assets/api-themes-CvKtX6Hd.js +0 -1
- package/dist/web/assets/apl-DUQ6Oyth.js +0 -1
- package/dist/web/assets/appearance-settings-section-K5o_Di4V.js +0 -1
- package/dist/web/assets/architecture-PBZL5I3N-B9M_VqZI.js +0 -1
- package/dist/web/assets/astro-CakOjJ6X.js +0 -1
- package/dist/web/assets/audio-preview-CwCDCN-_.js +0 -1
- package/dist/web/assets/blade-C903KM82.js +0 -1
- package/dist/web/assets/branch-review-tab-BNpYiUhC.js +0 -1
- package/dist/web/assets/bsl-slfcE_kB.js +0 -1
- package/dist/web/assets/button-B9CTrsEf.js +0 -1
- package/dist/web/assets/c-BWO-aeyf.js +0 -1
- package/dist/web/assets/cairo-DRwEaH6w.js +0 -1
- package/dist/web/assets/chat-tab-CC8KANoK.js +0 -15
- package/dist/web/assets/cobol--n4m6b70.js +0 -1
- package/dist/web/assets/code-editor-Ccf0Egrc.js +0 -7
- package/dist/web/assets/codex-daily-guard-CKk2WFlV.js +0 -1
- package/dist/web/assets/coffee-CjyFmw8_.js +0 -1
- package/dist/web/assets/conflict-editor-BCKbdpXy.js +0 -19
- package/dist/web/assets/context-menu-C6pIsf83.js +0 -1
- package/dist/web/assets/cpp-D18jdQPZ.js +0 -1
- package/dist/web/assets/createLucideIcon-DoiEKeJ_.js +0 -1
- package/dist/web/assets/crystal-CySzfH-7.js +0 -1
- package/dist/web/assets/css-Ca_hTmU6.js +0 -1
- package/dist/web/assets/csv-preview-I3a2lGUx.js +0 -2
- package/dist/web/assets/data-grid-overlay-editor-BD9eJweQ.js +0 -1
- package/dist/web/assets/data-grid-types-C6UX8kgh.js +0 -1
- package/dist/web/assets/database-viewer-DCuBR-bZ.js +0 -1
- package/dist/web/assets/dialog-B84_DJQ8.js +0 -1
- package/dist/web/assets/diff-viewer-DGaBe_Ln.js +0 -4
- package/dist/web/assets/dist-BD2gbdy0.js +0 -1
- package/dist/web/assets/docx-preview-CeH6p2Oi.js +0 -12
- package/dist/web/assets/edge-B6b5FHmU.js +0 -1
- package/dist/web/assets/edit-diff-preview-BG5DsLJG.js +0 -7
- package/dist/web/assets/editor-language-service-BaocEaLc.js +0 -1
- package/dist/web/assets/elixir-Dpo1rvn2.js +0 -1
- package/dist/web/assets/elm-D9CNOsWT.js +0 -1
- package/dist/web/assets/erb-sY7Yee1W.js +0 -1
- package/dist/web/assets/erlang-CfyrBxyF.js +0 -1
- package/dist/web/assets/esm-5AhGJcV8.js +0 -2
- package/dist/web/assets/explorer-body-2GYIYmUh.js +0 -2
- package/dist/web/assets/explorer-window-content-CYQSEX-g.js +0 -1
- package/dist/web/assets/extension-manager-section-BFAGdy3G.js +0 -1
- package/dist/web/assets/extension-webview-D5TXIBMf.js +0 -12
- package/dist/web/assets/file-icons-wS-OmEVu.js +0 -1
- package/dist/web/assets/file-store-Ds3qJ4hC.js +0 -1
- package/dist/web/assets/files-settings-section-BE6o-oHu.js +0 -1
- package/dist/web/assets/format-file-meta-eKLstbCL.js +0 -1
- package/dist/web/assets/fortran-fixed-form-N67gM_wp.js +0 -1
- package/dist/web/assets/fs-api-orca76dV.js +0 -1
- package/dist/web/assets/fsharp-Dq0K01wX.js +0 -1
- package/dist/web/assets/gdresource-DkFbszqY.js +0 -1
- package/dist/web/assets/general-settings-section-mQiXM537.js +0 -1
- package/dist/web/assets/git-commit-Ddt_nerD.js +0 -1
- package/dist/web/assets/git-log-panel-DqbcM9eC.js +0 -1
- package/dist/web/assets/git-rebase-CVK5OA7i.js +0 -1
- package/dist/web/assets/git-repo-store-BCEPfUGT.js +0 -1
- package/dist/web/assets/gitGraph-HDMCJU4V-D3RB33aA.js +0 -1
- package/dist/web/assets/glide-data-grid-BjEF7M5i.js +0 -141
- package/dist/web/assets/glimmer-js-51jbYnyY.js +0 -1
- package/dist/web/assets/glimmer-ts-C5L1J32J.js +0 -1
- package/dist/web/assets/glsl-BcsfmwJZ.js +0 -1
- package/dist/web/assets/graphql-dv4wuJsK.js +0 -1
- package/dist/web/assets/group-chat-tab-aX2GEnkD.js +0 -1
- package/dist/web/assets/hack-DLE5d3bx.js +0 -1
- package/dist/web/assets/haml-CoKfcM3E.js +0 -1
- package/dist/web/assets/handlebars-Bn0jy8pD.js +0 -1
- package/dist/web/assets/html-DXzY5Cew.js +0 -1
- package/dist/web/assets/html-derivative-DhcVfYuw.js +0 -1
- package/dist/web/assets/http-DepeIWQ1.js +0 -1
- package/dist/web/assets/hurl-CfsP4sCj.js +0 -1
- package/dist/web/assets/hxml-IfVkY3HL.js +0 -1
- package/dist/web/assets/icons-DQjqk0lJ.js +0 -1
- package/dist/web/assets/image-preview-CWncz5iI.js +0 -1
- package/dist/web/assets/index-BoaecXhu.js +0 -52
- package/dist/web/assets/index-aXJy_SvC.css +0 -1
- package/dist/web/assets/info-3K5VOQVL-DDX-2VB7.js +0 -1
- package/dist/web/assets/input-QNG_gTHh.js +0 -1
- package/dist/web/assets/java-JWdrzVo8.js +0 -1
- package/dist/web/assets/javascript-5aQKJRxB.js +0 -1
- package/dist/web/assets/jinja-DcCmNDQ8.js +0 -1
- package/dist/web/assets/jira-watcher-section-BKn3A8zI.js +0 -1
- package/dist/web/assets/jison-Bt-5cKVZ.js +0 -1
- package/dist/web/assets/json-BOq7QblK.js +0 -1
- package/dist/web/assets/jsx-BSLWViGE.js +0 -1
- package/dist/web/assets/julia-DewYVRtE.js +0 -1
- package/dist/web/assets/just-CLT_ggBy.js +0 -1
- package/dist/web/assets/keybindings-store-Brz0qepi.js +0 -1
- package/dist/web/assets/keyboard-shortcuts-section-Ck8KIbJ8.js +0 -1
- package/dist/web/assets/latex-DXmcayW1.js +0 -1
- package/dist/web/assets/lib-BWyA9SvU.js +0 -4
- package/dist/web/assets/liquid-BVcHf0IA.js +0 -1
- package/dist/web/assets/lua-BYupsB1B.js +0 -1
- package/dist/web/assets/markdown-renderer-BGuM2PBI.js +0 -5
- package/dist/web/assets/markdown-renderer-Ddz8tPbb.js +0 -1
- package/dist/web/assets/marko-CsD0R5tv.js +0 -1
- package/dist/web/assets/mdc-DP2tC4Kc.js +0 -1
- package/dist/web/assets/media-url-CVO4m4zr.js +0 -1
- package/dist/web/assets/mobile-bottom-sheet-C3TniEP-.js +0 -1
- package/dist/web/assets/mobile-explorer-sheet-DpKfB6iF.js +0 -1
- package/dist/web/assets/monaco-dotenv-language-DD8_UQG7.js +0 -1
- package/dist/web/assets/nextflow-FQM6iZO2.js +0 -1
- package/dist/web/assets/nginx-Bg0TK_a9.js +0 -1
- package/dist/web/assets/nim-D1kSCHdq.js +0 -1
- package/dist/web/assets/notification-store-ByCdTvCC.js +0 -1
- package/dist/web/assets/notifications-settings-section-C5v8FoH9.js +0 -1
- package/dist/web/assets/number-overlay-editor-Bsr04yCI.js +0 -9
- package/dist/web/assets/onboarding-entry-C81awoR5.js +0 -1
- package/dist/web/assets/onboarding-quick-orientation-Dqmis-E5.js +0 -1
- package/dist/web/assets/overview-panel-9OdBcYJC.js +0 -1
- package/dist/web/assets/packet-RMMSAZCW-B0ZSm6VM.js +0 -1
- package/dist/web/assets/panel-store-D20Zuf3i.js +0 -1
- package/dist/web/assets/pdf-preview-DuR07OfN.js +0 -1
- package/dist/web/assets/perl-B6QNc69s.js +0 -1
- package/dist/web/assets/php-Bvwf1t96.js +0 -1
- package/dist/web/assets/pie-UPGHQEXC-DKM0oPn7.js +0 -1
- package/dist/web/assets/portal-container-context-BarKmT4S.js +0 -1
- package/dist/web/assets/postgres-viewer-CGf7_g6Z.js +0 -3
- package/dist/web/assets/ppmbot-settings-section-DeTFU1b-.js +0 -1
- package/dist/web/assets/problems-panel-Bgkcge5_.js +0 -1
- package/dist/web/assets/process-table-DH7pnH5I.js +0 -1
- package/dist/web/assets/project-framework-store-ViZgce6y.js +0 -1
- package/dist/web/assets/project-store-hNvwfqX3.js +0 -1
- package/dist/web/assets/proxy-settings-section-DMGMRHH-.js +0 -1
- package/dist/web/assets/pug-I8oitXP4.js +0 -1
- package/dist/web/assets/qml-LKb7CHg-.js +0 -1
- package/dist/web/assets/query-audit-section-CpiXQVcS.js +0 -1
- package/dist/web/assets/r-DHu15BOo.js +0 -1
- package/dist/web/assets/radar-KQ55EAFF-DKhtzXmy.js +0 -1
- package/dist/web/assets/razor-CIPT897U.js +0 -1
- package/dist/web/assets/react-Bghu0NUO.js +0 -1
- package/dist/web/assets/regexp-Vdt2OEkk.js +0 -1
- package/dist/web/assets/remote-desktop-clipboard-notice-Bj5FtU0O.js +0 -1
- package/dist/web/assets/remote-desktop-mobile-sheet-BhwVrKxv.js +0 -2
- package/dist/web/assets/remote-desktop-mobile-view-B1oAqbjG.js +0 -1
- package/dist/web/assets/remote-desktop-readiness-gate-2LE86aTu.js +0 -1
- package/dist/web/assets/remote-desktop-window-content-u8HwuzyN.js +0 -1
- package/dist/web/assets/rolldown-runtime-FhOqtrmT.js +0 -1
- package/dist/web/assets/rst-BpcmfJFA.js +0 -1
- package/dist/web/assets/ruby-Cx413jgE.js +0 -1
- package/dist/web/assets/run-in-terminal-BFR70TLU.js +0 -1
- package/dist/web/assets/sas-B3ui_NHy.js +0 -1
- package/dist/web/assets/schedules-settings-section-C8XNDdi9.js +0 -1
- package/dist/web/assets/scroll-area-C0fQWNnx.js +0 -1
- package/dist/web/assets/scss-V4NlXnGi.js +0 -1
- package/dist/web/assets/send-to-chat-C8l7AcV4.js +0 -1
- package/dist/web/assets/separator-DwDoQpxS.js +0 -1
- package/dist/web/assets/settings-body-DelxmiKf.js +0 -2
- package/dist/web/assets/settings-store-m6qOXoy4.js +0 -2
- package/dist/web/assets/settings-tab-Cb_dFdA6.js +0 -1
- package/dist/web/assets/settings-window-content-5EQQfC1t.js +0 -1
- package/dist/web/assets/shaderlab-Cf7qZ4DR.js +0 -1
- package/dist/web/assets/shellscript-DRxJLgrx.js +0 -1
- package/dist/web/assets/shellsession-BfA8Fmhb.js +0 -1
- package/dist/web/assets/soy-CGKN9rxg.js +0 -1
- package/dist/web/assets/sparql-CArCsIdI.js +0 -1
- package/dist/web/assets/sql-ljEiM8nf.js +0 -1
- package/dist/web/assets/sql-query-editor-B3wrPR6K.js +0 -1
- package/dist/web/assets/sqlite-viewer-iQXNp0kH.js +0 -1
- package/dist/web/assets/stata-CplvndbA.js +0 -1
- package/dist/web/assets/surrealql-DwX1PCpP.js +0 -1
- package/dist/web/assets/svelte-DYCNmQjy.js +0 -1
- package/dist/web/assets/system-monitor-body-5grJyA7C.js +0 -2
- package/dist/web/assets/system-monitor-tab-CJr797F8.js +0 -1
- package/dist/web/assets/system-monitor-window-content-OGAhFXXo.js +0 -1
- package/dist/web/assets/tab-host-window-content-C-eEo8I7.js +0 -1
- package/dist/web/assets/tab-store-krAuHQ6_.js +0 -1
- package/dist/web/assets/team-member-sheet-CRvJUtdh.js +0 -2
- package/dist/web/assets/team-member-window-content-C97N4RXb.js +0 -1
- package/dist/web/assets/templ-b_h2-Z9l.js +0 -1
- package/dist/web/assets/terminal-tab-eZwpkvEe.js +0 -3
- package/dist/web/assets/tex-022M3-MR.js +0 -1
- package/dist/web/assets/tool-cards-Bg4vjDYu.js +0 -9
- package/dist/web/assets/treemap-KZPCXAKY-CxqsD_6n.js +0 -1
- package/dist/web/assets/ts-tags-BUl0AdO6.js +0 -1
- package/dist/web/assets/tsx-CKaH7SzK.js +0 -1
- package/dist/web/assets/twig-CMzYUcSa.js +0 -1
- package/dist/web/assets/typescript-DZozDFsi.js +0 -1
- package/dist/web/assets/use-blob-url-C0VR6Uhh.js +0 -1
- package/dist/web/assets/use-inline-blame-CzR8CnOZ.js +0 -16
- package/dist/web/assets/use-is-mobile-TkcwP1Gx.js +0 -1
- package/dist/web/assets/use-lsp-BAoOSc-L.js +0 -6
- package/dist/web/assets/use-monaco-theme-Gd8cpt9n.js +0 -1
- package/dist/web/assets/use-open-team-member-y9sVhaNr.js +0 -1
- package/dist/web/assets/use-visual-viewport-Lp878uzs.js +0 -1
- package/dist/web/assets/use-websocket-CDfXkXo3.js +0 -1
- package/dist/web/assets/vendor-markdown-CuWCHIVb.js +0 -291
- package/dist/web/assets/vendor-mermaid-D6lgjvVE.js +0 -2921
- package/dist/web/assets/vendor-ui-DmZ-Mb-H.js +0 -45
- package/dist/web/assets/video-preview-BYJ3aVo1.js +0 -1
- package/dist/web/assets/vue-D83SsURi.js +0 -1
- package/dist/web/assets/vue-html-BGU-OYYb.js +0 -1
- package/dist/web/assets/vue-vine-1sHE1gZn.js +0 -1
- package/dist/web/assets/window-pip-registry-D1oXq-Dq.js +0 -1
- package/dist/web/assets/window-store-UC1jJeLM.js +0 -1
- package/dist/web/assets/ws-auth-CaxV807E.js +0 -1
- package/dist/web/assets/xml-bWQJszMK.js +0 -1
- package/dist/web/assets/xsl-DTMc1Tsm.js +0 -1
- package/dist/web/assets/yaml-4pzZq5KT.js +0 -1
- /package/dist/web/assets/{abap-DrxZXLHj.js → abap-DWbETETF.js} +0 -0
- /package/dist/web/assets/{actionscript-3-DOPR4pRC.js → actionscript-3-C278tgAF.js} +0 -0
- /package/dist/web/assets/{ada-DkqjEnDr.js → ada-C_5J29IC.js} +0 -0
- /package/dist/web/assets/{andromeeda-BSZjevw2.js → andromeeda-Ct0fb9Zo.js} +0 -0
- /package/dist/web/assets/{apache-DYwdQ5F_.js → apache-oMwCqc2o.js} +0 -0
- /package/dist/web/assets/{apex-Dohu7DfB.js → apex-n6XQQudq.js} +0 -0
- /package/dist/web/assets/{applescript-CdfGIVqp.js → applescript-QDMA6blY.js} +0 -0
- /package/dist/web/assets/{apply-theme-CbR31K6I.js → apply-theme-aVoqSG0I.js} +0 -0
- /package/dist/web/assets/{ara-i3_3TMnI.js → ara-D6rg_rTp.js} +0 -0
- /package/dist/web/assets/{asciidoc-DJFM-7vl.js → asciidoc-DVeBWv0S.js} +0 -0
- /package/dist/web/assets/{asm-bMFssizQ.js → asm-DzHQzzqu.js} +0 -0
- /package/dist/web/assets/{aurora-x-CetC7M8b.js → aurora-x-pJESoXa6.js} +0 -0
- /package/dist/web/assets/{awk-FFWx9ZrE.js → awk-BwfK4mzn.js} +0 -0
- /package/dist/web/assets/{ayu-dark-D4ION2wO.js → ayu-dark-CG-9c7ej.js} +0 -0
- /package/dist/web/assets/{ayu-light-BZN99P5A.js → ayu-light-BGUfMG6m.js} +0 -0
- /package/dist/web/assets/{ayu-mirage-B-IpsKiL.js → ayu-mirage-CMD89qy6.js} +0 -0
- /package/dist/web/assets/{ballerina-DhyJcKkq.js → ballerina-CP5gYaiB.js} +0 -0
- /package/dist/web/assets/{bat-GOVQY81F.js → bat-DCRdiK45.js} +0 -0
- /package/dist/web/assets/{beancount-BO749Rhc.js → beancount-DHkDiOKO.js} +0 -0
- /package/dist/web/assets/{berry-CHYYKXmK.js → berry-B6TPldKS.js} +0 -0
- /package/dist/web/assets/{bibtex-BnYiDnxT.js → bibtex-DIor8yh9.js} +0 -0
- /package/dist/web/assets/{bicep-kljgR_G3.js → bicep-BbIdLZZ_.js} +0 -0
- /package/dist/web/assets/{bird2-DnLtJGhV.js → bird2-C76TmOG1.js} +0 -0
- /package/dist/web/assets/{c3-fc_jio6D.js → c3-CqZ77xXr.js} +0 -0
- /package/dist/web/assets/{cadence-DopRCrdB.js → cadence-BlaAb6F6.js} +0 -0
- /package/dist/web/assets/{can-open-in-ppm-CUW3vVJg.js → can-open-in-ppm-D8T6Xca-.js} +0 -0
- /package/dist/web/assets/{catppuccin-frappe-DL6iCUa8.js → catppuccin-frappe-BuV7Zg67.js} +0 -0
- /package/dist/web/assets/{catppuccin-latte-DNF7n3uY.js → catppuccin-latte-B7HXEZf7.js} +0 -0
- /package/dist/web/assets/{catppuccin-macchiato-ByMic_k0.js → catppuccin-macchiato-B0KctcoC.js} +0 -0
- /package/dist/web/assets/{catppuccin-mocha-DcrJtZtv.js → catppuccin-mocha-Bofr5rzo.js} +0 -0
- /package/dist/web/assets/{clarity-0cRLlvQe.js → clarity-CerfZ3dW.js} +0 -0
- /package/dist/web/assets/{clojure-DPqZAcpI.js → clojure-BCEG1uj6.js} +0 -0
- /package/dist/web/assets/{cmake-Bx26bw5u.js → cmake-CRxSSKSr.js} +0 -0
- /package/dist/web/assets/{codeowners-BpgxIgxr.js → codeowners-BqW6DYSk.js} +0 -0
- /package/dist/web/assets/{codeql-TRoWjo5g.js → codeql-DlnOpgWF.js} +0 -0
- /package/dist/web/assets/{common-lisp-Ctohamsb.js → common-lisp-DgIX9jkq.js} +0 -0
- /package/dist/web/assets/{coq-BO6TJSED.js → coq-CFeLOER-.js} +0 -0
- /package/dist/web/assets/{csharp-DSy4nlrl.js → csharp-BGFGcV8G.js} +0 -0
- /package/dist/web/assets/{csv-DND7YJXD.js → csv-Cx126-fo.js} +0 -0
- /package/dist/web/assets/{csv-parser-DZ_75eCb.js → csv-parser-BXeH-yzY.js} +0 -0
- /package/dist/web/assets/{cue-BUnWK221.js → cue-Cd0PEGFL.js} +0 -0
- /package/dist/web/assets/{cypher-CInm9Etl.js → cypher-QS9S-1Nu.js} +0 -0
- /package/dist/web/assets/{d-BbsB8r6R.js → d-Bx6zK6J7.js} +0 -0
- /package/dist/web/assets/{dark-plus-DkzIiuQX.js → dark-plus-DLqXEd2I.js} +0 -0
- /package/dist/web/assets/{dart-BG2nw7Se.js → dart-BL2C2Z6E.js} +0 -0
- /package/dist/web/assets/{dax-j4h6VhlV.js → dax-ClxUDxvY.js} +0 -0
- /package/dist/web/assets/{desktop-Dg34JDlS.js → desktop-DLEkw1UR.js} +0 -0
- /package/dist/web/assets/{diff-CRrKo-mH.js → diff-Dlp9KQSL.js} +0 -0
- /package/dist/web/assets/{dist-D39GQICe.js → dist-CDpxSUMU.js} +0 -0
- /package/dist/web/assets/{docker-DAtcxZjt.js → docker-DVBsQYb-.js} +0 -0
- /package/dist/web/assets/{dotenv-DNUcgQCn.js → dotenv-DjBB7S8B.js} +0 -0
- /package/dist/web/assets/{dracula-bhhaShNC.js → dracula-Cu055q9D.js} +0 -0
- /package/dist/web/assets/{dracula-soft-CeHAoi-D.js → dracula-soft-BiX_luwV.js} +0 -0
- /package/dist/web/assets/{dream-maker-BMH1JI2G.js → dream-maker-S6ie6kFg.js} +0 -0
- /package/dist/web/assets/{editor-font-D_4aaSCa.js → editor-font-BOjGgYeg.js} +0 -0
- /package/dist/web/assets/{emacs-lisp-BaAYIdWN.js → emacs-lisp-DpOda430.js} +0 -0
- /package/dist/web/assets/{everforest-dark-Cs91gPa_.js → everforest-dark-BAfSXdLG.js} +0 -0
- /package/dist/web/assets/{everforest-light-lTkE6qWA.js → everforest-light-Dp59kp4R.js} +0 -0
- /package/dist/web/assets/{fennel-CmhYEhcM.js → fennel-CNaNUmMo.js} +0 -0
- /package/dist/web/assets/{fish-p1jauFum.js → fish-C8Z04ic7.js} +0 -0
- /package/dist/web/assets/{fluent-BsH-lUh2.js → fluent-Bugk01mf.js} +0 -0
- /package/dist/web/assets/{format-bytes-amUJ8Js8.js → format-bytes-DBBzVCYA.js} +0 -0
- /package/dist/web/assets/{fortran-free-form-CB6SdVKB.js → fortran-free-form-csIz6MQj.js} +0 -0
- /package/dist/web/assets/{gdscript--YoKuvEA.js → gdscript-fdzYQLfk.js} +0 -0
- /package/dist/web/assets/{gdshader-BRtMwf5z.js → gdshader-CfsEtDeZ.js} +0 -0
- /package/dist/web/assets/{genie-wrzVG2Z8.js → genie-CtHN5N2Q.js} +0 -0
- /package/dist/web/assets/{gherkin-HnpURN27.js → gherkin-gSp2ZJTf.js} +0 -0
- /package/dist/web/assets/{github-dark-XlZ3pGhn.js → github-dark-D7O9efii.js} +0 -0
- /package/dist/web/assets/{github-dark-default-D_R0hfJe.js → github-dark-default-Bv2wIhqD.js} +0 -0
- /package/dist/web/assets/{github-dark-dimmed-BHQgHLnK.js → github-dark-dimmed-BuY_SpCX.js} +0 -0
- /package/dist/web/assets/{github-dark-high-contrast-Pbl4mEFe.js → github-dark-high-contrast-Chv0f5Wu.js} +0 -0
- /package/dist/web/assets/{github-light-0P0VANJn.js → github-light-DV8f-W2f.js} +0 -0
- /package/dist/web/assets/{github-light-default-DTfsnyDq.js → github-light-default-CNBSU3dB.js} +0 -0
- /package/dist/web/assets/{github-light-high-contrast-DKITR-5Y.js → github-light-high-contrast-sg94tHwU.js} +0 -0
- /package/dist/web/assets/{gleam-refSZtkM.js → gleam-w7270-PJ.js} +0 -0
- /package/dist/web/assets/{gn-BZ9cGckR.js → gn-yo_iE_A_.js} +0 -0
- /package/dist/web/assets/{gnuplot-CMHqDcTW.js → gnuplot-DSBPrzl4.js} +0 -0
- /package/dist/web/assets/{go-bFdCrzvY.js → go-D1S7g97D.js} +0 -0
- /package/dist/web/assets/{groovy-Dvz5tluQ.js → groovy-C7xW-5IV.js} +0 -0
- /package/dist/web/assets/{gruvbox-dark-hard-D0Z-pclr.js → gruvbox-dark-hard-BZald7Z_.js} +0 -0
- /package/dist/web/assets/{gruvbox-dark-medium-BG6oIRQR.js → gruvbox-dark-medium-v6W4PZne.js} +0 -0
- /package/dist/web/assets/{gruvbox-dark-soft-ILJ-3tU6.js → gruvbox-dark-soft-CN5mIGkw.js} +0 -0
- /package/dist/web/assets/{gruvbox-light-hard-Bl95khkz.js → gruvbox-light-hard-D3NIGRxd.js} +0 -0
- /package/dist/web/assets/{gruvbox-light-medium-CdislFOh.js → gruvbox-light-medium-m4ShuCnD.js} +0 -0
- /package/dist/web/assets/{gruvbox-light-soft-CTcEyxlX.js → gruvbox-light-soft-BEEYNyk-.js} +0 -0
- /package/dist/web/assets/{haskell-D9jfkQuH.js → haskell-CgtdXIH3.js} +0 -0
- /package/dist/web/assets/{haxe-Ckfl4osD.js → haxe-D7HQqtIx.js} +0 -0
- /package/dist/web/assets/{hcl-t03N4k5N.js → hcl-C-YHDaXH.js} +0 -0
- /package/dist/web/assets/{hjson-B_TIVRki.js → hjson-BrgEMvJK.js} +0 -0
- /package/dist/web/assets/{hlsl-BBCTeANz.js → hlsl-BsDumu1j.js} +0 -0
- /package/dist/web/assets/{horizon-CRY-xdGU.js → horizon-D9Kre3KQ.js} +0 -0
- /package/dist/web/assets/{horizon-bright-BpUM2C5u.js → horizon-bright-DJq8c_Yq.js} +0 -0
- /package/dist/web/assets/{houston-RVyAGlyS.js → houston-B9tnxzX8.js} +0 -0
- /package/dist/web/assets/{hy-BHFJHuHd.js → hy-DUYVvXOj.js} +0 -0
- /package/dist/web/assets/{image-gallery-DdQblMAe.js → image-gallery-DvAgPQ3L.js} +0 -0
- /package/dist/web/assets/{image-preview-geometry-BFKR37Pj.js → image-preview-geometry-B-SdD7_D.js} +0 -0
- /package/dist/web/assets/{imba-DyG0_0MS.js → imba-CGW-TsRm.js} +0 -0
- /package/dist/web/assets/{ini-CsCTH-_o.js → ini-PqgYiEAV.js} +0 -0
- /package/dist/web/assets/{json5-g3g-IFTV.js → json5-sbkvqHou.js} +0 -0
- /package/dist/web/assets/{jsonc-DQHBJwib.js → jsonc-pnywfpws.js} +0 -0
- /package/dist/web/assets/{jsonl-zFLDm4eB.js → jsonl-ZPOQ0pRn.js} +0 -0
- /package/dist/web/assets/{jsonnet-DgNm2IGn.js → jsonnet-B_Q7j1YF.js} +0 -0
- /package/dist/web/assets/{jssm-BErkU0In.js → jssm-K-xYeQyp.js} +0 -0
- /package/dist/web/assets/{kanagawa-dragon-Dgymfjca.js → kanagawa-dragon-DAdLBtU8.js} +0 -0
- /package/dist/web/assets/{kanagawa-lotus-CWZEYd27.js → kanagawa-lotus-5BwvVGu8.js} +0 -0
- /package/dist/web/assets/{kanagawa-wave-CQg17ecf.js → kanagawa-wave-C0h9fsDT.js} +0 -0
- /package/dist/web/assets/{kdl-DY4GHmJC.js → kdl-DXSsFcms.js} +0 -0
- /package/dist/web/assets/{kotlin-DeGTz7bl.js → kotlin-BXNIvloo.js} +0 -0
- /package/dist/web/assets/{kusto-BN-OqpQj.js → kusto-wM3eio5V.js} +0 -0
- /package/dist/web/assets/{laserwave-bAqiAiOp.js → laserwave-FcbxdP2A.js} +0 -0
- /package/dist/web/assets/{lean-CAypLWCf.js → lean-RenzGeoM.js} +0 -0
- /package/dist/web/assets/{less-ikHAUlPb.js → less-CcUdtNJi.js} +0 -0
- /package/dist/web/assets/{libesm-cUHvIIuW.js → libesm-DMnQ3WlF.js} +0 -0
- /package/dist/web/assets/{light-plus-BamuTcT9.js → light-plus-BsMoOZJR.js} +0 -0
- /package/dist/web/assets/{llvm-CddObVkW.js → llvm-CyylMBuq.js} +0 -0
- /package/dist/web/assets/{log-CWbfGTTc.js → log-BOi0GB58.js} +0 -0
- /package/dist/web/assets/{logo-AHyhxX3Z.js → logo-BQUr3X2Y.js} +0 -0
- /package/dist/web/assets/{luau-y7she9L3.js → luau-3YZRDIsh.js} +0 -0
- /package/dist/web/assets/{make-DP3sQaP3.js → make-DEkKRDRU.js} +0 -0
- /package/dist/web/assets/{markdown-9Nuxib8a.js → markdown-BmFN0-A1.js} +0 -0
- /package/dist/web/assets/{material-theme-DDpm-uS7.js → material-theme-DqLHjEZ8.js} +0 -0
- /package/dist/web/assets/{material-theme-darker-CHk91wbm.js → material-theme-darker-DhbvULnI.js} +0 -0
- /package/dist/web/assets/{material-theme-lighter-LkmOI8KM.js → material-theme-lighter-C_aA4yVe.js} +0 -0
- /package/dist/web/assets/{material-theme-ocean-PpkUhB4-.js → material-theme-ocean-Pk5JltJS.js} +0 -0
- /package/dist/web/assets/{material-theme-palenight-DZAigXgW.js → material-theme-palenight-DNi3VguV.js} +0 -0
- /package/dist/web/assets/{matlab-CexKVVPc.js → matlab-BqUtv2ml.js} +0 -0
- /package/dist/web/assets/{mdx-BrcepHfI.js → mdx-DFMrnHBn.js} +0 -0
- /package/dist/web/assets/{mermaid-CNFhZZaG.js → mermaid-BpyuE0L_.js} +0 -0
- /package/dist/web/assets/{min-dark-hd3nbDV4.js → min-dark-DVfCMEPW.js} +0 -0
- /package/dist/web/assets/{min-light-AqA5jmks.js → min-light-B96aMADV.js} +0 -0
- /package/dist/web/assets/{mipsasm-B3x4L8Zk.js → mipsasm-DHhEcvKr.js} +0 -0
- /package/dist/web/assets/{mojo-CvfXy3YL.js → mojo-BQ6HsVIQ.js} +0 -0
- /package/dist/web/assets/{monokai-CdxwmnU_.js → monokai-amcXAKGG.js} +0 -0
- /package/dist/web/assets/{moonbit-6Z_VCO0_.js → moonbit-CGSXXQJI.js} +0 -0
- /package/dist/web/assets/{move-B2__B6Po.js → move-BOa4mq0q.js} +0 -0
- /package/dist/web/assets/{narrat-D6vL6wL-.js → narrat-dBYNSnhr.js} +0 -0
- /package/dist/web/assets/{nextflow-groovy-L-FBME4e.js → nextflow-groovy-Dm2Y_qgn.js} +0 -0
- /package/dist/web/assets/{night-owl-DjKrkDjv.js → night-owl-Dy9ibYHN.js} +0 -0
- /package/dist/web/assets/{night-owl-light-CeGjPuUQ.js → night-owl-light-DamYjQKi.js} +0 -0
- /package/dist/web/assets/{nix-dr279CcA.js → nix-C1LyoszC.js} +0 -0
- /package/dist/web/assets/{nord-Dxn-_H_Y.js → nord-LtGRYAFI.js} +0 -0
- /package/dist/web/assets/{nushell-DgeAQO7j.js → nushell-BMoOkt47.js} +0 -0
- /package/dist/web/assets/{objective-c-CO0-Pacn.js → objective-c-CILaOZJu.js} +0 -0
- /package/dist/web/assets/{objective-cpp-SkrjegYw.js → objective-cpp-D5Fo-SoM.js} +0 -0
- /package/dist/web/assets/{ocaml-CAihtkib.js → ocaml-D1TCTCEJ.js} +0 -0
- /package/dist/web/assets/{odin-D0XZbUDB.js → odin-CjdYcmpW.js} +0 -0
- /package/dist/web/assets/{one-dark-pro-BUMNMxjX.js → one-dark-pro-GpsZUGZl.js} +0 -0
- /package/dist/web/assets/{one-light-C0Ui69Bx.js → one-light-DlketcS4.js} +0 -0
- /package/dist/web/assets/{openscad-fZ9ggqM-.js → openscad-BoT8wwuI.js} +0 -0
- /package/dist/web/assets/{pascal-DvZm-eun.js → pascal-Cqy403Sf.js} +0 -0
- /package/dist/web/assets/{pkl-CQSIp_z8.js → pkl-D6gRI9qQ.js} +0 -0
- /package/dist/web/assets/{plastic-CMspsouJ.js → plastic-DgvX8DXX.js} +0 -0
- /package/dist/web/assets/{plsql-B_HL7UfT.js → plsql-CTDnCVE3.js} +0 -0
- /package/dist/web/assets/{po-DxAfbdfe.js → po-DDnzm7AQ.js} +0 -0
- /package/dist/web/assets/{poimandres-JGmqmwux.js → poimandres-C4HQwFp-.js} +0 -0
- /package/dist/web/assets/{polar-_mNmplk8.js → polar-WBTQdMzX.js} +0 -0
- /package/dist/web/assets/{postcss-GpU0Sjqc.js → postcss-CWxogTg1.js} +0 -0
- /package/dist/web/assets/{powerquery-B1IP1lCQ.js → powerquery-DVtReIRR.js} +0 -0
- /package/dist/web/assets/{powershell-BiSO9XmG.js → powershell-Cb_RNzSh.js} +0 -0
- /package/dist/web/assets/{prisma-4QqDYSnH.js → prisma-nKLUh3DY.js} +0 -0
- /package/dist/web/assets/{prolog-BNjvyRqT.js → prolog-BD9orEy4.js} +0 -0
- /package/dist/web/assets/{proto-RNOumnkw.js → proto-B-AFoz75.js} +0 -0
- /package/dist/web/assets/{puppet-CDfv5o8f.js → puppet-DDW6wWm4.js} +0 -0
- /package/dist/web/assets/{purescript-YTjSoifd.js → purescript-DXy49AJg.js} +0 -0
- /package/dist/web/assets/{python-Mh7JD25U.js → python-BQnvDlc7.js} +0 -0
- /package/dist/web/assets/{qmldir-Da_ZrqZy.js → qmldir-CboMQXQW.js} +0 -0
- /package/dist/web/assets/{qss-DANVkyhy.js → qss-8XaprLEt.js} +0 -0
- /package/dist/web/assets/{racket-CwPOn4T1.js → racket-ChcVp15M.js} +0 -0
- /package/dist/web/assets/{raku-B04lBsXd.js → raku-dEgEXW0A.js} +0 -0
- /package/dist/web/assets/{red-MW6Zm5pd.js → red-hmwjontD.js} +0 -0
- /package/dist/web/assets/{reg-44SURM-E.js → reg-CIkOufh2.js} +0 -0
- /package/dist/web/assets/{rel-Gu5Erhpm.js → rel-NXKKDiTi.js} +0 -0
- /package/dist/web/assets/{resolve-theme-BNubecVz.js → resolve-theme-B87m6l4i.js} +0 -0
- /package/dist/web/assets/{riscv-DZDP0Ce7.js → riscv-BEIzhPcg.js} +0 -0
- /package/dist/web/assets/{ron-BwLObbl6.js → ron-CW2Bt8rN.js} +0 -0
- /package/dist/web/assets/{rose-pine-Bz6ToXok.js → rose-pine-DhnBfr5a.js} +0 -0
- /package/dist/web/assets/{rose-pine-dawn-LyFogzAh.js → rose-pine-dawn-Jyj59rVs.js} +0 -0
- /package/dist/web/assets/{rose-pine-moon-CpjkefjD.js → rose-pine-moon-BMulxhJC.js} +0 -0
- /package/dist/web/assets/{rosmsg-BldDLaz1.js → rosmsg-DuctJm-Q.js} +0 -0
- /package/dist/web/assets/{rust-74skZ8CC.js → rust-FbJ2fCp9.js} +0 -0
- /package/dist/web/assets/{sass-CitUFDWl.js → sass-Dfxwdu2h.js} +0 -0
- /package/dist/web/assets/{scala-D2kl5ghT.js → scala-ClsSR0wG.js} +0 -0
- /package/dist/web/assets/{scheme-DZqhC9Xs.js → scheme-Jj_Cc-8H.js} +0 -0
- /package/dist/web/assets/{sdbl-D6a8sHP9.js → sdbl-Bi8D_DGN.js} +0 -0
- /package/dist/web/assets/{slack-dark-DrlPLUB_.js → slack-dark-B7gbmJT9.js} +0 -0
- /package/dist/web/assets/{slack-ochin-Djgychog.js → slack-ochin-O7j_c76D.js} +0 -0
- /package/dist/web/assets/{smalltalk-CYQHXftK.js → smalltalk-BD5-U3JK.js} +0 -0
- /package/dist/web/assets/{snazzy-light-BQAdF14K.js → snazzy-light-BbiRB69_.js} +0 -0
- /package/dist/web/assets/{solarized-dark-JDtJfY-g.js → solarized-dark-2OWHYEBu.js} +0 -0
- /package/dist/web/assets/{solarized-light-DHzVPLDD.js → solarized-light-Cew4YqT3.js} +0 -0
- /package/dist/web/assets/{solidity-CYCEiPu1.js → solidity-Bpbne2Tx.js} +0 -0
- /package/dist/web/assets/{splunk-B7RHmJY2.js → splunk-Dq86L1_O.js} +0 -0
- /package/dist/web/assets/{ssh-config-B74-n00O.js → ssh-config-j5hsMvbs.js} +0 -0
- /package/dist/web/assets/{stylus-xlRhcbpN.js → stylus-DWhCIBg0.js} +0 -0
- /package/dist/web/assets/{swift-DTFwWJtu.js → swift-29fG5ztW.js} +0 -0
- /package/dist/web/assets/{synthwave-84-BuCpuX2E.js → synthwave-84-DraIUmiw.js} +0 -0
- /package/dist/web/assets/{system-verilog-CgxJCrOK.js → system-verilog-DqcJAWq_.js} +0 -0
- /package/dist/web/assets/{systemd-D0x7_XYJ.js → systemd-BUPJrx1D.js} +0 -0
- /package/dist/web/assets/{talonscript-B50aQRuc.js → talonscript-BGYbnAKh.js} +0 -0
- /package/dist/web/assets/{tasl-Byv8gHCL.js → tasl-CwbSJqng.js} +0 -0
- /package/dist/web/assets/{tcl-CzMjCzWo.js → tcl-Ba9376wa.js} +0 -0
- /package/dist/web/assets/{terraform-D6GH4CXG.js → terraform-ChSasWu8.js} +0 -0
- /package/dist/web/assets/{tokyo-night-CQ4rTpHY.js → tokyo-night-Bbw1Yguv.js} +0 -0
- /package/dist/web/assets/{toml-D9W-BuJE.js → toml-CYb7zi5B.js} +0 -0
- /package/dist/web/assets/{tsv-BddanT8p.js → tsv-P2eVmwf9.js} +0 -0
- /package/dist/web/assets/{turtle-BddVklvD.js → turtle-DIoQTATC.js} +0 -0
- /package/dist/web/assets/{typespec-D60I2kfB.js → typespec-Dpr1bC2k.js} +0 -0
- /package/dist/web/assets/{typst-Bxvc-9ID.js → typst-D4WMCDMn.js} +0 -0
- /package/dist/web/assets/{utils-Bmf_8h7Y.js → utils-btZ8C8-R.js} +0 -0
- /package/dist/web/assets/{v-kVYZE10o.js → v-B1wY-VFU.js} +0 -0
- /package/dist/web/assets/{vala-B3zj44PV.js → vala-BKqhrirP.js} +0 -0
- /package/dist/web/assets/{vb-CHgWrFTj.js → vb-S9PHCa7-.js} +0 -0
- /package/dist/web/assets/{vendor-xterm-_yyu5n32.js → vendor-xterm-BHKF_Nsf.js} +0 -0
- /package/dist/web/assets/{verilog-zIMuE3hE.js → verilog-CrztYl3V.js} +0 -0
- /package/dist/web/assets/{vesper-BjqPTQr0.js → vesper-C5KfcyFv.js} +0 -0
- /package/dist/web/assets/{vhdl-Q2EtgpQN.js → vhdl-D0qMeIJu.js} +0 -0
- /package/dist/web/assets/{viml-CrtDZkFz.js → viml-Dsv9mRPK.js} +0 -0
- /package/dist/web/assets/{vitesse-black-D2VWO3oN.js → vitesse-black-rJvNN5GN.js} +0 -0
- /package/dist/web/assets/{vitesse-dark-lleZmHBJ.js → vitesse-dark-CYp0WWjf.js} +0 -0
- /package/dist/web/assets/{vitesse-light-utUY298S.js → vitesse-light-BczSAvzE.js} +0 -0
- /package/dist/web/assets/{vyper-LQ1KxOUo.js → vyper-DM7bKz7E.js} +0 -0
- /package/dist/web/assets/{wasm-CJ9U4zWg.js → wasm-BXCHhbrz.js} +0 -0
- /package/dist/web/assets/{wasm-B-mpMVDM.js → wasm-CAJoqhGc.js} +0 -0
- /package/dist/web/assets/{wenyan-LqMyA7px.js → wenyan-NQ8fdbEq.js} +0 -0
- /package/dist/web/assets/{wgsl-eI4U21sm.js → wgsl-C88C7vmC.js} +0 -0
- /package/dist/web/assets/{wikitext-CuWC2dfS.js → wikitext-D92r7uX8.js} +0 -0
- /package/dist/web/assets/{wit-CCPY0MNz.js → wit-DNvTfQjW.js} +0 -0
- /package/dist/web/assets/{wolfram-CXhjyJun.js → wolfram-CNS5lCGj.js} +0 -0
- /package/dist/web/assets/{zenscript-BzHPI08Q.js → zenscript-B_rGi-H_.js} +0 -0
- /package/dist/web/assets/{zig-CBuhKUve.js → zig-BRi9UYQa.js} +0 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { readdir, readFile, rm } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import {
|
|
5
|
+
DESIGN_SNAPSHOT_REASONS, isSnapshotId, type DesignSnapshotInfo, type DesignSnapshotReason,
|
|
6
|
+
} from "../../shared/design-types.ts";
|
|
7
|
+
import { dotDesignDir, lstatOrNull } from "./design-paths.ts";
|
|
8
|
+
import { ensureDotDesign, mkdirIfMissing } from "./design-fs.ts";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* On-disk layout of a design's snapshot history:
|
|
12
|
+
*
|
|
13
|
+
* designs/<slug>/.design/history/<id>/meta.json
|
|
14
|
+
* designs/<slug>/.design/history/<id>/files/<the design's files>
|
|
15
|
+
*
|
|
16
|
+
* A snapshot is written under `history/.tmp-<id>/` and renamed into place when complete,
|
|
17
|
+
* so a listed snapshot is always whole; a crash leaves only a `.tmp-` directory, which
|
|
18
|
+
* pruning removes.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
export const HISTORY_DIR = "history";
|
|
22
|
+
export const SNAPSHOT_META = "meta.json";
|
|
23
|
+
export const SNAPSHOT_FILES = "files";
|
|
24
|
+
|
|
25
|
+
/** Newest `turn`, `pre-restore` and `manual` snapshots kept, together. */
|
|
26
|
+
export const SNAPSHOT_CAP = 100;
|
|
27
|
+
/** Newest `before-edit` snapshots kept, in a pool of their own so they cannot evict real history. */
|
|
28
|
+
export const EDIT_SNAPSHOT_CAP = 30;
|
|
29
|
+
|
|
30
|
+
const MAX_META_BYTES = 64 * 1024;
|
|
31
|
+
|
|
32
|
+
export function historyDir(designDir: string): string {
|
|
33
|
+
return join(dotDesignDir(designDir), HISTORY_DIR);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function snapshotDir(designDir: string, id: string): string {
|
|
37
|
+
return join(historyDir(designDir), id);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function snapshotFilesDir(designDir: string, id: string): string {
|
|
41
|
+
return join(snapshotDir(designDir, id), SNAPSHOT_FILES);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function isReason(value: unknown): value is DesignSnapshotReason {
|
|
45
|
+
return typeof value === "string" && (DESIGN_SNAPSHOT_REASONS as readonly string[]).includes(value);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Parse a meta.json, refusing anything that does not describe the directory it sits in. */
|
|
49
|
+
function parseMeta(raw: string, id: string): DesignSnapshotInfo | null {
|
|
50
|
+
let data: Record<string, unknown>;
|
|
51
|
+
try {
|
|
52
|
+
data = JSON.parse(raw) as Record<string, unknown>;
|
|
53
|
+
} catch {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
if (!data || typeof data !== "object" || data.id !== id || !isReason(data.reason)) return null;
|
|
57
|
+
if (typeof data.createdAt !== "string" || Number.isNaN(Date.parse(data.createdAt))) return null;
|
|
58
|
+
if (typeof data.fileCount !== "number" || typeof data.bytes !== "number") return null;
|
|
59
|
+
if (typeof data.treeHash !== "string" || !/^[0-9a-f]{64}$/.test(data.treeHash)) return null;
|
|
60
|
+
return {
|
|
61
|
+
id,
|
|
62
|
+
reason: data.reason,
|
|
63
|
+
createdAt: data.createdAt,
|
|
64
|
+
...(typeof data.sessionId === "string" ? { sessionId: data.sessionId } : {}),
|
|
65
|
+
...(isSnapshotId(data.restoreOf) ? { restoreOf: data.restoreOf } : {}),
|
|
66
|
+
fileCount: data.fileCount,
|
|
67
|
+
bytes: data.bytes,
|
|
68
|
+
treeHash: data.treeHash,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async function readMeta(designDir: string, id: string): Promise<DesignSnapshotInfo | null> {
|
|
73
|
+
// `.design/` is inside a folder the agent writes to. A snapshot directory that is a
|
|
74
|
+
// symlink is not one this module made, and restoring "from" it would read elsewhere.
|
|
75
|
+
const dirSt = await lstatOrNull(snapshotDir(designDir, id));
|
|
76
|
+
if (!dirSt || dirSt.isSymbolicLink() || !dirSt.isDirectory()) return null;
|
|
77
|
+
const path = join(snapshotDir(designDir, id), SNAPSHOT_META);
|
|
78
|
+
const st = await lstatOrNull(path);
|
|
79
|
+
if (!st || !st.isFile() || st.size > MAX_META_BYTES) return null;
|
|
80
|
+
return parseMeta(await readFile(path, "utf8"), id);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Every complete snapshot, newest first. Unreadable entries are left out, never guessed at. */
|
|
84
|
+
export async function readSnapshotHistory(designDir: string): Promise<DesignSnapshotInfo[]> {
|
|
85
|
+
const st = await lstatOrNull(historyDir(designDir));
|
|
86
|
+
if (!st || st.isSymbolicLink() || !st.isDirectory()) return [];
|
|
87
|
+
let names: string[];
|
|
88
|
+
try {
|
|
89
|
+
names = await readdir(historyDir(designDir));
|
|
90
|
+
} catch (e) {
|
|
91
|
+
if ((e as { code?: string }).code === "ENOENT") return [];
|
|
92
|
+
throw e;
|
|
93
|
+
}
|
|
94
|
+
const infos = await Promise.all(names.filter(isSnapshotId).map((id) => readMeta(designDir, id)));
|
|
95
|
+
return infos
|
|
96
|
+
.filter((info): info is DesignSnapshotInfo => info !== null)
|
|
97
|
+
.sort((a, b) => Date.parse(b.createdAt) - Date.parse(a.createdAt) || (a.id < b.id ? 1 : -1));
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export async function readSnapshotInfo(designDir: string, id: string): Promise<DesignSnapshotInfo | null> {
|
|
101
|
+
return isSnapshotId(id) ? readMeta(designDir, id) : null;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** `history/`, created (with `.design/` and its `.gitignore`) when missing; never a symlink. */
|
|
105
|
+
export async function ensureHistoryDir(designDir: string): Promise<string> {
|
|
106
|
+
await ensureDotDesign(designDir);
|
|
107
|
+
const dir = historyDir(designDir);
|
|
108
|
+
await mkdirIfMissing(dir);
|
|
109
|
+
const st = await lstatOrNull(dir);
|
|
110
|
+
if (!st || st.isSymbolicLink() || !st.isDirectory()) {
|
|
111
|
+
throw Object.assign(new Error(".design/history must be a real directory"), { status: 403, code: "EDESIGNPATH" });
|
|
112
|
+
}
|
|
113
|
+
return dir;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function pad(n: number): string {
|
|
117
|
+
return String(n).padStart(2, "0");
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** A fresh `YYYYMMDD-HHMMSS-xxxx` id (UTC) that names nothing in `history/` yet. */
|
|
121
|
+
export async function newSnapshotId(designDir: string, now = new Date()): Promise<string> {
|
|
122
|
+
const stamp = `${now.getUTCFullYear()}${pad(now.getUTCMonth() + 1)}${pad(now.getUTCDate())}-`
|
|
123
|
+
+ `${pad(now.getUTCHours())}${pad(now.getUTCMinutes())}${pad(now.getUTCSeconds())}`;
|
|
124
|
+
for (let attempt = 0; attempt < 64; attempt++) {
|
|
125
|
+
const id = `${stamp}-${randomBytes(2).toString("hex")}`;
|
|
126
|
+
const taken = (await lstatOrNull(snapshotDir(designDir, id)))
|
|
127
|
+
|| (await lstatOrNull(join(historyDir(designDir), `.tmp-${id}`)));
|
|
128
|
+
if (!taken) return id;
|
|
129
|
+
}
|
|
130
|
+
throw new Error("Could not allocate a snapshot id");
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Apply retention to a newest-first history: keep the newest {@link SNAPSHOT_CAP} protected
|
|
135
|
+
* snapshots and the newest {@link EDIT_SNAPSHOT_CAP} `before-edit` ones, each pool counted
|
|
136
|
+
* on its own. Ids in `keep` survive regardless (a restore protects its own target while it
|
|
137
|
+
* snapshots the current state). Also clears half-written `.tmp-` directories, which only
|
|
138
|
+
* exist after a crash because every caller holds the design lock. Returns the removed ids.
|
|
139
|
+
*/
|
|
140
|
+
export async function pruneSnapshotHistory(
|
|
141
|
+
designDir: string,
|
|
142
|
+
history: DesignSnapshotInfo[],
|
|
143
|
+
keep: ReadonlySet<string> = new Set(),
|
|
144
|
+
): Promise<string[]> {
|
|
145
|
+
const removed: string[] = [];
|
|
146
|
+
let edits = 0;
|
|
147
|
+
let others = 0;
|
|
148
|
+
for (const info of history) {
|
|
149
|
+
const overCap = info.reason === "before-edit" ? ++edits > EDIT_SNAPSHOT_CAP : ++others > SNAPSHOT_CAP;
|
|
150
|
+
if (!overCap || keep.has(info.id)) continue;
|
|
151
|
+
await rm(snapshotDir(designDir, info.id), { recursive: true, force: true });
|
|
152
|
+
removed.push(info.id);
|
|
153
|
+
}
|
|
154
|
+
const names = await readdir(historyDir(designDir)).catch(() => [] as string[]);
|
|
155
|
+
for (const name of names) {
|
|
156
|
+
if (name.startsWith(".tmp-")) await rm(join(historyDir(designDir), name), { recursive: true, force: true });
|
|
157
|
+
}
|
|
158
|
+
return removed;
|
|
159
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { mkdir, rename, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { dirname, join, resolve } from "node:path";
|
|
4
|
+
import {
|
|
5
|
+
DESIGN_SNAPSHOT_REASONS, type DesignSnapshotInfo, type DesignSnapshotReason,
|
|
6
|
+
} from "../../shared/design-types.ts";
|
|
7
|
+
import { resolveDesignDir } from "./design-paths.ts";
|
|
8
|
+
import { readDesignFileSafe, safeWalkDesignTree, type SafeWalkEntry } from "./design-safe-walk.ts";
|
|
9
|
+
import {
|
|
10
|
+
ensureHistoryDir, newSnapshotId, pruneSnapshotHistory, readSnapshotHistory,
|
|
11
|
+
SNAPSHOT_FILES, SNAPSHOT_META,
|
|
12
|
+
} from "./design-snapshot-history.ts";
|
|
13
|
+
import { withRecoveredDesign } from "./design-restore-journal.ts";
|
|
14
|
+
import { emitDesignEvent } from "./design-events.ts";
|
|
15
|
+
import { DesignError, isDesignError } from "./design-error.ts";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Snapshots are plain file copies of a design folder (minus `.design/`) kept in
|
|
19
|
+
* `.design/history/`, not git commits: the user does not want a commit per AI turn.
|
|
20
|
+
*
|
|
21
|
+
* A snapshot identical to the newest one is not taken (tree-hash dedupe), a design over
|
|
22
|
+
* {@link SNAPSHOT_MAX_BYTES} is skipped with a warning rather than copied every turn, and
|
|
23
|
+
* retention runs per reason (see `pruneSnapshotHistory`).
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
export const SNAPSHOT_MAX_BYTES = 50 * 1024 * 1024;
|
|
27
|
+
export const SNAPSHOT_MAX_FILES = 5000;
|
|
28
|
+
|
|
29
|
+
export type SnapshotResult =
|
|
30
|
+
| { id: string }
|
|
31
|
+
| { skipped: "unchanged"; sameAs: string }
|
|
32
|
+
| { skipped: "too-large" | "missing" };
|
|
33
|
+
|
|
34
|
+
export interface SnapshotMeta {
|
|
35
|
+
sessionId?: string;
|
|
36
|
+
restoreOf?: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
interface ReadTree {
|
|
40
|
+
files: { rel: string; data: Buffer }[];
|
|
41
|
+
bytes: number;
|
|
42
|
+
treeHash: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Walk and read a tree, or null when it is over the size or file-count budget. */
|
|
46
|
+
export async function readDesignTree(root: string, opts: { skipDotDesign?: boolean } = {}): Promise<ReadTree | null> {
|
|
47
|
+
const entries: SafeWalkEntry[] = [];
|
|
48
|
+
let listed = 0;
|
|
49
|
+
for await (const entry of safeWalkDesignTree(root, opts)) {
|
|
50
|
+
listed += entry.size;
|
|
51
|
+
entries.push(entry);
|
|
52
|
+
if (listed > SNAPSHOT_MAX_BYTES || entries.length > SNAPSHOT_MAX_FILES) return null;
|
|
53
|
+
}
|
|
54
|
+
const tree = createHash("sha256");
|
|
55
|
+
const files: ReadTree["files"] = [];
|
|
56
|
+
let bytes = 0;
|
|
57
|
+
for (const entry of entries) {
|
|
58
|
+
const data = await readDesignFileSafe(entry.abs, SNAPSHOT_MAX_BYTES);
|
|
59
|
+
bytes += data.length;
|
|
60
|
+
// A file can grow between the walk and the read; the budget is on what was read.
|
|
61
|
+
if (bytes > SNAPSHOT_MAX_BYTES) return null;
|
|
62
|
+
const fileHash = createHash("sha256").update(data).digest("hex");
|
|
63
|
+
tree.update(`${entry.rel}\0${data.length}\0${fileHash}\n`);
|
|
64
|
+
files.push({ rel: entry.rel, data });
|
|
65
|
+
}
|
|
66
|
+
return { files, bytes, treeHash: tree.digest("hex") };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Write already-read files under `destRoot`, creating directories as needed. */
|
|
70
|
+
export async function writeTreeFiles(destRoot: string, files: ReadTree["files"]): Promise<void> {
|
|
71
|
+
for (const file of files) {
|
|
72
|
+
const dest = join(destRoot, ...file.rel.split("/"));
|
|
73
|
+
await mkdir(dirname(dest), { recursive: true });
|
|
74
|
+
await writeFile(dest, file.data);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Take a snapshot of a design whose lock the caller already holds (restore takes its
|
|
80
|
+
* `pre-restore` this way). `keep` protects ids from this snapshot's pruning.
|
|
81
|
+
*
|
|
82
|
+
* Dedupe compares against the newest snapshot, except that a protected snapshot never
|
|
83
|
+
* dedupes against a `before-edit` one: that pool is evictable, and the state it holds
|
|
84
|
+
* would then survive only as long as the next thirty canvas edits allow.
|
|
85
|
+
*/
|
|
86
|
+
export async function takeSnapshotLocked(
|
|
87
|
+
designDir: string,
|
|
88
|
+
reason: DesignSnapshotReason,
|
|
89
|
+
meta: SnapshotMeta = {},
|
|
90
|
+
keep: ReadonlySet<string> = new Set(),
|
|
91
|
+
): Promise<SnapshotResult> {
|
|
92
|
+
const tree = await readDesignTree(designDir);
|
|
93
|
+
if (!tree) {
|
|
94
|
+
console.warn(`[design] not snapshotting ${designDir}: over ${SNAPSHOT_MAX_BYTES / 1024 / 1024} MB or ${SNAPSHOT_MAX_FILES} files`);
|
|
95
|
+
return { skipped: "too-large" };
|
|
96
|
+
}
|
|
97
|
+
const history = await readSnapshotHistory(designDir);
|
|
98
|
+
const newest = history[0];
|
|
99
|
+
if (newest && newest.treeHash === tree.treeHash && (newest.reason !== "before-edit" || reason === "before-edit")) {
|
|
100
|
+
return { skipped: "unchanged", sameAs: newest.id };
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const historyRoot = await ensureHistoryDir(designDir);
|
|
104
|
+
// Strictly after the newest one, so two snapshots within a millisecond still have an order.
|
|
105
|
+
const createdMs = Math.max(Date.now(), newest ? Date.parse(newest.createdAt) + 1 : 0);
|
|
106
|
+
const id = await newSnapshotId(designDir, new Date(createdMs));
|
|
107
|
+
const staging = join(historyRoot, `.tmp-${id}`);
|
|
108
|
+
const info: DesignSnapshotInfo = {
|
|
109
|
+
id,
|
|
110
|
+
reason,
|
|
111
|
+
createdAt: new Date(createdMs).toISOString(),
|
|
112
|
+
...(meta.sessionId ? { sessionId: meta.sessionId } : {}),
|
|
113
|
+
...(meta.restoreOf ? { restoreOf: meta.restoreOf } : {}),
|
|
114
|
+
fileCount: tree.files.length,
|
|
115
|
+
bytes: tree.bytes,
|
|
116
|
+
treeHash: tree.treeHash,
|
|
117
|
+
};
|
|
118
|
+
try {
|
|
119
|
+
await mkdir(join(staging, SNAPSHOT_FILES), { recursive: true });
|
|
120
|
+
await writeTreeFiles(join(staging, SNAPSHOT_FILES), tree.files);
|
|
121
|
+
await writeFile(join(staging, SNAPSHOT_META), `${JSON.stringify(info, null, 2)}\n`);
|
|
122
|
+
// Published by one rename, so a listed snapshot is always complete.
|
|
123
|
+
await rename(staging, join(historyRoot, id));
|
|
124
|
+
} catch (e) {
|
|
125
|
+
await rm(staging, { recursive: true, force: true });
|
|
126
|
+
throw e;
|
|
127
|
+
}
|
|
128
|
+
await pruneSnapshotHistory(designDir, [info, ...history], keep);
|
|
129
|
+
return { id };
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Snapshot a design (`turn` after an AI turn, `before-edit` ahead of a canvas write-back,
|
|
134
|
+
* `manual` on request). Announces the change with one `history_changed` event when a
|
|
135
|
+
* snapshot was actually taken. A design that does not exist is reported as skipped, since
|
|
136
|
+
* a turn can end in a session whose design was deleted.
|
|
137
|
+
*/
|
|
138
|
+
export async function snapshotDesign(
|
|
139
|
+
projectPath: string,
|
|
140
|
+
slug: string,
|
|
141
|
+
reason: DesignSnapshotReason,
|
|
142
|
+
meta: SnapshotMeta = {},
|
|
143
|
+
): Promise<SnapshotResult> {
|
|
144
|
+
if (!(DESIGN_SNAPSHOT_REASONS as readonly string[]).includes(reason)) {
|
|
145
|
+
throw new DesignError(400, "EBADREASON", `Unknown snapshot reason: ${reason}`);
|
|
146
|
+
}
|
|
147
|
+
let result: SnapshotResult;
|
|
148
|
+
try {
|
|
149
|
+
result = await withRecoveredDesign(projectPath, slug, (dir) => takeSnapshotLocked(dir, reason, meta));
|
|
150
|
+
} catch (e) {
|
|
151
|
+
if (isDesignError(e) && e.status === 404) return { skipped: "missing" };
|
|
152
|
+
throw e;
|
|
153
|
+
}
|
|
154
|
+
if ("id" in result) emitDesignEvent("history_changed", { projectPath: resolve(projectPath), slug });
|
|
155
|
+
return result;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/** Snapshots of one design, newest first. */
|
|
159
|
+
export async function listSnapshots(projectPath: string, slug: string): Promise<DesignSnapshotInfo[]> {
|
|
160
|
+
return readSnapshotHistory(await resolveDesignDir(projectPath, slug));
|
|
161
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import type { DesignKind } from "../../shared/design-types.ts";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The `index.html` a new design starts with: enough structure for the canvas to render
|
|
5
|
+
* something and for the agent to extend, following the same conventions its instructions
|
|
6
|
+
* describe (a `:root` block for tweakable values, `../tokens.css` when the project has one,
|
|
7
|
+
* `<section class="slide">` at 1280x720 for decks).
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
function escapeHtml(text: string): string {
|
|
11
|
+
return text
|
|
12
|
+
.replace(/&/g, "&")
|
|
13
|
+
.replace(/</g, "<")
|
|
14
|
+
.replace(/>/g, ">")
|
|
15
|
+
.replace(/"/g, """)
|
|
16
|
+
.replace(/'/g, "'");
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const PAGE_STYLE = ` :root {
|
|
20
|
+
--accent: #4f46e5;
|
|
21
|
+
--radius: 12px;
|
|
22
|
+
--space: 24px;
|
|
23
|
+
}
|
|
24
|
+
* { box-sizing: border-box; }
|
|
25
|
+
body {
|
|
26
|
+
margin: 0;
|
|
27
|
+
font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
|
|
28
|
+
color: #111827;
|
|
29
|
+
background: #f9fafb;
|
|
30
|
+
}
|
|
31
|
+
main {
|
|
32
|
+
max-width: 960px;
|
|
33
|
+
margin: 0 auto;
|
|
34
|
+
padding: calc(var(--space) * 3) var(--space);
|
|
35
|
+
}
|
|
36
|
+
h1 { margin: 0 0 var(--space); font-size: 2.5rem; }
|
|
37
|
+
p { color: #4b5563; line-height: 1.6; }
|
|
38
|
+
.button {
|
|
39
|
+
display: inline-block;
|
|
40
|
+
padding: 12px 20px;
|
|
41
|
+
border-radius: var(--radius);
|
|
42
|
+
background: var(--accent);
|
|
43
|
+
color: #fff;
|
|
44
|
+
text-decoration: none;
|
|
45
|
+
}`;
|
|
46
|
+
|
|
47
|
+
const SLIDES_STYLE = ` :root {
|
|
48
|
+
--accent: #4f46e5;
|
|
49
|
+
--space: 64px;
|
|
50
|
+
}
|
|
51
|
+
* { box-sizing: border-box; }
|
|
52
|
+
body {
|
|
53
|
+
margin: 0;
|
|
54
|
+
font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
|
|
55
|
+
background: #e5e7eb;
|
|
56
|
+
}
|
|
57
|
+
.slide {
|
|
58
|
+
width: 1280px;
|
|
59
|
+
height: 720px;
|
|
60
|
+
margin: 0 auto 24px;
|
|
61
|
+
padding: var(--space);
|
|
62
|
+
background: #fff;
|
|
63
|
+
overflow: hidden;
|
|
64
|
+
display: flex;
|
|
65
|
+
flex-direction: column;
|
|
66
|
+
justify-content: center;
|
|
67
|
+
}
|
|
68
|
+
.slide h1 { margin: 0 0 24px; font-size: 64px; color: var(--accent); }
|
|
69
|
+
.slide p { margin: 0; font-size: 28px; color: #4b5563; }`;
|
|
70
|
+
|
|
71
|
+
export function starterHtml(kind: DesignKind, title: string, hasTokens: boolean): string {
|
|
72
|
+
const safeTitle = escapeHtml(title);
|
|
73
|
+
const tokensLink = hasTokens ? ` <link rel="stylesheet" href="../tokens.css">\n` : "";
|
|
74
|
+
const body =
|
|
75
|
+
kind === "slides"
|
|
76
|
+
? ` <section class="slide">
|
|
77
|
+
<h1>${safeTitle}</h1>
|
|
78
|
+
<p>Describe the deck in the chat and the slides will appear here.</p>
|
|
79
|
+
</section>`
|
|
80
|
+
: ` <main>
|
|
81
|
+
<h1>${safeTitle}</h1>
|
|
82
|
+
<p>Describe what you want in the chat and the design will appear here.</p>
|
|
83
|
+
<a class="button" href="#">Get started</a>
|
|
84
|
+
</main>`;
|
|
85
|
+
return `<!doctype html>
|
|
86
|
+
<html lang="en">
|
|
87
|
+
<head>
|
|
88
|
+
<meta charset="utf-8">
|
|
89
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
90
|
+
<title>${safeTitle}</title>
|
|
91
|
+
${tokensLink} <style>
|
|
92
|
+
${kind === "slides" ? SLIDES_STYLE : PAGE_STYLE}
|
|
93
|
+
</style>
|
|
94
|
+
</head>
|
|
95
|
+
<body>
|
|
96
|
+
${body}
|
|
97
|
+
</body>
|
|
98
|
+
</html>
|
|
99
|
+
`;
|
|
100
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { mkdir, readdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import type { Stats } from "node:fs";
|
|
4
|
+
import {
|
|
5
|
+
isDesignKind, type DesignKind, type DesignSummary, type DesignSystemStatus,
|
|
6
|
+
} from "../../shared/design-types.ts";
|
|
7
|
+
import { isValidDesignSlug, slugFromTitle } from "./design-slug.ts";
|
|
8
|
+
import { lstatOrNull, resolveDesignDir, resolveDesignsRoot } from "./design-paths.ts";
|
|
9
|
+
import { ensureDotDesign, writeFileAtomic } from "./design-fs.ts";
|
|
10
|
+
import {
|
|
11
|
+
DEFAULT_ENTRY, MANIFEST_FILE, normalizeTitle, parseManifest, serializeManifest, type DesignManifest,
|
|
12
|
+
} from "./design-manifest.ts";
|
|
13
|
+
import { starterHtml } from "./design-starter-template.ts";
|
|
14
|
+
import { DesignError } from "./design-error.ts";
|
|
15
|
+
import { designLockKey, withDesignLock } from "./design-lock.ts";
|
|
16
|
+
import { withRecoveredDesign } from "./design-restore-journal.ts";
|
|
17
|
+
|
|
18
|
+
/** Designs listed per project, newest first. */
|
|
19
|
+
export const MAX_LISTED_DESIGNS = 200;
|
|
20
|
+
const MAX_MANIFEST_BYTES = 256 * 1024;
|
|
21
|
+
const MAX_SLUG_SUFFIX = 999;
|
|
22
|
+
|
|
23
|
+
async function readManifestRaw(designDir: string): Promise<string | null> {
|
|
24
|
+
const path = join(designDir, MANIFEST_FILE);
|
|
25
|
+
const st = await lstatOrNull(path);
|
|
26
|
+
if (!st || !st.isFile() || st.size > MAX_MANIFEST_BYTES) return null;
|
|
27
|
+
return readFile(path, "utf8");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function regularFileStat(path: string): Promise<Stats | null> {
|
|
31
|
+
const st = await lstatOrNull(path);
|
|
32
|
+
return st?.isFile() ? st : null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function summarize(designDir: string, slug: string, manifest: DesignManifest): Promise<DesignSummary> {
|
|
36
|
+
const entry = await regularFileStat(join(designDir, ...manifest.entry.split("/")));
|
|
37
|
+
const updated = Math.max(Date.parse(manifest.updatedAt), entry?.mtimeMs ?? 0);
|
|
38
|
+
const { title, kind, createdAt } = manifest;
|
|
39
|
+
return { slug, title, kind, entry: manifest.entry, createdAt, updatedAt: new Date(updated).toISOString() };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async function loadManifest(designDir: string, slug: string): Promise<{ manifest: DesignManifest; valid: boolean; raw: string | null }> {
|
|
43
|
+
const dirSt = await lstatOrNull(designDir);
|
|
44
|
+
// A manifest without timestamps falls back to the folder's own age, not "now", so a
|
|
45
|
+
// hand-made design does not jump to the top of the list on every read.
|
|
46
|
+
const now = new Date(dirSt?.birthtimeMs || dirSt?.mtimeMs || Date.now()).toISOString();
|
|
47
|
+
const raw = await readManifestRaw(designDir);
|
|
48
|
+
return { ...parseManifest(raw, { slug, now }), raw };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export async function getDesign(projectPath: string, slug: string): Promise<DesignSummary> {
|
|
52
|
+
const dir = await resolveDesignDir(projectPath, slug);
|
|
53
|
+
return summarize(dir, slug, (await loadManifest(dir, slug)).manifest);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Every design folder under `designs/`, newest first, at most {@link MAX_LISTED_DESIGNS}.
|
|
58
|
+
* A folder counts as a design when its name is a valid slug and it holds a manifest or an
|
|
59
|
+
* entry page; symlinked folders are never listed.
|
|
60
|
+
*/
|
|
61
|
+
export async function listDesigns(projectPath: string): Promise<DesignSummary[]> {
|
|
62
|
+
const root = await resolveDesignsRoot(projectPath);
|
|
63
|
+
if (!root) return [];
|
|
64
|
+
const out: DesignSummary[] = [];
|
|
65
|
+
for (const name of await readdir(root)) {
|
|
66
|
+
if (!isValidDesignSlug(name)) continue;
|
|
67
|
+
const dir = join(root, name);
|
|
68
|
+
const st = await lstatOrNull(dir);
|
|
69
|
+
if (!st || st.isSymbolicLink() || !st.isDirectory()) continue;
|
|
70
|
+
const hasManifest = await regularFileStat(join(dir, MANIFEST_FILE));
|
|
71
|
+
if (!hasManifest && !(await regularFileStat(join(dir, DEFAULT_ENTRY)))) continue;
|
|
72
|
+
try {
|
|
73
|
+
out.push(await summarize(dir, name, (await loadManifest(dir, name)).manifest));
|
|
74
|
+
} catch (e) {
|
|
75
|
+
console.warn(`[design] skipping ${dir}: ${(e as Error).message}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return out.sort((a, b) => Date.parse(b.updatedAt) - Date.parse(a.updatedAt)).slice(0, MAX_LISTED_DESIGNS);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function candidateSlug(base: string, n: number): string {
|
|
82
|
+
if (n === 1) return base;
|
|
83
|
+
const suffix = `-${n}`;
|
|
84
|
+
return `${base.slice(0, 63 - suffix.length).replace(/-+$/, "")}${suffix}`;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Create `designs/<slug>/` with a starter page, the manifest and `.design/.gitignore`.
|
|
89
|
+
* The slug comes from the title; a taken slug gets `-2`, `-3`… The folder is claimed with a
|
|
90
|
+
* non-recursive mkdir, which fails if it already exists, so two creates racing for one
|
|
91
|
+
* title end up in two folders rather than one overwriting the other.
|
|
92
|
+
*/
|
|
93
|
+
export async function createDesign(projectPath: string, input: { title: unknown; kind: unknown }): Promise<DesignSummary> {
|
|
94
|
+
const title = normalizeTitle(input.title);
|
|
95
|
+
if (!title) throw new DesignError(400, "EBADTITLE", "A design needs a title");
|
|
96
|
+
if (input.kind !== undefined && !isDesignKind(input.kind)) throw new DesignError(400, "EBADKIND", "Unknown design kind");
|
|
97
|
+
const kind: DesignKind = isDesignKind(input.kind) ? input.kind : "page";
|
|
98
|
+
const root = await resolveDesignsRoot(projectPath, { create: true });
|
|
99
|
+
if (!root) throw new DesignError(500, "EDESIGNROOT", "Could not create designs/");
|
|
100
|
+
const base = slugFromTitle(title) || "design";
|
|
101
|
+
|
|
102
|
+
for (let n = 1; n <= MAX_SLUG_SUFFIX; n++) {
|
|
103
|
+
const slug = candidateSlug(base, n);
|
|
104
|
+
const dir = join(root, slug);
|
|
105
|
+
try {
|
|
106
|
+
await mkdir(dir);
|
|
107
|
+
} catch (e) {
|
|
108
|
+
if ((e as { code?: string }).code === "EEXIST") continue;
|
|
109
|
+
throw e;
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
const now = new Date().toISOString();
|
|
113
|
+
const manifest: DesignManifest = { title, kind, entry: DEFAULT_ENTRY, createdAt: now, updatedAt: now, extra: { tweaks: [] } };
|
|
114
|
+
const hasTokens = !!(await regularFileStat(join(root, "tokens.css")));
|
|
115
|
+
await ensureDotDesign(dir);
|
|
116
|
+
await writeFile(join(dir, DEFAULT_ENTRY), starterHtml(kind, title, hasTokens));
|
|
117
|
+
await writeFile(join(dir, MANIFEST_FILE), serializeManifest(manifest));
|
|
118
|
+
return await summarize(dir, slug, manifest);
|
|
119
|
+
} catch (e) {
|
|
120
|
+
await rm(dir, { recursive: true, force: true });
|
|
121
|
+
throw e;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
throw new DesignError(409, "EEXIST", "Too many designs share this title");
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/** Change the title only: the slug is fixed because design sessions carry it in their instructions. */
|
|
128
|
+
export async function renameDesign(projectPath: string, slug: string, rawTitle: unknown): Promise<DesignSummary> {
|
|
129
|
+
const title = normalizeTitle(rawTitle);
|
|
130
|
+
if (!title) throw new DesignError(400, "EBADTITLE", "A design needs a title");
|
|
131
|
+
return withRecoveredDesign(projectPath, slug, async (dir) => {
|
|
132
|
+
const { manifest, valid, raw } = await loadManifest(dir, slug);
|
|
133
|
+
// Rewriting an unreadable manifest would replace whatever the agent put there with defaults.
|
|
134
|
+
if (raw !== null && !valid) throw new DesignError(409, "EBADMANIFEST", `${MANIFEST_FILE} is not a valid JSON object`);
|
|
135
|
+
const next: DesignManifest = { ...manifest, title, updatedAt: new Date().toISOString() };
|
|
136
|
+
await writeFileAtomic(join(dir, MANIFEST_FILE), serializeManifest(next));
|
|
137
|
+
return summarize(dir, slug, next);
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** Delete a design folder, `.design/` and its history included. */
|
|
142
|
+
export async function deleteDesign(projectPath: string, slug: string): Promise<void> {
|
|
143
|
+
await withDesignLock(designLockKey(projectPath, slug), async () => {
|
|
144
|
+
const dir = await resolveDesignDir(projectPath, slug);
|
|
145
|
+
// rm never follows a symlink inside the tree; the folder itself was checked not to be one.
|
|
146
|
+
await rm(dir, { recursive: true, force: false });
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/** Whether the project design system exists yet (`designs/DESIGN.md`, `designs/tokens.css`). */
|
|
151
|
+
export async function designSystemStatus(projectPath: string): Promise<DesignSystemStatus> {
|
|
152
|
+
const root = await resolveDesignsRoot(projectPath);
|
|
153
|
+
if (!root) return { designMd: false, tokensCss: false };
|
|
154
|
+
const [md, css] = await Promise.all([regularFileStat(join(root, "DESIGN.md")), regularFileStat(join(root, "tokens.css"))]);
|
|
155
|
+
return { designMd: !!md, tokensCss: !!css };
|
|
156
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { DESIGN_GEN_RE } from "../../shared/design-types.ts";
|
|
2
|
+
import { ELEMENT_TAG_RE, parsePpmId } from "../../shared/design-comment-types.ts";
|
|
3
|
+
import { parseTransformProps, type TransformProps } from "../../shared/design-bridge-messages-transform.ts";
|
|
4
|
+
import { withRecoveredDesign } from "./design-restore-journal.ts";
|
|
5
|
+
import { isSafeEntry } from "./design-manifest.ts";
|
|
6
|
+
import { snapshotDesign } from "./design-snapshots.service.ts";
|
|
7
|
+
import { DesignError } from "./design-error.ts";
|
|
8
|
+
import { takeDesignWrite } from "./design-write-rate-limit.ts";
|
|
9
|
+
import { changedSpan, recordEdit } from "./design-edit-undo-journal.ts";
|
|
10
|
+
import { resolveScopedPath } from "./preview/design-preview-scope.ts";
|
|
11
|
+
import { INSTRUMENT_MAX_BYTES } from "./preview/design-preview-html.ts";
|
|
12
|
+
import { readDesignSource, writeDesignSource } from "./source/design-source-file.ts";
|
|
13
|
+
import { patchStartTagStyle } from "./source/inline-style-patch.ts";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* A move or resize from the canvas, written into the element's inline `style`.
|
|
17
|
+
*
|
|
18
|
+
* The request names the element the way the canvas knows it — file, the gen the canvas
|
|
19
|
+
* loaded, `data-ppm-id`, tag — and carries only `translate`/`width`/`height` px values
|
|
20
|
+
* ({@link parseTransformProps}). Under the design's lock the server re-reads the file and
|
|
21
|
+
* refuses with a 409 when its gen moved on (`stale`) or the tag at that offset is not the
|
|
22
|
+
* expected one (`element-moved`), so a canvas behind an agent's edit can never write into
|
|
23
|
+
* the wrong element. Only then does the write count against the rate limit, take a
|
|
24
|
+
* `before-edit` snapshot, patch the style attribute and go to disk atomically, and the patch
|
|
25
|
+
* is journaled so Undo can reverse exactly it.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
export interface StylePatchInput {
|
|
29
|
+
file: string;
|
|
30
|
+
gen: string;
|
|
31
|
+
ppmId: number;
|
|
32
|
+
tag: string;
|
|
33
|
+
props: TransformProps;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface StylePatchResult {
|
|
37
|
+
gen: string;
|
|
38
|
+
/** Null when the edit was too large to journal; History still has the snapshot. */
|
|
39
|
+
undoId: string | null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** A 409 carrying why, so the canvas can say whether to reload or reselect. */
|
|
43
|
+
export class StyleConflictError extends DesignError {
|
|
44
|
+
constructor(reason: "stale" | "element-moved", message: string, readonly currentGen: string) {
|
|
45
|
+
super(409, reason, message);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const bad = (message: string): DesignError => new DesignError(400, "EBADSTYLE", message);
|
|
50
|
+
|
|
51
|
+
export function parseStylePatchInput(input: unknown): StylePatchInput {
|
|
52
|
+
if (!input || typeof input !== "object" || Array.isArray(input)) throw bad("Expected a JSON object");
|
|
53
|
+
const raw = input as Record<string, unknown>;
|
|
54
|
+
if (!isSafeEntry(raw.file)) throw bad("file must be an HTML file of the design");
|
|
55
|
+
if (typeof raw.gen !== "string" || !DESIGN_GEN_RE.test(raw.gen)) throw bad("Invalid gen");
|
|
56
|
+
const ppmId = parsePpmId(raw.ppmId);
|
|
57
|
+
if (typeof ppmId !== "number") throw bad("Invalid element id");
|
|
58
|
+
const tag = typeof raw.tag === "string" ? raw.tag.toLowerCase() : "";
|
|
59
|
+
if (!ELEMENT_TAG_RE.test(tag)) throw bad("Invalid tag");
|
|
60
|
+
const props = parseTransformProps(raw.props);
|
|
61
|
+
if (!props) throw bad("props may only set translate, width and height to px values");
|
|
62
|
+
return { file: raw.file, gen: raw.gen, ppmId, tag, props };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export async function commitStylePatch(projectPath: string, slug: string, raw: unknown): Promise<StylePatchResult> {
|
|
66
|
+
const input = parseStylePatchInput(raw);
|
|
67
|
+
return withRecoveredDesign(projectPath, slug, async () => {
|
|
68
|
+
const abs = (await resolveScopedPath({ projectPath, slug }, `${slug}/${input.file}`)).abs;
|
|
69
|
+
// Files above this size are served without ids, so no canvas can address one of their elements.
|
|
70
|
+
const source = await readDesignSource(abs, { maxBytes: INSTRUMENT_MAX_BYTES });
|
|
71
|
+
if (source.gen !== input.gen) {
|
|
72
|
+
throw new StyleConflictError("stale", `${input.file} changed since the canvas loaded it`, source.gen);
|
|
73
|
+
}
|
|
74
|
+
const patched = patchStartTagStyle(source.text, input.ppmId, input.tag, input.props);
|
|
75
|
+
if ("error" in patched) throw new StyleConflictError("element-moved", patched.message, source.gen);
|
|
76
|
+
takeDesignWrite(projectPath, slug);
|
|
77
|
+
await snapshotDesign(projectPath, slug, "before-edit");
|
|
78
|
+
const gen = await writeDesignSource(abs, patched.text, { bom: source.bom });
|
|
79
|
+
const span = changedSpan(input.file, source.text, patched.text);
|
|
80
|
+
const undoId = span ? recordEdit(projectPath, slug, [span], { [input.file]: gen }) : null;
|
|
81
|
+
return { gen, undoId };
|
|
82
|
+
});
|
|
83
|
+
}
|