@hienlh/ppm 0.18.11 → 0.18.13
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/AGENTS.md +17 -5
- package/CHANGELOG.md +27 -0
- package/CLAUDE.md +3 -0
- package/README.md +87 -29
- package/assets/skills/ppm/SKILL.md +1 -1
- package/assets/skills/ppm/references/http-api.md +19 -1
- package/dist/web/assets/{adaptive-context-menu-DGCKKeTy.js → adaptive-context-menu-CbgPYQmj.js} +1 -1
- package/dist/web/assets/{ai-resource-editor-BOHHTTe7.js → ai-resource-editor-unM2HNmg.js} +1 -1
- package/dist/web/assets/{ai-settings-section-BigC_nZR.js → ai-settings-section-CdktdrwF.js} +1 -1
- package/dist/web/assets/{angular-html-BYPaydvh.js → angular-html-DcpbdcNG.js} +1 -1
- package/dist/web/assets/{angular-ts-Bb4AMKlk.js → angular-ts-Bv_WIk34.js} +1 -1
- package/dist/web/assets/api-client-BogqsFna.js +1 -0
- package/dist/web/assets/{api-settings-Bd3M4YpI.js → api-settings-BdCtex9i.js} +1 -1
- package/dist/web/assets/api-settings-DfXViPKz.js +1 -0
- package/dist/web/assets/{api-themes-Cpx419SL.js → api-themes-pRRoLvgD.js} +1 -1
- package/dist/web/assets/{apl-DB2VjFCS.js → apl-D5_lLszu.js} +1 -1
- package/dist/web/assets/architecture-PBZL5I3N-BzFm9ELu.js +1 -0
- package/dist/web/assets/{astro-BeoJdVpk.js → astro-CBHwddYL.js} +1 -1
- package/dist/web/assets/{audio-preview-BgFuTn-0.js → audio-preview-BD1iDovf.js} +1 -1
- package/dist/web/assets/{blade-Cf2q1sPf.js → blade-DGe1d2Pq.js} +1 -1
- package/dist/web/assets/{bsl-W1kOaNpu.js → bsl-2lyAzRJA.js} +1 -1
- package/dist/web/assets/{button-5zTrkEoN.js → button-2WCAS8dI.js} +1 -1
- package/dist/web/assets/{cairo-BoAZFcje.js → cairo-DjzZeJrq.js} +1 -1
- package/dist/web/assets/chat-tab-DzK8LGti.js +15 -0
- package/dist/web/assets/{cobol-B0Nm7RXj.js → cobol-cC3XIuAJ.js} +1 -1
- package/dist/web/assets/code-editor-CuMfPN9X.js +10 -0
- package/dist/web/assets/{coffee-BakMn3on.js → coffee-4eGboVoU.js} +1 -1
- package/dist/web/assets/{conflict-editor-BUs5k9q_.js → conflict-editor-DdJag4QK.js} +1 -1
- package/dist/web/assets/{context-menu-Bq92km4s.js → context-menu-BO1c9jKy.js} +1 -1
- package/dist/web/assets/{cpp-BRAJQHK2.js → cpp-DF9_G-OU.js} +1 -1
- package/dist/web/assets/{crystal-kqqO3zkK.js → crystal-OavZlzcm.js} +1 -1
- package/dist/web/assets/{csv-preview-ByoDgLAZ.js → csv-preview-DnXwouF3.js} +1 -1
- package/dist/web/assets/{data-grid-overlay-editor-Brkf9z41.js → data-grid-overlay-editor-B9Gpjm3l.js} +1 -1
- package/dist/web/assets/{database-viewer-Btc3h8Yu.js → database-viewer-Dk8oGyZx.js} +1 -1
- package/dist/web/assets/{dialog-DwtGlowE.js → dialog-B-l2ZxVm.js} +1 -1
- package/dist/web/assets/{diff-viewer-CZaDnR4w.js → diff-viewer-eaUBjLCH.js} +1 -1
- package/dist/web/assets/{docx-preview-DAD_vg59.js → docx-preview-DAdHPlhZ.js} +1 -1
- package/dist/web/assets/{edge-Cq1ZKZuE.js → edge-TzYh8OlN.js} +1 -1
- package/dist/web/assets/{edit-diff-preview-B_VE7ppQ.js → edit-diff-preview-DlwP3UIU.js} +1 -1
- package/dist/web/assets/{elixir-BM_JoJRk.js → elixir-Cy3RhKKH.js} +1 -1
- package/dist/web/assets/{elm-Dw7oO08Y.js → elm-BTBZdweK.js} +1 -1
- package/dist/web/assets/{erb-CfKOGAfk.js → erb-dv1mI0y4.js} +1 -1
- package/dist/web/assets/{erlang-DlDmGVeE.js → erlang-DjeiDrkl.js} +1 -1
- package/dist/web/assets/{esm-DGAP0GFh.js → esm-FRwvcesu.js} +1 -1
- package/dist/web/assets/explorer-body-DkCkSVrN.js +2 -0
- package/dist/web/assets/explorer-window-content-MsnTVngu.js +1 -0
- package/dist/web/assets/{extension-store-Cpfh2vMm.js → extension-store-DUaZINyC.js} +1 -1
- package/dist/web/assets/{extension-webview-B2OnjuCu.js → extension-webview-W0qRfaAU.js} +1 -1
- package/dist/web/assets/{file-store-aOERIEo-.js → file-store-yReVbR8q.js} +1 -1
- package/dist/web/assets/{fortran-fixed-form-XnAhQWxS.js → fortran-fixed-form-BCH9DAIJ.js} +1 -1
- package/dist/web/assets/{fsharp-CdNvy0PG.js → fsharp-C93NYKYD.js} +1 -1
- package/dist/web/assets/{gdresource-DxuG5i8i.js → gdresource-BcIEE2eX.js} +1 -1
- package/dist/web/assets/{git-commit-3lMonsur.js → git-commit-BVjlXEy8.js} +1 -1
- package/dist/web/assets/{git-log-panel-Co0PBPHC.js → git-log-panel-2_4HuP47.js} +1 -1
- package/dist/web/assets/{git-rebase-N8Z9kIMf.js → git-rebase-Bj_21B1V.js} +1 -1
- package/dist/web/assets/gitGraph-HDMCJU4V-B72vcb2r.js +1 -0
- package/dist/web/assets/glide-data-grid-B0IY6n_Q.js +138 -0
- package/dist/web/assets/{glimmer-js-Dp9OXiib.js → glimmer-js-C20yj4Zv.js} +1 -1
- package/dist/web/assets/{glimmer-ts-CDVKBcDj.js → glimmer-ts-ipbYC7kh.js} +1 -1
- package/dist/web/assets/{glsl-DPJxI4us.js → glsl-Dovazu3t.js} +1 -1
- package/dist/web/assets/{graphql-BrFhaQQl.js → graphql-DpMlM7hC.js} +1 -1
- package/dist/web/assets/{group-chat-tab-rOd8J8GC.js → group-chat-tab-DRLDHOp6.js} +1 -1
- package/dist/web/assets/{hack-BzXbDMlA.js → hack-gc7LCBuV.js} +1 -1
- package/dist/web/assets/{haml-CPpkX0s5.js → haml-vtlFm9gm.js} +1 -1
- package/dist/web/assets/{handlebars-BqrApy52.js → handlebars-DGKhpCji.js} +1 -1
- package/dist/web/assets/{html-DmjUl-OA.js → html-DvfhQbXb.js} +1 -1
- package/dist/web/assets/{html-derivative-Cnd6XFR5.js → html-derivative-C3oTSSCN.js} +1 -1
- package/dist/web/assets/{http-DMLWYun2.js → http-SG6zLTo7.js} +1 -1
- package/dist/web/assets/{hurl-CKkCVxbj.js → hurl-BWXsYlqW.js} +1 -1
- package/dist/web/assets/{hxml-CAx19TtQ.js → hxml-DUdMzaoh.js} +1 -1
- package/dist/web/assets/{image-preview-DHUoylQ1.js → image-preview-DxgFOV1T.js} +1 -1
- package/dist/web/assets/index-CBn4SOoT.js +52 -0
- package/dist/web/assets/index-DWpNR3nB.css +2 -0
- package/dist/web/assets/info-3K5VOQVL-3irPxRK_.js +1 -0
- package/dist/web/assets/{input-DcEk7mA3.js → input-DuAF-Stj.js} +1 -1
- package/dist/web/assets/{jinja-BmB9YN9l.js → jinja-955w9RKM.js} +1 -1
- package/dist/web/assets/{jison-BaVsKKpw.js → jison-WWfqPo50.js} +1 -1
- package/dist/web/assets/{julia-BgVBLveX.js → julia-BFrfnaNl.js} +1 -1
- package/dist/web/assets/{just-C2ENIbl9.js → just-BrZdyR_I.js} +1 -1
- package/dist/web/assets/{keybindings-store-BGIyqXHI.js → keybindings-store-0Wqfa7Qp.js} +1 -1
- package/dist/web/assets/keybindings-store-d54pv2NK.js +1 -0
- package/dist/web/assets/{latex-BiDIWxKL.js → latex-CwtPPASD.js} +1 -1
- package/dist/web/assets/{liquid-NxpapreE.js → liquid-CYZuvDDd.js} +1 -1
- package/dist/web/assets/{lua-DVepQvwH.js → lua-BV095ZyY.js} +1 -1
- package/dist/web/assets/markdown-renderer-BTS8ifdu.js +1 -0
- package/dist/web/assets/{markdown-renderer-DlcDhgrF.js → markdown-renderer-CnRcKK3d.js} +3 -3
- package/dist/web/assets/{marko-CJ2606Xl.js → marko-CNeljZ1C.js} +1 -1
- package/dist/web/assets/{mdc-D2bjqclE.js → mdc-JfGapShy.js} +1 -1
- package/dist/web/assets/{media-url-H17XJF-I.js → media-url-Bm4PsduE.js} +1 -1
- package/dist/web/assets/{mobile-bottom-sheet-g-r2hCFa.js → mobile-bottom-sheet-M5iZDX7y.js} +1 -1
- package/dist/web/assets/mobile-explorer-sheet-BqK2-WuN.js +1 -0
- package/dist/web/assets/{nextflow-BtJwUbfF.js → nextflow-DD5C8nqX.js} +1 -1
- package/dist/web/assets/{nginx-j4gyIhHE.js → nginx-Ca7B__x_.js} +1 -1
- package/dist/web/assets/{nim-ClH_gjP5.js → nim-B8FogsDw.js} +1 -1
- package/dist/web/assets/notification-store-Yvy1I8gd.js +1 -0
- package/dist/web/assets/{number-overlay-editor-C1EqJnWq.js → number-overlay-editor-DG9xJwEG.js} +1 -1
- package/dist/web/assets/{overview-panel-vTeeJYVZ.js → overview-panel-s53bnl0q.js} +1 -1
- package/dist/web/assets/packet-RMMSAZCW-Z5jWjFCV.js +1 -0
- package/dist/web/assets/{panel-store-BSnkjgHt.js → panel-store-B4rijFKN.js} +1 -1
- package/dist/web/assets/{pdf-preview-CqFGRY0Z.js → pdf-preview-DYt3aBzM.js} +1 -1
- package/dist/web/assets/{perl-C9H7X7CT.js → perl-BR78hS8R.js} +1 -1
- package/dist/web/assets/{php-Bx2U-cQ_.js → php-DXBOMC9z.js} +1 -1
- package/dist/web/assets/pie-UPGHQEXC-Bq7UMi8P.js +1 -0
- package/dist/web/assets/{postgres-viewer-DHwcQucn.js → postgres-viewer-BvoWSuoZ.js} +3 -3
- package/dist/web/assets/{process-table-BGRJNlpn.js → process-table-BYwKigiD.js} +1 -1
- package/dist/web/assets/{project-store--nvQiy75.js → project-store-BuY7rxn_.js} +1 -1
- package/dist/web/assets/{pug-Cw74sKsE.js → pug-CvTwVVKV.js} +1 -1
- package/dist/web/assets/{qml-BXD94Eqz.js → qml-CPSoZ1-B.js} +1 -1
- package/dist/web/assets/radar-KQ55EAFF-BLo4BOTD.js +1 -0
- package/dist/web/assets/{razor-DZ0-Ge0S.js → razor-BUA1YKtF.js} +1 -1
- package/dist/web/assets/{rst-Dtdh0QUj.js → rst-BJsq7ISz.js} +1 -1
- package/dist/web/assets/{ruby-BC51BW2Q.js → ruby-DSDMeYf5.js} +1 -1
- package/dist/web/assets/{run-in-terminal-Sd3KyjN4.js → run-in-terminal-C9xpskFn.js} +1 -1
- package/dist/web/assets/{sas-BN8i4qOU.js → sas-B1nJOjbN.js} +1 -1
- package/dist/web/assets/{scroll-area-0gljZ6lF.js → scroll-area-DBcG1fQo.js} +1 -1
- package/dist/web/assets/{scss-H-QtA7Rz.js → scss-BZFyRiQn.js} +1 -1
- package/dist/web/assets/{send-to-chat-u6m8l-rH.js → send-to-chat-BIg70MUZ.js} +1 -1
- package/dist/web/assets/{settings-store-CHY6Kzin.js → settings-store-GV5pkkke.js} +2 -2
- package/dist/web/assets/{settings-tab-IY6K1MiZ.js → settings-tab-BePvIcjd.js} +1 -1
- package/dist/web/assets/settings-tab-Br-lJSPa.js +1 -0
- package/dist/web/assets/{shaderlab-CalNsj_x.js → shaderlab-laINRXBo.js} +1 -1
- package/dist/web/assets/{shellsession-BFrcoR8x.js → shellsession-BpOOvWVR.js} +1 -1
- package/dist/web/assets/{soy-CNbku7vP.js → soy-BW4d91Sa.js} +1 -1
- package/dist/web/assets/{sparql-BN_orcVp.js → sparql-BsvvyoHn.js} +1 -1
- package/dist/web/assets/{sql-query-editor-C6pC3I8l.js → sql-query-editor-qQce5QJ6.js} +1 -1
- package/dist/web/assets/{sqlite-viewer-DTr5PzUb.js → sqlite-viewer-yhc0YNvu.js} +1 -1
- package/dist/web/assets/{stata-C6a5Ijzq.js → stata-K-dZInUt.js} +1 -1
- package/dist/web/assets/{surrealql-ClplI_HY.js → surrealql-CpNp2sgf.js} +1 -1
- package/dist/web/assets/{svelte-DNm-UNXB.js → svelte-BG6iBA8R.js} +1 -1
- package/dist/web/assets/{switch-DKvKya9y.js → switch-_NcrktLe.js} +1 -1
- package/dist/web/assets/system-monitor-body-D8Z5QXBB.js +2 -0
- package/dist/web/assets/system-monitor-tab-BclYXFTe.js +1 -0
- package/dist/web/assets/{system-monitor-window-content-BUqRsPK2.js → system-monitor-window-content-CaOhD0AU.js} +1 -1
- package/dist/web/assets/{tab-host-window-content-BnqGPu8a.js → tab-host-window-content-f_Rc5rJK.js} +1 -1
- package/dist/web/assets/{tab-store-CJuJRapl.js → tab-store-tFnyPmm4.js} +1 -1
- package/dist/web/assets/team-member-sheet-QDHoYCs0.js +2 -0
- package/dist/web/assets/{team-member-window-content-T4Q5JI-G.js → team-member-window-content-B1jkKkDi.js} +1 -1
- package/dist/web/assets/{templ-CSdqVobu.js → templ-gxNKXmt3.js} +1 -1
- package/dist/web/assets/{terminal-tab-Bb2rZegQ.js → terminal-tab-UvwM0sty.js} +3 -3
- package/dist/web/assets/{tex-DzSJ4kcZ.js → tex-C0ON27g5.js} +1 -1
- package/dist/web/assets/{tool-cards-lhqhrDTT.js → tool-cards-jB7GT-wj.js} +4 -4
- package/dist/web/assets/treemap-KZPCXAKY-dyrE6SW2.js +1 -0
- package/dist/web/assets/{ts-tags-C28w3bTg.js → ts-tags-BX_CTVgQ.js} +1 -1
- package/dist/web/assets/{twig-i5jY3QXB.js → twig-CwL7XnU0.js} +1 -1
- package/dist/web/assets/{use-blob-url-Dsq9OjTh.js → use-blob-url-DcRcjNTE.js} +1 -1
- package/dist/web/assets/use-coarse-long-press-BmI_GVW5.js +1 -0
- package/dist/web/assets/{use-monaco-theme-BZvlsoBv.js → use-monaco-theme--9tOOkDA.js} +1 -1
- package/dist/web/assets/{use-open-team-member-DkiEjFYE.js → use-open-team-member-1hRsHLKg.js} +1 -1
- package/dist/web/assets/{use-websocket-B8R50f7f.js → use-websocket-rxJLbFqy.js} +1 -1
- package/dist/web/assets/{vendor-mermaid-By4AVvJY.js → vendor-mermaid-CHTa6D69.js} +1 -1
- package/dist/web/assets/video-preview-DMhnf2Gi.js +1 -0
- package/dist/web/assets/{vue-Ceyet_lv.js → vue-Bykm6wSS.js} +1 -1
- package/dist/web/assets/{vue-html-GuU7g_hg.js → vue-html-CETdK_iV.js} +1 -1
- package/dist/web/assets/{vue-vine-CxXoaJr2.js → vue-vine-DiJb6fO5.js} +1 -1
- package/dist/web/assets/{window-store-CsEW6jiE.js → window-store-CQ1lghvv.js} +1 -1
- package/dist/web/assets/{xml-CbqOVhkP.js → xml-BNw8J5YW.js} +1 -1
- package/dist/web/assets/{xsl-KfAmCauy.js → xsl-CsG9L31b.js} +1 -1
- package/dist/web/index.html +46 -45
- package/dist/web/sw.js +1 -1
- package/docs/architecture/ai-chat-and-providers.md +309 -0
- package/docs/architecture/data-and-storage.md +356 -0
- package/docs/architecture/extensions.md +496 -0
- package/docs/architecture/integrations.md +214 -0
- package/docs/architecture/workspace-and-ui.md +391 -0
- package/docs/claude-agent-sdk-reference.md +1 -1
- package/docs/code-patterns.md +361 -0
- package/docs/code-standards.md +8 -358
- package/docs/codebase-subsystems.md +364 -0
- package/docs/codebase-summary.md +34 -379
- package/docs/deployment-guide.md +280 -490
- package/docs/design-guidelines.md +1 -1
- package/docs/lessons-learned.md +27 -10
- package/docs/project-changelog.md +18 -806
- package/docs/project-overview-pdr.md +117 -111
- package/docs/project-roadmap.md +89 -133
- package/docs/system-architecture.md +77 -1826
- package/package.json +2 -2
- package/src/cli/commands/autostart.ts +2 -2
- package/src/cli/commands/config-cmd.ts +12 -3
- package/src/cli/commands/status.ts +3 -2
- package/src/cli/commands/stop.ts +32 -4
- package/src/server/index.ts +17 -3
- package/src/server/routes/chat-unread.ts +36 -0
- package/src/server/routes/named-tunnel.ts +132 -0
- package/src/server/routes/tunnel.ts +13 -0
- package/src/server/ws/chat.ts +5 -2
- package/src/services/autostart-register.ts +47 -29
- package/src/services/cloud.service.ts +26 -1
- package/src/services/config-secret-keys.ts +48 -0
- package/src/services/config.service.ts +1 -1
- package/src/services/db.service.ts +62 -12
- package/src/services/extension-rpc-handlers.ts +9 -1
- package/src/services/file-watcher/watch-tree.ts +67 -33
- package/src/services/file-watcher.service.ts +28 -10
- package/src/services/fs-credential-path-guard.ts +103 -0
- package/src/services/fs-path-guard.service.ts +14 -66
- package/src/services/named-tunnel/cloudflare-dns-api.ts +40 -0
- package/src/services/named-tunnel/cloudflare-zone-api.ts +28 -0
- package/src/services/named-tunnel/cloudflared-cert.ts +95 -0
- package/src/services/named-tunnel/cloudflared-exec.ts +50 -0
- package/src/services/named-tunnel/cloudflared-login-helpers.ts +98 -0
- package/src/services/named-tunnel/cloudflared-login.service.ts +182 -0
- package/src/services/named-tunnel/hostname-rules.ts +58 -0
- package/src/services/named-tunnel/login-output-parser.ts +36 -0
- package/src/services/named-tunnel/named-tunnel-args.ts +110 -0
- package/src/services/named-tunnel/named-tunnel-config.ts +67 -0
- package/src/services/named-tunnel/named-tunnel-probe-state.ts +95 -0
- package/src/services/named-tunnel/named-tunnel-readiness.ts +59 -0
- package/src/services/named-tunnel/named-tunnel-runtime.ts +42 -0
- package/src/services/named-tunnel/named-tunnel-setup-confirm.ts +98 -0
- package/src/services/named-tunnel/named-tunnel-setup.service.ts +191 -0
- package/src/services/supervisor-state.ts +67 -2
- package/src/services/supervisor.ts +454 -157
- package/src/services/tunnel-registry-parse.ts +27 -0
- package/src/services/tunnel-registry.service.ts +2 -15
- package/src/services/tunnel.service.ts +12 -3
- package/src/types/config.ts +31 -0
- package/src/web/app.tsx +5 -0
- package/src/web/components/chat/chat-history-bar.tsx +95 -98
- package/src/web/components/chat/chat-toolbar-overflow-menu.tsx +57 -0
- package/src/web/components/chat/session-debug-dialog.tsx +35 -27
- package/src/web/components/layout/cloud-share-named-tunnel-row.tsx +111 -0
- package/src/web/components/layout/cloud-share-popover.tsx +56 -14
- package/src/web/components/shared/connection-lost-overlay.tsx +44 -5
- package/src/web/components/tunnels/named-tunnel/hostname-validation.ts +14 -0
- package/src/web/components/tunnels/named-tunnel/named-tunnel-copy.ts +96 -0
- package/src/web/components/tunnels/named-tunnel/named-tunnel-hostname-field.tsx +51 -0
- package/src/web/components/tunnels/named-tunnel/named-tunnel-login-step.tsx +105 -0
- package/src/web/components/tunnels/named-tunnel/named-tunnel-section.tsx +159 -0
- package/src/web/components/tunnels/named-tunnel/named-tunnel-setup-content.tsx +197 -0
- package/src/web/components/tunnels/named-tunnel/named-tunnel-setup-popup.tsx +57 -0
- package/src/web/components/tunnels/named-tunnel/named-tunnel-step-reducer.ts +191 -0
- package/src/web/components/tunnels/named-tunnel/use-named-tunnel-setup.ts +212 -0
- package/src/web/components/tunnels/tunnel-manager-tab.tsx +4 -0
- package/src/web/hooks/use-global-events.ts +3 -1
- package/src/web/lib/api-named-tunnel.ts +54 -0
- package/src/web/lib/last-known-local-url.ts +23 -0
- package/src/web/stores/notification-store.ts +20 -1
- package/.spike/cdp-client.ts +0 -116
- package/.spike/cleanup-ppm-workspace.mjs +0 -44
- package/.spike/group-protected-probe.ts +0 -21
- package/.spike/pip-eval.ts +0 -17
- package/.spike/pip-page-helpers.js +0 -119
- package/.spike/pip-results-editor-glue.json +0 -105
- package/.spike/pip-results-editor.json +0 -158
- package/.spike/pip-results-input-isolation.json +0 -28
- package/.spike/pip-results-key-probe.json +0 -58
- package/.spike/pip-results-listener-survival.json +0 -98
- package/.spike/pip-results-listeners.json +0 -36
- package/.spike/pip-results-pagehide.json +0 -92
- package/.spike/pip-results-resize.json +0 -104
- package/.spike/pip-results-terminal-debug.json +0 -99
- package/.spike/pip-results-terminal-v2.json +0 -191
- package/.spike/pip-results-terminal.json +0 -220
- package/.spike/pip-results-xterm-trace.json +0 -73
- package/.spike/pip-spike-common.ts +0 -83
- package/.spike/pip-spike-editor-glue.ts +0 -82
- package/.spike/pip-spike-editor.ts +0 -129
- package/.spike/pip-spike-input-isolation.ts +0 -38
- package/.spike/pip-spike-key-probe.ts +0 -34
- package/.spike/pip-spike-listener-survival.ts +0 -54
- package/.spike/pip-spike-listeners.ts +0 -19
- package/.spike/pip-spike-pagehide.ts +0 -59
- package/.spike/pip-spike-resize.ts +0 -42
- package/.spike/pip-spike-setup.ts +0 -63
- package/.spike/pip-spike-terminal-debug.ts +0 -81
- package/.spike/pip-spike-terminal-v2.ts +0 -139
- package/.spike/pip-spike-terminal.ts +0 -169
- package/.spike/pip-spike-xterm-trace.ts +0 -36
- package/.spike/probe-drag-memo-error.mjs +0 -67
- package/.spike/read-dev-db.ts +0 -15
- package/.spike/s.err +0 -63
- package/.spike/scratch-editor-target.ts +0 -7
- package/.spike/smoke-unified-chrome-pip.mjs +0 -353
- package/.spike/tunnel.err +0 -63
- package/.spike/vite-restart.err +0 -663
- package/.spike/w.err +0 -571
- package/dist/web/assets/api-client-DTZEgjBQ.js +0 -1
- package/dist/web/assets/api-settings-kd1j4iR8.js +0 -1
- package/dist/web/assets/architecture-PBZL5I3N-8dCMT9r7.js +0 -1
- package/dist/web/assets/chat-tab-E3bf_V8X.js +0 -15
- package/dist/web/assets/code-editor-BUlM2gXk.js +0 -10
- package/dist/web/assets/explorer-body-9aBmyVpZ.js +0 -2
- package/dist/web/assets/explorer-window-content-DRtqoSPA.js +0 -1
- package/dist/web/assets/gitGraph-HDMCJU4V-2e_8dfbs.js +0 -1
- package/dist/web/assets/glide-data-grid-C4_zIneN.js +0 -138
- package/dist/web/assets/index-BImUaigO.js +0 -52
- package/dist/web/assets/index-CSfi6DSU.css +0 -2
- package/dist/web/assets/info-3K5VOQVL-BZi1Gha1.js +0 -1
- package/dist/web/assets/keybindings-store-CzV2sPls.js +0 -1
- package/dist/web/assets/markdown-renderer-CcbR33VG.js +0 -1
- package/dist/web/assets/mobile-explorer-sheet-SIwQXlwA.js +0 -1
- package/dist/web/assets/notification-store-DV5QtUTg.js +0 -1
- package/dist/web/assets/packet-RMMSAZCW-o5htEcin.js +0 -1
- package/dist/web/assets/pie-UPGHQEXC-BXAIFSAD.js +0 -1
- package/dist/web/assets/radar-KQ55EAFF-Dbt2Aebl.js +0 -1
- package/dist/web/assets/settings-tab-Dic6TKkU.js +0 -1
- package/dist/web/assets/system-monitor-body-iwGiCns9.js +0 -2
- package/dist/web/assets/system-monitor-tab-DdXQhEel.js +0 -1
- package/dist/web/assets/team-member-sheet-LkAFSCvb.js +0 -2
- package/dist/web/assets/treemap-KZPCXAKY-DUbnl9dz.js +0 -1
- package/dist/web/assets/video-preview-m0-3p7QZ.js +0 -1
- /package/dist/web/assets/{abap-C6nB04tn.js → abap-DGlrX_8G.js} +0 -0
- /package/dist/web/assets/{actionscript-3-Vx4rw2sC.js → actionscript-3-CUqRtUJE.js} +0 -0
- /package/dist/web/assets/{ada-Ccd8vM20.js → ada-CY3Spa33.js} +0 -0
- /package/dist/web/assets/{andromeeda-DnBX5xMg.js → andromeeda-Lxs2TJn7.js} +0 -0
- /package/dist/web/assets/{apache-B-9_sx0g.js → apache-DfxgGdgM.js} +0 -0
- /package/dist/web/assets/{apex-_wPVBYoL.js → apex-QVDF1dnI.js} +0 -0
- /package/dist/web/assets/{api-client-aQb5hHE5.js → api-client-oY1tC3tM.js} +0 -0
- /package/dist/web/assets/{applescript-CcvD-qr0.js → applescript-pwJ8QXh-.js} +0 -0
- /package/dist/web/assets/{apply-theme-BeLRfsSu.js → apply-theme-B_bMVL6a.js} +0 -0
- /package/dist/web/assets/{ara-C40Ztoms.js → ara-mPjeX5YX.js} +0 -0
- /package/dist/web/assets/{asciidoc-CybYkJV4.js → asciidoc-Bf7LsDkI.js} +0 -0
- /package/dist/web/assets/{asm-9eOKwzR0.js → asm-rRKC1OUx.js} +0 -0
- /package/dist/web/assets/{aurora-x-B5ZH4t7t.js → aurora-x-DwQr0DkG.js} +0 -0
- /package/dist/web/assets/{awk-Dqilob-2.js → awk-Bpt768fN.js} +0 -0
- /package/dist/web/assets/{ayu-dark-CPgRhf5r.js → ayu-dark-D9lwQHMs.js} +0 -0
- /package/dist/web/assets/{ayu-light-Do06Q52f.js → ayu-light-B4-ptrU5.js} +0 -0
- /package/dist/web/assets/{ayu-mirage-_BhxcrxY.js → ayu-mirage-DAyRzH5Q.js} +0 -0
- /package/dist/web/assets/{ballerina-DDwK54QW.js → ballerina-Cgdpj1HC.js} +0 -0
- /package/dist/web/assets/{bat-BGyGlzGk.js → bat-4FrN36S2.js} +0 -0
- /package/dist/web/assets/{beancount-CRWBdapI.js → beancount-DkcxQER3.js} +0 -0
- /package/dist/web/assets/{berry-DbSFn2gO.js → berry-Dnuut-Ml.js} +0 -0
- /package/dist/web/assets/{bibtex-QpsV9gm9.js → bibtex-CCDwmbuA.js} +0 -0
- /package/dist/web/assets/{bicep-CxS8CUve.js → bicep-BC0ryoGM.js} +0 -0
- /package/dist/web/assets/{bird2-CuZhQzYR.js → bird2-C50V_A-0.js} +0 -0
- /package/dist/web/assets/{c-9bnDqE3g.js → c-Ddorhq0U.js} +0 -0
- /package/dist/web/assets/{c3-JMZTrOhA.js → c3-DdIf5r9E.js} +0 -0
- /package/dist/web/assets/{cadence-DsDNayJS.js → cadence-s9pd1Wng.js} +0 -0
- /package/dist/web/assets/{can-open-in-ppm-BJfpynya.js → can-open-in-ppm-C6hZV1OP.js} +0 -0
- /package/dist/web/assets/{catppuccin-frappe-DYIKXXBe.js → catppuccin-frappe-CzJNTyu-.js} +0 -0
- /package/dist/web/assets/{catppuccin-latte-IYYOnUJ8.js → catppuccin-latte-BNpt-m7s.js} +0 -0
- /package/dist/web/assets/{catppuccin-macchiato-BrJ_7mfS.js → catppuccin-macchiato-FYGkfsJ5.js} +0 -0
- /package/dist/web/assets/{catppuccin-mocha-gzSu7v7-.js → catppuccin-mocha-it2g5D1q.js} +0 -0
- /package/dist/web/assets/{clarity-DLzsC0Hb.js → clarity-BVFBTjMe.js} +0 -0
- /package/dist/web/assets/{clipboard-7fw0Shic.js → clipboard-BWznymz7.js} +0 -0
- /package/dist/web/assets/{clojure-DS1BvoTt.js → clojure-BSYvXMI8.js} +0 -0
- /package/dist/web/assets/{cmake-CDvsJwYp.js → cmake-DGEqH-Np.js} +0 -0
- /package/dist/web/assets/{codeowners-BjsYiflJ.js → codeowners-D8FCOxWg.js} +0 -0
- /package/dist/web/assets/{codeql-CG-7ARat.js → codeql-COV0eluG.js} +0 -0
- /package/dist/web/assets/{common-lisp-DSO1Lbh9.js → common-lisp-xHnZUlgt.js} +0 -0
- /package/dist/web/assets/{coq-DYdh3oP_.js → coq-Cs_2i3Xg.js} +0 -0
- /package/dist/web/assets/{csharp-DxEBz5s0.js → csharp-B1ONB4PT.js} +0 -0
- /package/dist/web/assets/{css-dal3Q-8C.js → css-BgGQbvrZ.js} +0 -0
- /package/dist/web/assets/{csv-CpqjMGiA.js → csv-CNHmQBzs.js} +0 -0
- /package/dist/web/assets/{csv-parser-3umBA4NY.js → csv-parser-DWR24J17.js} +0 -0
- /package/dist/web/assets/{cue-DinoJ_5k.js → cue-ZXAKzwIy.js} +0 -0
- /package/dist/web/assets/{cypher-DzxqmkUW.js → cypher-4PL5bmT5.js} +0 -0
- /package/dist/web/assets/{d-BxNwJuEC.js → d-CEsV3RT2.js} +0 -0
- /package/dist/web/assets/{dark-plus-Clmv3V-0.js → dark-plus-NtFnYSDz.js} +0 -0
- /package/dist/web/assets/{dart-BWVtXD35.js → dart-CKHn4mDf.js} +0 -0
- /package/dist/web/assets/{data-grid-types-B4n51Fck.js → data-grid-types-CxU8oo-j.js} +0 -0
- /package/dist/web/assets/{dax-DsImuWgJ.js → dax-Cmkj1I_M.js} +0 -0
- /package/dist/web/assets/{desktop-B0jJuG2r.js → desktop-DJLalvPQ.js} +0 -0
- /package/dist/web/assets/{diff-CWqAAxoE.js → diff-BnS2wpj6.js} +0 -0
- /package/dist/web/assets/{dist-C0eNNfbt.js → dist-CuIdRyUB.js} +0 -0
- /package/dist/web/assets/{dist-B-EXdSYE.js → dist-uYjs3Wv6.js} +0 -0
- /package/dist/web/assets/{docker-CYFCJdIL.js → docker-CovNy7ml.js} +0 -0
- /package/dist/web/assets/{dotenv-CKDUjURg.js → dotenv-Gh4w3I6B.js} +0 -0
- /package/dist/web/assets/{dracula-CSoPspHE.js → dracula-NF0tAHXl.js} +0 -0
- /package/dist/web/assets/{dracula-soft-BuFjw5L1.js → dracula-soft-Cj_qBurK.js} +0 -0
- /package/dist/web/assets/{dream-maker-B6PdDRZu.js → dream-maker-CRuZPcl7.js} +0 -0
- /package/dist/web/assets/{emacs-lisp-CMcXvD0G.js → emacs-lisp-BACmC9qj.js} +0 -0
- /package/dist/web/assets/{everforest-dark-cU8-wYzi.js → everforest-dark-Dd9av4QG.js} +0 -0
- /package/dist/web/assets/{everforest-light-KhorllqK.js → everforest-light-C-jsss-B.js} +0 -0
- /package/dist/web/assets/{external-link-B8BynhvY.js → external-link-B6Hl0U4X.js} +0 -0
- /package/dist/web/assets/{fennel-BCELZK87.js → fennel-BJA9XnL8.js} +0 -0
- /package/dist/web/assets/{file-exclamation-point-CZ4DiR75.js → file-exclamation-point-JzhTU2TX.js} +0 -0
- /package/dist/web/assets/{fish-BQc0y_jy.js → fish-CKlhNSc2.js} +0 -0
- /package/dist/web/assets/{fluent-BTINnwF6.js → fluent-wfglRk5D.js} +0 -0
- /package/dist/web/assets/{folder-symlink-B8XrtvQK.js → folder-symlink-Dx1hOk8X.js} +0 -0
- /package/dist/web/assets/{format-bytes-WVcFxJuT.js → format-bytes-utwHMTry.js} +0 -0
- /package/dist/web/assets/{fortran-free-form-BQim9wDz.js → fortran-free-form-BlXCdid3.js} +0 -0
- /package/dist/web/assets/{gdscript-03w5u8un.js → gdscript-BwAVG6Et.js} +0 -0
- /package/dist/web/assets/{gdshader-Dp2daNzU.js → gdshader-DPc_T7ib.js} +0 -0
- /package/dist/web/assets/{genie-CoNcjPiD.js → genie-B-zZSLCX.js} +0 -0
- /package/dist/web/assets/{gherkin-NrPOSPQL.js → gherkin-CJ0ajpGs.js} +0 -0
- /package/dist/web/assets/{github-dark-z4RE9ZqA.js → github-dark-Dz8ZkzSP.js} +0 -0
- /package/dist/web/assets/{github-dark-default-DOKw-1cI.js → github-dark-default-CNUYo_kp.js} +0 -0
- /package/dist/web/assets/{github-dark-dimmed-DJRNMkEA.js → github-dark-dimmed-241z_Ycx.js} +0 -0
- /package/dist/web/assets/{github-dark-high-contrast-Bj7jJ_Gs.js → github-dark-high-contrast-7r6yZZYH.js} +0 -0
- /package/dist/web/assets/{github-light-B4k_yMFu.js → github-light-C8gmZn-D.js} +0 -0
- /package/dist/web/assets/{github-light-default-BHc-Uzhs.js → github-light-default-GAEgq1eA.js} +0 -0
- /package/dist/web/assets/{github-light-high-contrast-CHisIywL.js → github-light-high-contrast-3z91352E.js} +0 -0
- /package/dist/web/assets/{gleam-CfbypZ4q.js → gleam-C7vxW5zd.js} +0 -0
- /package/dist/web/assets/{gn-YoAjyhJa.js → gn-CyJIXwHP.js} +0 -0
- /package/dist/web/assets/{gnuplot-xVkc1f1c.js → gnuplot-CqLbGgPd.js} +0 -0
- /package/dist/web/assets/{go-GPCwP3Gu.js → go-DdDcK9aX.js} +0 -0
- /package/dist/web/assets/{groovy-Crh4Yww9.js → groovy-UYHggEqH.js} +0 -0
- /package/dist/web/assets/{gruvbox-dark-hard-BluUFuDS.js → gruvbox-dark-hard-B4ierkJn.js} +0 -0
- /package/dist/web/assets/{gruvbox-dark-medium-Cxk1FWQp.js → gruvbox-dark-medium-DYwkDSZ6.js} +0 -0
- /package/dist/web/assets/{gruvbox-dark-soft-CHXMiFmj.js → gruvbox-dark-soft-CVL4P-Lz.js} +0 -0
- /package/dist/web/assets/{gruvbox-light-hard-B6eKPjAD.js → gruvbox-light-hard-BJ0LewUZ.js} +0 -0
- /package/dist/web/assets/{gruvbox-light-medium-pDwMm1ut.js → gruvbox-light-medium-CaqqjeGJ.js} +0 -0
- /package/dist/web/assets/{gruvbox-light-soft-Cxu6kHqK.js → gruvbox-light-soft-ByKMoVNr.js} +0 -0
- /package/dist/web/assets/{haskell-C6JKHjbK.js → haskell-BilYRVPp.js} +0 -0
- /package/dist/web/assets/{haxe-BuBNdF0a.js → haxe-Brs9Bj1s.js} +0 -0
- /package/dist/web/assets/{hcl-DZpDdGj2.js → hcl-ClrZpol-.js} +0 -0
- /package/dist/web/assets/{hjson-CBkhYRuo.js → hjson-9PvHnYMX.js} +0 -0
- /package/dist/web/assets/{hlsl-C5nMxnp9.js → hlsl-BbBk4vqV.js} +0 -0
- /package/dist/web/assets/{horizon-VAFvA6R6.js → horizon-E5Py0cny.js} +0 -0
- /package/dist/web/assets/{horizon-bright-BC0xn7T3.js → horizon-bright-DVCsNGEk.js} +0 -0
- /package/dist/web/assets/{houston-BxrUivmz.js → houston-JdFEax9Y.js} +0 -0
- /package/dist/web/assets/{hy-DLtOXoaH.js → hy-W_W3tLKT.js} +0 -0
- /package/dist/web/assets/{image-gallery-Gnf7TdCR.js → image-gallery-5IURd6db.js} +0 -0
- /package/dist/web/assets/{imba-BdpFXM2W.js → imba-CfAqJz7T.js} +0 -0
- /package/dist/web/assets/{ini-BInJO_T0.js → ini-C_3gvKWs.js} +0 -0
- /package/dist/web/assets/{java-Dxuddnkb.js → java-CKqtXZ-j.js} +0 -0
- /package/dist/web/assets/{javascript-CVamJfLY.js → javascript-C7gSEfae.js} +0 -0
- /package/dist/web/assets/{json-BLZ0ozYk.js → json-BoN6e11T.js} +0 -0
- /package/dist/web/assets/{json5-BnXzmMKs.js → json5-CgE7C8HW.js} +0 -0
- /package/dist/web/assets/{jsonc-CSgkSga7.js → jsonc-DjyoattY.js} +0 -0
- /package/dist/web/assets/{jsonl-CY5W2nF2.js → jsonl-lI82wGSw.js} +0 -0
- /package/dist/web/assets/{jsonnet-CEJYH3sF.js → jsonnet-CszEI8va.js} +0 -0
- /package/dist/web/assets/{jssm-CsJc7Uhk.js → jssm-CZXDlszb.js} +0 -0
- /package/dist/web/assets/{jsx-jCiRaHU7.js → jsx-BeRz0eEz.js} +0 -0
- /package/dist/web/assets/{kanagawa-dragon-DfoA_GxX.js → kanagawa-dragon-BOmnUiyd.js} +0 -0
- /package/dist/web/assets/{kanagawa-lotus-BOLYJpWd.js → kanagawa-lotus-ffU_P5w-.js} +0 -0
- /package/dist/web/assets/{kanagawa-wave-DfKlbT1G.js → kanagawa-wave-DKTJZrMu.js} +0 -0
- /package/dist/web/assets/{kdl-CmssIFTi.js → kdl-BWECJveH.js} +0 -0
- /package/dist/web/assets/{kotlin-BRsNgp6x.js → kotlin-DpVwBCSt.js} +0 -0
- /package/dist/web/assets/{kusto-T8X9jUab.js → kusto-BgVqjUZA.js} +0 -0
- /package/dist/web/assets/{laserwave-DkJMVJ8Z.js → laserwave-CEVCi8em.js} +0 -0
- /package/dist/web/assets/{lean-C65KGVPq.js → lean-CGyfRhLJ.js} +0 -0
- /package/dist/web/assets/{less-exIPdDlf.js → less-B0_H10Ku.js} +0 -0
- /package/dist/web/assets/{lib-mC1NZfuw.js → lib-hrC3bruJ.js} +0 -0
- /package/dist/web/assets/{libesm-DSutUtl1.js → libesm-DVpFmwJu.js} +0 -0
- /package/dist/web/assets/{light-plus-DiHUXAZt.js → light-plus-DqzMqPID.js} +0 -0
- /package/dist/web/assets/{llvm-CJBnEzFM.js → llvm-9ucnfNiF.js} +0 -0
- /package/dist/web/assets/{loader-circle-gSPVxfvH.js → loader-circle-Dpqcv0eS.js} +0 -0
- /package/dist/web/assets/{lock-Did-87UV.js → lock-DldbT31x.js} +0 -0
- /package/dist/web/assets/{log-DxMyUMuP.js → log-m6A2dOSj.js} +0 -0
- /package/dist/web/assets/{logo-CC9NKzca.js → logo-ByPcsC9P.js} +0 -0
- /package/dist/web/assets/{luau-Bw10I6zf.js → luau-DFCo8nBn.js} +0 -0
- /package/dist/web/assets/{make-C_6M90m6.js → make-C90w3MeA.js} +0 -0
- /package/dist/web/assets/{markdown-bR9_R-LF.js → markdown-DT0uywZG.js} +0 -0
- /package/dist/web/assets/{material-theme-BUx2Qujn.js → material-theme-BVUO93tJ.js} +0 -0
- /package/dist/web/assets/{material-theme-darker-CRJrPgKm.js → material-theme-darker-xXgGDwnF.js} +0 -0
- /package/dist/web/assets/{material-theme-lighter-CUAYppPa.js → material-theme-lighter-BjStPzWB.js} +0 -0
- /package/dist/web/assets/{material-theme-ocean-DuINF1fg.js → material-theme-ocean-wFmSiKjy.js} +0 -0
- /package/dist/web/assets/{material-theme-palenight-W6_icGCj.js → material-theme-palenight-e-0CtRoe.js} +0 -0
- /package/dist/web/assets/{matlab-rfqn_b3z.js → matlab-BNaNQAUH.js} +0 -0
- /package/dist/web/assets/{mdx-Bh1B_YOJ.js → mdx-DfpVWAqO.js} +0 -0
- /package/dist/web/assets/{mermaid-Dxf6Ya2k.js → mermaid-Bpq7wFCP.js} +0 -0
- /package/dist/web/assets/{min-dark-CivZ2L0h.js → min-dark-CL2Y0WH6.js} +0 -0
- /package/dist/web/assets/{min-light-B1Ykqtma.js → min-light-DOgr_IdP.js} +0 -0
- /package/dist/web/assets/{mipsasm-DynHaM0d.js → mipsasm-C9ie2zlB.js} +0 -0
- /package/dist/web/assets/{mojo-Clw5PbGH.js → mojo-Md2A2sJy.js} +0 -0
- /package/dist/web/assets/{monitor-Dv8vn_6O.js → monitor-4vWfqzuN.js} +0 -0
- /package/dist/web/assets/{monokai-DFIooFZT.js → monokai-nbXIEySB.js} +0 -0
- /package/dist/web/assets/{moonbit-DnBSZWGM.js → moonbit-CJ-T-s4A.js} +0 -0
- /package/dist/web/assets/{move-CCcL2PfL.js → move-DwEehLIK.js} +0 -0
- /package/dist/web/assets/{narrat-BDarg5Lk.js → narrat-CuF4sIKr.js} +0 -0
- /package/dist/web/assets/{nextflow-groovy-DrZOeCNW.js → nextflow-groovy-1dYhfPfq.js} +0 -0
- /package/dist/web/assets/{night-owl-BnZZCK7v.js → night-owl-gZS5mfzY.js} +0 -0
- /package/dist/web/assets/{night-owl-light-CEwBsVHS.js → night-owl-light-DDAster5.js} +0 -0
- /package/dist/web/assets/{nix-amCzOPMR.js → nix-BlbEYs2c.js} +0 -0
- /package/dist/web/assets/{nord-BIs2BC6q.js → nord-BRiPb8Vy.js} +0 -0
- /package/dist/web/assets/{nushell-Y02fo4yw.js → nushell-DgWicB1i.js} +0 -0
- /package/dist/web/assets/{objective-c-7xOZtWW1.js → objective-c-D8mPZ42Y.js} +0 -0
- /package/dist/web/assets/{objective-cpp-eVtjUvVB.js → objective-cpp-B0pNXzuj.js} +0 -0
- /package/dist/web/assets/{ocaml-Bi6ZwqG4.js → ocaml-lQd7aK5d.js} +0 -0
- /package/dist/web/assets/{odin-8xf1Y0S9.js → odin-CxtIOBjm.js} +0 -0
- /package/dist/web/assets/{one-dark-pro-hVv-_y_b.js → one-dark-pro-T_UFnWfe.js} +0 -0
- /package/dist/web/assets/{one-light-CJJ3MtHt.js → one-light-LBVqwyV-.js} +0 -0
- /package/dist/web/assets/{openscad-B2HcywLk.js → openscad-C5dnS6J7.js} +0 -0
- /package/dist/web/assets/{pascal-C7fllV_7.js → pascal-CmWCWQML.js} +0 -0
- /package/dist/web/assets/{pkl-qvLC1IWP.js → pkl-BWWOtDQk.js} +0 -0
- /package/dist/web/assets/{plastic-BT1wHZv2.js → plastic-ekhupckF.js} +0 -0
- /package/dist/web/assets/{play-4MZi1Axp.js → play-CpCAoQRZ.js} +0 -0
- /package/dist/web/assets/{plsql-1MsmdmJD.js → plsql-BPsDHXx4.js} +0 -0
- /package/dist/web/assets/{plus-BhMZqFsN.js → plus-BR0qewJI.js} +0 -0
- /package/dist/web/assets/{po-BigskytD.js → po-BX2FiuW2.js} +0 -0
- /package/dist/web/assets/{poimandres-DuklniF7.js → poimandres-DzXOdZcN.js} +0 -0
- /package/dist/web/assets/{polar-e2pjN_sp.js → polar-DDRXgJzG.js} +0 -0
- /package/dist/web/assets/{portal-container-context-Cm5HipFr.js → portal-container-context-a399Hd9F.js} +0 -0
- /package/dist/web/assets/{postcss-DtAeYjWw.js → postcss-BHW6XBhx.js} +0 -0
- /package/dist/web/assets/{powerquery-Cr2PtehI.js → powerquery-B89c2NBb.js} +0 -0
- /package/dist/web/assets/{powershell-BxFTGLJ4.js → powershell-Dvxrd3Tu.js} +0 -0
- /package/dist/web/assets/{prisma-COWJiwdZ.js → prisma-lMK8EFLU.js} +0 -0
- /package/dist/web/assets/{prolog-DFvGKRx6.js → prolog-D0YrtMG4.js} +0 -0
- /package/dist/web/assets/{proto-CcK80lFt.js → proto-J0mM25aw.js} +0 -0
- /package/dist/web/assets/{puppet-BF60bZ4F.js → puppet-CUT0xkhh.js} +0 -0
- /package/dist/web/assets/{purescript-zL_69MzU.js → purescript-CoJWSGRp.js} +0 -0
- /package/dist/web/assets/{python-CIwKhfb_.js → python-BBrmuz6P.js} +0 -0
- /package/dist/web/assets/{qmldir-CXNe04Lo.js → qmldir-CUtzs4Q7.js} +0 -0
- /package/dist/web/assets/{qss-C8lAWe6G.js → qss-Dm1RZ8aL.js} +0 -0
- /package/dist/web/assets/{r-CL5ZVL3_.js → r-BGP7qZTe.js} +0 -0
- /package/dist/web/assets/{racket-BBfh0uh0.js → racket-K_6U1lqJ.js} +0 -0
- /package/dist/web/assets/{raku-o6E8R5Q3.js → raku-bNSiZeW_.js} +0 -0
- /package/dist/web/assets/{react-CBTnT4sY.js → react-X4jUntEf.js} +0 -0
- /package/dist/web/assets/{red-GomRF2Xp.js → red-uVeIEF0f.js} +0 -0
- /package/dist/web/assets/{refresh-cw-B06yaBrW.js → refresh-cw-B9iv7csb.js} +0 -0
- /package/dist/web/assets/{reg-_ffDIvx9.js → reg-DSm9GWjh.js} +0 -0
- /package/dist/web/assets/{regexp-Bl5sF65W.js → regexp-CljRm_j_.js} +0 -0
- /package/dist/web/assets/{rel-DgMdqDuj.js → rel-d3JcopZg.js} +0 -0
- /package/dist/web/assets/{resolve-theme-CRt_7wpd.js → resolve-theme-DLKmm-lE.js} +0 -0
- /package/dist/web/assets/{riscv-8b3-Ye4X.js → riscv-CJmaELjT.js} +0 -0
- /package/dist/web/assets/{ron-DrmU1KHP.js → ron-D0g9B1rW.js} +0 -0
- /package/dist/web/assets/{rose-pine-C_-E2tF1.js → rose-pine-DOrD2BSH.js} +0 -0
- /package/dist/web/assets/{rose-pine-dawn-DEfhNlFH.js → rose-pine-dawn-CzZQ-LCF.js} +0 -0
- /package/dist/web/assets/{rose-pine-moon-BdvX3gdn.js → rose-pine-moon-CdmsYp7C.js} +0 -0
- /package/dist/web/assets/{rosmsg-B6GhGpd5.js → rosmsg-CmDth6pO.js} +0 -0
- /package/dist/web/assets/{rotate-ccw-COXu_9oj.js → rotate-ccw-DnuPzJRE.js} +0 -0
- /package/dist/web/assets/{rust-DmC97M1-.js → rust-DGdP6jiR.js} +0 -0
- /package/dist/web/assets/{sass-B0tJOHLM.js → sass-Dkgt2FKZ.js} +0 -0
- /package/dist/web/assets/{save-CtIGOjmx.js → save-DxonD4y1.js} +0 -0
- /package/dist/web/assets/{scala-n8zaFOXv.js → scala-BQLTON6C.js} +0 -0
- /package/dist/web/assets/{scheme-BKD9ztBU.js → scheme-DKlxUGCi.js} +0 -0
- /package/dist/web/assets/{sdbl-D8gB5-rS.js → sdbl-C3iZJQeZ.js} +0 -0
- /package/dist/web/assets/{send-BlyNJAzy.js → send-B-t5Mz26.js} +0 -0
- /package/dist/web/assets/{shallow-DYo6goJ4.js → shallow-jwPzEunk.js} +0 -0
- /package/dist/web/assets/{shellscript-BfXlf_Ao.js → shellscript-BRu-ZQAx.js} +0 -0
- /package/dist/web/assets/{shield-check-B0iGUiOK.js → shield-check-CdTiK1j2.js} +0 -0
- /package/dist/web/assets/{shield-off-BNLWBhcq.js → shield-off-DuetkXKM.js} +0 -0
- /package/dist/web/assets/{slack-dark-CylEddse.js → slack-dark-qkm_u2zz.js} +0 -0
- /package/dist/web/assets/{slack-ochin-w8wg8vuC.js → slack-ochin-BP8_8e4m.js} +0 -0
- /package/dist/web/assets/{smalltalk-hiAXA64u.js → smalltalk-Bnz4gt07.js} +0 -0
- /package/dist/web/assets/{snazzy-light-BwlV3Xty.js → snazzy-light-fbPZg5io.js} +0 -0
- /package/dist/web/assets/{solarized-dark-vmNGdykz.js → solarized-dark-CM0vTRoi.js} +0 -0
- /package/dist/web/assets/{solarized-light-DGv_0JXq.js → solarized-light-C4_W9mvs.js} +0 -0
- /package/dist/web/assets/{solidity-Y7QSH0B1.js → solidity-Bz6v1PoD.js} +0 -0
- /package/dist/web/assets/{splunk-BtgpLjHi.js → splunk-DyNxu-0i.js} +0 -0
- /package/dist/web/assets/{sql-CRHYhOia.js → sql-DXRL1gw1.js} +0 -0
- /package/dist/web/assets/{ssh-config-DOqSs3au.js → ssh-config-2z1QHuOG.js} +0 -0
- /package/dist/web/assets/{stylus-crCAEaBT.js → stylus-D4I-VaeY.js} +0 -0
- /package/dist/web/assets/{swift-eE3rT7TC.js → swift-C_2G-tIc.js} +0 -0
- /package/dist/web/assets/{synthwave-84-BWy14LBX.js → synthwave-84-osBjChRP.js} +0 -0
- /package/dist/web/assets/{system-verilog-DC0-DZM4.js → system-verilog-zQP2qPNU.js} +0 -0
- /package/dist/web/assets/{systemd-to5p6N8I.js → systemd-UGfjRSBM.js} +0 -0
- /package/dist/web/assets/{table-Bbc783ko.js → table-FLU8ei8b.js} +0 -0
- /package/dist/web/assets/{talonscript-DoTcU8wm.js → talonscript-C1XrFPwo.js} +0 -0
- /package/dist/web/assets/{tasl-cNZvUs95.js → tasl-B5raVn43.js} +0 -0
- /package/dist/web/assets/{tcl-mZE8sZH8.js → tcl-3-vbeMIc.js} +0 -0
- /package/dist/web/assets/{terraform-CqHPpIfu.js → terraform-a8VXZDm9.js} +0 -0
- /package/dist/web/assets/{text-wrap-CBT4Gxtg.js → text-wrap-B05VGRa-.js} +0 -0
- /package/dist/web/assets/{tokyo-night-Tp2rTIZd.js → tokyo-night-4SRhf-Hz.js} +0 -0
- /package/dist/web/assets/{toml-CU_vscgn.js → toml-B4N0i8wT.js} +0 -0
- /package/dist/web/assets/{trash-2-Bk4yYlck.js → trash-2-CTXlTflF.js} +0 -0
- /package/dist/web/assets/{triangle-alert-B8EYecpe.js → triangle-alert-BRq0VAfd.js} +0 -0
- /package/dist/web/assets/{tsv-ik7iFB9D.js → tsv-DA5k9Lvw.js} +0 -0
- /package/dist/web/assets/{tsx-BMvvMKiv.js → tsx-D9SZ8owC.js} +0 -0
- /package/dist/web/assets/{turtle-DBqKCq9o.js → turtle-BTHTvyY_.js} +0 -0
- /package/dist/web/assets/{typescript-DXJDmMZZ.js → typescript-DYzV9p5L.js} +0 -0
- /package/dist/web/assets/{typespec-CBseCMtZ.js → typespec-BC15eh7F.js} +0 -0
- /package/dist/web/assets/{typst-4oY25U9y.js → typst-BJUqzA6D.js} +0 -0
- /package/dist/web/assets/{use-is-mobile-D1weanbj.js → use-is-mobile-DFWViA4S.js} +0 -0
- /package/dist/web/assets/{utils-BNRH507E.js → utils-C9OjCrou.js} +0 -0
- /package/dist/web/assets/{v-BXaZ_1oy.js → v-50Lps6oA.js} +0 -0
- /package/dist/web/assets/{vala-BImWJE7z.js → vala-8wiUvvrD.js} +0 -0
- /package/dist/web/assets/{vb-CLfj2_sy.js → vb-BlgPLt6B.js} +0 -0
- /package/dist/web/assets/{vendor-xterm-_yyu5n32.js → vendor-xterm-BZOrwF_F.js} +0 -0
- /package/dist/web/assets/{verilog-BWa8Ed2b.js → verilog-CD9pVW5p.js} +0 -0
- /package/dist/web/assets/{vesper-BGj1cg6m.js → vesper-BrivW4PT.js} +0 -0
- /package/dist/web/assets/{vhdl-mByK7mlx.js → vhdl-Bunxfa7N.js} +0 -0
- /package/dist/web/assets/{viml-CugmlW5g.js → viml-DndUb2qM.js} +0 -0
- /package/dist/web/assets/{vitesse-black-vPdpy9TL.js → vitesse-black-BurZSkxW.js} +0 -0
- /package/dist/web/assets/{vitesse-dark-BuQK3dUh.js → vitesse-dark-8UShspzC.js} +0 -0
- /package/dist/web/assets/{vitesse-light-B3nz1XL9.js → vitesse-light-DghCAZ90.js} +0 -0
- /package/dist/web/assets/{vyper-DH_GTIHG.js → vyper-b-Clr-8u.js} +0 -0
- /package/dist/web/assets/{wasm-DfVbVJlW.js → wasm-C5v2T06Y.js} +0 -0
- /package/dist/web/assets/{wasm-C-LF9GjX.js → wasm-CpcKStkw.js} +0 -0
- /package/dist/web/assets/{wenyan-CzQkHyHx.js → wenyan-Dz2srLZR.js} +0 -0
- /package/dist/web/assets/{wgsl-Du_M1DW9.js → wgsl-CeD1-dRb.js} +0 -0
- /package/dist/web/assets/{wikitext-BWN_w5S7.js → wikitext-CyeS-9FH.js} +0 -0
- /package/dist/web/assets/{wit-BR13v5HD.js → wit-Kr-q-qBQ.js} +0 -0
- /package/dist/web/assets/{wolfram-BoXxp_Xl.js → wolfram-BKm8bmln.js} +0 -0
- /package/dist/web/assets/{x-nhriOX9o.js → x-YDu4m2Iq.js} +0 -0
- /package/dist/web/assets/{yaml-DpR_EF-d.js → yaml-2XSxomjM.js} +0 -0
- /package/dist/web/assets/{zenscript-C-EdUtUd.js → zenscript-CKIS34vf.js} +0 -0
- /package/dist/web/assets/{zig-BD4eA5nU.js → zig-DdHGNllX.js} +0 -0
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
// Shared harness for the Document PiP spike stages (terminal / editor).
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
import { CdpClient, sleep } from "./cdp-client";
|
|
4
|
-
|
|
5
|
-
export const APP = "http://localhost:5173";
|
|
6
|
-
export const SHOTS = "C:/Users/PC/ppm/plans/reports/screenshots";
|
|
7
|
-
export { sleep };
|
|
8
|
-
|
|
9
|
-
export async function connectApp() {
|
|
10
|
-
const cdp = await CdpClient.connect(9333);
|
|
11
|
-
const page = (await cdp.targets()).find((t) => t.type === "page" && t.url.startsWith(APP));
|
|
12
|
-
if (!page) throw new Error("no app page target");
|
|
13
|
-
const sid = await cdp.attach(page.targetId);
|
|
14
|
-
await cdp.send("Page.enable", {}, sid);
|
|
15
|
-
await cdp.send("Runtime.enable", {}, sid);
|
|
16
|
-
const helpers = await Bun.file(join(import.meta.dir, "pip-page-helpers.js")).text();
|
|
17
|
-
await cdp.eval(sid, helpers);
|
|
18
|
-
const knownTargets = new Set((await cdp.targets()).map((t) => t.targetId));
|
|
19
|
-
|
|
20
|
-
const ev = <T = unknown>(expr: string) => cdp.eval<T>(sid, expr);
|
|
21
|
-
async function waitFor(expr: string, timeoutMs = 20000, label = expr) {
|
|
22
|
-
const t0 = Date.now();
|
|
23
|
-
while (Date.now() - t0 < timeoutMs) {
|
|
24
|
-
if (await ev<boolean>(`!!(${expr})`)) return;
|
|
25
|
-
await sleep(250);
|
|
26
|
-
}
|
|
27
|
-
throw new Error(`timeout waiting: ${label}`);
|
|
28
|
-
}
|
|
29
|
-
async function openViaUrl(path: string) {
|
|
30
|
-
await ev(`history.pushState(null, '', ${JSON.stringify(path)}); dispatchEvent(new PopStateEvent('popstate')); 'ok'`);
|
|
31
|
-
await sleep(600);
|
|
32
|
-
}
|
|
33
|
-
/** Click the injected trusted-gesture button and wait for its async work to settle. */
|
|
34
|
-
async function runGesture(id: string, fnSource: string, timeoutMs = 20000) {
|
|
35
|
-
const pt = await ev<{ x: number; y: number }>(`window.__spike.installButton(${JSON.stringify(id)}, ${fnSource})`);
|
|
36
|
-
await cdp.click(sid, pt.x, pt.y);
|
|
37
|
-
const t0 = Date.now();
|
|
38
|
-
while (Date.now() - t0 < timeoutMs) {
|
|
39
|
-
const r = await ev<any>(`window.__spike.results[${JSON.stringify(id)}]`);
|
|
40
|
-
if (r && r.phase !== "running") return r;
|
|
41
|
-
await sleep(200);
|
|
42
|
-
}
|
|
43
|
-
throw new Error(`gesture ${id} timed out`);
|
|
44
|
-
}
|
|
45
|
-
/** Any CDP target that appeared since connect (candidate PiP window). */
|
|
46
|
-
async function newTargets() {
|
|
47
|
-
return (await cdp.targets()).filter((t) => !knownTargets.has(t.targetId));
|
|
48
|
-
}
|
|
49
|
-
/** Whole-screen capture via PowerShell (PiP is a separate always-on-top OS window). */
|
|
50
|
-
async function screenShot(name: string) {
|
|
51
|
-
const out = `${SHOTS}/${name}`;
|
|
52
|
-
const ps = `Add-Type -AssemblyName System.Windows.Forms; Add-Type -AssemblyName System.Drawing; $b=[System.Windows.Forms.Screen]::PrimaryScreen.Bounds; $bmp=New-Object System.Drawing.Bitmap $b.Width,$b.Height; $g=[System.Drawing.Graphics]::FromImage($bmp); $g.CopyFromScreen($b.Location,[System.Drawing.Point]::Empty,$b.Size); $bmp.Save('${out}',[System.Drawing.Imaging.ImageFormat]::Png); $g.Dispose(); $bmp.Dispose(); 'saved'`;
|
|
53
|
-
const p = Bun.spawn(["powershell", "-NoProfile", "-Command", ps], { stdout: "pipe", stderr: "pipe" });
|
|
54
|
-
await p.exited;
|
|
55
|
-
const err = await new Response(p.stderr).text();
|
|
56
|
-
return p.exitCode === 0 && !err ? out : `FAILED (${err.split("\n")[0]?.trim()})`;
|
|
57
|
-
}
|
|
58
|
-
/** Attach to the PiP window (an about:blank page target created after connect). */
|
|
59
|
-
async function attachPip(): Promise<string | null> {
|
|
60
|
-
const cands = (await newTargets()).filter((t) => t.type === "page");
|
|
61
|
-
for (const t of cands) {
|
|
62
|
-
try { return await cdp.attach(t.targetId); } catch { /* try next */ }
|
|
63
|
-
}
|
|
64
|
-
return null;
|
|
65
|
-
}
|
|
66
|
-
/** Page.captureScreenshot of the PiP target — works even when the OS desktop is not capturable. */
|
|
67
|
-
async function pipShot(pipSid: string | null, name: string) {
|
|
68
|
-
if (!pipSid) return "no pip session";
|
|
69
|
-
const out = `${SHOTS}/${name}`;
|
|
70
|
-
await cdp.screenshot(pipSid, out);
|
|
71
|
-
return out;
|
|
72
|
-
}
|
|
73
|
-
return { cdp, sid, ev, waitFor, openViaUrl, runGesture, newTargets, screenShot, attachPip, pipShot };
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export type Harness = Awaited<ReturnType<typeof connectApp>>;
|
|
77
|
-
|
|
78
|
-
export async function saveResults(name: string, data: unknown) {
|
|
79
|
-
const path = join(import.meta.dir, name);
|
|
80
|
-
await Bun.write(path, JSON.stringify(data, null, 2));
|
|
81
|
-
console.log(JSON.stringify(data, null, 2));
|
|
82
|
-
console.log("saved", path);
|
|
83
|
-
}
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
// Stage 3b: Monaco glue candidates — editContext:false for typing, explicit editor.layout() on pip resize, suggest widget placement.
|
|
2
|
-
import { connectApp, saveResults, sleep } from "./pip-spike-common";
|
|
3
|
-
|
|
4
|
-
const W = `window.__spike.ew`, E = `window.__spike.ed`;
|
|
5
|
-
const R: Record<string, unknown> = {};
|
|
6
|
-
const h = await connectApp();
|
|
7
|
-
const { ev, cdp, sid } = h;
|
|
8
|
-
await cdp.send("Emulation.setFocusEmulationEnabled", { enabled: true }, sid);
|
|
9
|
-
await ev(`(() => { const S = window.__spike; if (S.pip && !S.pip.closed) { if (S.ew && S.ew.ownerDocument !== document) S.moveBack(S.ew); S.pip.close(); } S.pip = null; S.results = {}; return 'reset'; })()`);
|
|
10
|
-
await h.openViaUrl("/project/ppm/editor/.spike/scratch-editor-target.ts");
|
|
11
|
-
await sleep(800);
|
|
12
|
-
await ev(`window.__spike.ew = document.querySelector('[data-tab-pool-id="editor:.spike/scratch-editor-target.ts"]'); window.__spike.ed = window.__spike.findEditor(window.__spike.ew); 'held'`);
|
|
13
|
-
R.mainState = await ev(`({ layout: [${E}.getLayoutInfo().width, ${E}.getLayoutInfo().height], slot: [${W}.offsetWidth, ${W}.offsetHeight], editContextOpt: ${E}.getOption(window.monaco.editor.EditorOption.editContext), nativeEditContextEl: !!${W}.querySelector('.native-edit-context'), editContextApi: 'EditContext' in window, minimapEnabled: ${E}.getOption(window.monaco.editor.EditorOption.minimap).enabled })`);
|
|
14
|
-
R.layoutFixInMain = await ev(`(() => { ${E}.layout(); return [${E}.getLayoutInfo().width, ${E}.getLayoutInfo().height]; })()`);
|
|
15
|
-
|
|
16
|
-
R.move = await h.runGesture("pip-editor-glue", `async () => {
|
|
17
|
-
const S = window.__spike; const w = ${W}; const ed = ${E};
|
|
18
|
-
const pip = await documentPictureInPicture.requestWindow({ width: 900, height: 600 }); S.pip = pip; S.copyStyles(pip.document); S.moveToPip(pip, w); S.pinToPip(w);
|
|
19
|
-
S.pipResizes = 0; pip.addEventListener('resize', () => { S.pipResizes++; ed.layout(); });
|
|
20
|
-
await new Promise(r => setTimeout(r, 600));
|
|
21
|
-
const before = [ed.getLayoutInfo().width, ed.getLayoutInfo().height]; ed.layout();
|
|
22
|
-
return { pipSize: [pip.innerWidth, pip.innerHeight], layoutBeforeExplicit: before, layoutAfterExplicit: [ed.getLayoutInfo().width, ed.getLayoutInfo().height], wrapper: [w.offsetWidth, w.offsetHeight] };
|
|
23
|
-
}`);
|
|
24
|
-
const pipSid = await h.attachPip();
|
|
25
|
-
await cdp.send("Emulation.setFocusEmulationEnabled", { enabled: true }, pipSid!);
|
|
26
|
-
await sleep(400);
|
|
27
|
-
|
|
28
|
-
// Typing with EditContext (default)
|
|
29
|
-
await ev(`${E}.setPosition({ lineNumber: 2, column: 1 }); 'p'`);
|
|
30
|
-
R.pipFocusTarget = await cdp.eval(pipSid!, `(() => { const nec = document.querySelector('.native-edit-context'); const ta = document.querySelector('.monaco-editor textarea'); (nec || ta).focus(); return { focused: document.activeElement.className, hasEditContext: !!(nec && nec.editContext) }; })()`);
|
|
31
|
-
await cdp.typeText(pipSid!, "EC ");
|
|
32
|
-
await sleep(300);
|
|
33
|
-
R.typingEditContext = await ev(`({ line2: ${E}.getModel().getLineContent(2), pass: ${E}.getModel().getLineContent(2).startsWith('EC ') })`);
|
|
34
|
-
// Also try Input.insertText (IME-style commit) with EditContext
|
|
35
|
-
await cdp.send("Input.insertText", { text: "IT " }, pipSid!);
|
|
36
|
-
await sleep(300);
|
|
37
|
-
R.insertTextEditContext = await ev(`({ line2: ${E}.getModel().getLineContent(2), pass: ${E}.getModel().getLineContent(2).includes('IT ') })`);
|
|
38
|
-
|
|
39
|
-
// Switch to textarea input and type again
|
|
40
|
-
R.switchToTextarea = await ev(`(async () => { ${E}.updateOptions({ editContext: false }); await new Promise(r => setTimeout(r, 300)); return { editContextOpt: ${E}.getOption(window.monaco.editor.EditorOption.editContext), textarea: !!${W}.querySelector('.monaco-editor textarea'), nec: !!${W}.querySelector('.native-edit-context') }; })()`);
|
|
41
|
-
await ev(`${E}.setPosition({ lineNumber: 2, column: 1 }); 'p'`);
|
|
42
|
-
await cdp.eval(pipSid!, `document.querySelector('.monaco-editor textarea').focus(); document.activeElement.className`);
|
|
43
|
-
await cdp.typeText(pipSid!, "TA ");
|
|
44
|
-
await sleep(300);
|
|
45
|
-
R.typingTextarea = await ev(`({ line2: ${E}.getModel().getLineContent(2), pass: ${E}.getModel().getLineContent(2).startsWith('TA ') })`);
|
|
46
|
-
await h.pipShot(pipSid, "spike-02c-editor-in-pip-typed.png");
|
|
47
|
-
|
|
48
|
-
// Suggest widget placement (textarea mode): type "spi" on a new line then Ctrl+Space
|
|
49
|
-
await ev(`${E}.setPosition({ lineNumber: 8, column: 1 }); 'p'`);
|
|
50
|
-
await cdp.eval(pipSid!, `document.querySelector('.monaco-editor textarea').focus(); 'f'`);
|
|
51
|
-
await cdp.pressKey(pipSid!, "Enter", "Enter", 13, "\r");
|
|
52
|
-
await cdp.typeText(pipSid!, "spi");
|
|
53
|
-
await cdp.pressKey(pipSid!, " ", "Space", 32, undefined, 2); // Ctrl+Space
|
|
54
|
-
await sleep(1200);
|
|
55
|
-
R.suggestWidget = await ev(`(() => { const w = ${W}; const sw = w.querySelector('.suggest-widget'); return { inWrapper: !!sw, visible: sw ? sw.classList.contains('visible') : null, inMainDoc: !!document.querySelector('.suggest-widget'), items: sw ? sw.querySelectorAll('.monaco-list-row').length : 0 }; })()`);
|
|
56
|
-
await h.pipShot(pipSid, "spike-02e-editor-in-pip-suggest.png");
|
|
57
|
-
await cdp.pressKey(pipSid!, "Escape", "Escape", 27);
|
|
58
|
-
|
|
59
|
-
// Resize via resizeTo with the pip 'resize' → editor.layout() glue
|
|
60
|
-
R.resizeGlue = await (async () => {
|
|
61
|
-
const pt = await cdp.eval<any>(pipSid!, `(() => { const b = document.createElement('button'); b.id = 'rz'; b.textContent = 'rz'; b.style.cssText = 'position:fixed;right:4px;bottom:4px;z-index:99999'; b.onclick = () => window.resizeTo(700, 450); document.body.append(b); const r = b.getBoundingClientRect(); return { x: r.x + r.width / 2, y: r.y + r.height / 2 }; })()`);
|
|
62
|
-
await cdp.click(pipSid!, pt.x, pt.y);
|
|
63
|
-
await sleep(600);
|
|
64
|
-
const r = await ev(`({ pipResizes: window.__spike.pipResizes, layout: [${E}.getLayoutInfo().width, ${E}.getLayoutInfo().height], pip: [window.__spike.pip.innerWidth, window.__spike.pip.innerHeight] })`);
|
|
65
|
-
await cdp.eval(pipSid!, `document.getElementById('rz').remove(); 'x'`);
|
|
66
|
-
return r;
|
|
67
|
-
})();
|
|
68
|
-
await h.pipShot(pipSid, "spike-02d-editor-in-pip-resized.png");
|
|
69
|
-
|
|
70
|
-
// Return: explicit layout + undo of pip-typed text
|
|
71
|
-
R.back = await ev(`(async () => { const S = window.__spike; const w = ${W}; const ed = ${E}; const r = S.moveBack(w); await new Promise(res => setTimeout(res, 800));
|
|
72
|
-
const stale = [ed.getLayoutInfo().width, ed.getLayoutInfo().height]; ed.layout(); ed.updateOptions({ editContext: true });
|
|
73
|
-
return { ...r, layoutStaleAfterReturn: stale, layoutAfterExplicit: [ed.getLayoutInfo().width, ed.getLayoutInfo().height], slot: [w.offsetWidth, w.offsetHeight] }; })()`);
|
|
74
|
-
await ev(`window.__spike.pip.close(); 'c'`);
|
|
75
|
-
await sleep(400);
|
|
76
|
-
await ev(`${E}.focus(); 'f'`);
|
|
77
|
-
const undoSteps: string[] = [];
|
|
78
|
-
for (let i = 0; i < 6; i++) { await cdp.pressKey(sid, "z", "KeyZ", 90, undefined, 2); await sleep(150); undoSteps.push(await ev(`${E}.getModel().getLineContent(2) + ' || L8=' + (${E}.getModel().getLineCount() >= 9 ? ${E}.getModel().getLineContent(9) : '')`)); }
|
|
79
|
-
R.undoAfterReturn = { steps: undoSteps, line2Restored: await ev(`${E}.getModel().getLineContent(2) === 'export const spikeLine1 = "one";'`) };
|
|
80
|
-
await cdp.screenshot(sid, "C:/Users/PC/ppm/plans/reports/screenshots/spike-04-editor-after-return.png");
|
|
81
|
-
await saveResults("pip-results-editor-glue.json", R);
|
|
82
|
-
cdp.close();
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
// Stage 3: move the live Monaco editor tab wrapper into a Document PiP window and test it.
|
|
2
|
-
import { connectApp, saveResults, sleep } from "./pip-spike-common";
|
|
3
|
-
|
|
4
|
-
const TAB = "editor:.spike/scratch-editor-target.ts";
|
|
5
|
-
const Q = `document.querySelector('[data-tab-pool-id="${TAB}"]')`;
|
|
6
|
-
const W = `window.__spike.ew`;
|
|
7
|
-
const E = `window.__spike.ed`;
|
|
8
|
-
const R: Record<string, unknown> = {};
|
|
9
|
-
const h = await connectApp();
|
|
10
|
-
const { ev, cdp, sid } = h;
|
|
11
|
-
await cdp.send("Emulation.setFocusEmulationEnabled", { enabled: true }, sid);
|
|
12
|
-
|
|
13
|
-
await ev(`(() => { const S = window.__spike; if (S.pip && !S.pip.closed) { if (S.ew && S.ew.ownerDocument !== document) S.moveBack(S.ew); S.pip.close(); } S.pip = null; S.results = {}; return 'reset'; })()`);
|
|
14
|
-
await h.openViaUrl("/project/ppm/editor/.spike/scratch-editor-target.ts");
|
|
15
|
-
await h.waitFor(`${Q} && ${Q}.style.display !== 'none' && ${Q}.querySelector('.monaco-editor .view-lines') && window.__spike.findEditor(${Q})`, 30000, "editor visible");
|
|
16
|
-
await ev(`window.__spike.ew = ${Q}; window.__spike.ed = window.__spike.findEditor(window.__spike.ew); 'held'`);
|
|
17
|
-
const wordWrapExpr = `${E}.getOption(window.monaco.editor.EditorOption.wordWrap)`;
|
|
18
|
-
|
|
19
|
-
async function typeAt(targetSid: string, text: string) {
|
|
20
|
-
await cdp.typeText(targetSid, text);
|
|
21
|
-
await sleep(300);
|
|
22
|
-
}
|
|
23
|
-
// Baseline in main: put cursor at 1:1, type marker (trusted)
|
|
24
|
-
await ev(`${E}.setPosition({ lineNumber: 1, column: 1 }); ${E}.focus(); 'f'`);
|
|
25
|
-
await typeAt(sid, "MAIN1 ");
|
|
26
|
-
await sleep(2000); // let the 1s autosave + dirty-title re-render settle before the move
|
|
27
|
-
R.baseline = await ev(`({ line1: ${E}.getModel().getLineContent(1), layoutW: ${E}.getLayoutInfo().width, layoutH: ${E}.getLayoutInfo().height, wordWrap: ${wordWrapExpr}, minimapCanvases: ${W}.querySelectorAll('.minimap canvas').length })`);
|
|
28
|
-
|
|
29
|
-
R.move = await h.runGesture("pip-editor", `async () => {
|
|
30
|
-
const S = window.__spike; const w = ${W}; const ed = ${E};
|
|
31
|
-
const pip = await documentPictureInPicture.requestWindow({ width: 900, height: 600 }); S.pip = pip;
|
|
32
|
-
const styles = S.copyStyles(pip.document); const moved = S.moveToPip(pip, w); S.pinToPip(w); S.installClickProbes(pip, w);
|
|
33
|
-
await new Promise(r => setTimeout(r, 800));
|
|
34
|
-
const vl = w.querySelector('.view-lines'); const mm = w.querySelector('.minimap canvas');
|
|
35
|
-
return { styles, moved, pipSize: [pip.innerWidth, pip.innerHeight], viewLines: vl.children.length, firstLineText: vl.children[0]?.textContent, layout: [ed.getLayoutInfo().width, ed.getLayoutInfo().height],
|
|
36
|
-
minimap: mm ? { w: mm.width, h: mm.height } : null, editorRect: (() => { const r = ed.getDomNode().getBoundingClientRect(); return [r.width, r.height]; })(), monacoTheme: pip.getComputedStyle(w.querySelector('.monaco-editor')).backgroundColor, mainBg: getComputedStyle(document.body).backgroundColor };
|
|
37
|
-
}`);
|
|
38
|
-
const pipSid = await h.attachPip();
|
|
39
|
-
R.pipAttached = !!pipSid;
|
|
40
|
-
if (!pipSid) throw new Error("no pip target");
|
|
41
|
-
await cdp.send("Emulation.setFocusEmulationEnabled", { enabled: true }, pipSid);
|
|
42
|
-
await sleep(600);
|
|
43
|
-
R.shotInPip = await h.pipShot(pipSid, "spike-02-editor-in-pip.png");
|
|
44
|
-
|
|
45
|
-
// Mouse: trusted click at line 3 in the PiP → cursor moves? then drag-select on line 2
|
|
46
|
-
R.mouseInPip = await (async () => {
|
|
47
|
-
const geo = await cdp.eval<any>(pipSid, `(() => { const lines = [...document.querySelectorAll('.view-line')]; const l3 = lines.find(l => l.textContent.includes('spikeLine3')) || lines[2]; if (!l3) return null; const r = l3.getBoundingClientRect(); return { x: r.x + 40, y: r.y + r.height / 2, text: l3.textContent }; })()`);
|
|
48
|
-
if (!geo) return { error: "no .view-line in pip doc", inPip: await ev(`${W}.ownerDocument !== document`) };
|
|
49
|
-
await cdp.click(pipSid, geo.x, geo.y);
|
|
50
|
-
await sleep(300);
|
|
51
|
-
const pos = await ev<any>(`(() => { const p = ${E}.getPosition(); return [p.lineNumber, p.column]; })()`);
|
|
52
|
-
const g2 = await cdp.eval<any>(pipSid, `(() => { const l = [...document.querySelectorAll('.view-line')].find(l => l.textContent.includes('spikeLine2')); const r = l.getBoundingClientRect(); return { x: r.x + 4, y: r.y + r.height / 2 }; })()`);
|
|
53
|
-
await cdp.send("Input.dispatchMouseEvent", { type: "mousePressed", x: g2.x, y: g2.y, button: "left", clickCount: 1 }, pipSid);
|
|
54
|
-
for (let i = 1; i <= 8; i++) await cdp.send("Input.dispatchMouseEvent", { type: "mouseMoved", x: g2.x + i * 20, y: g2.y, button: "left", buttons: 1 }, pipSid);
|
|
55
|
-
await cdp.send("Input.dispatchMouseEvent", { type: "mouseReleased", x: g2.x + 160, y: g2.y, button: "left", clickCount: 1 }, pipSid);
|
|
56
|
-
await sleep(300);
|
|
57
|
-
const sel = await ev<string>(`${E}.getModel().getValueInRange(${E}.getSelection())`);
|
|
58
|
-
await h.pipShot(pipSid, "spike-02b-editor-in-pip-selection.png");
|
|
59
|
-
return { clickedLineText: geo.text, positionAfterClick: pos, dragSelection: sel, dragPass: sel.length > 0 };
|
|
60
|
-
})();
|
|
61
|
-
|
|
62
|
-
// Keyboard: trusted typing in PiP at 1:1
|
|
63
|
-
await ev(`${E}.setPosition({ lineNumber: 1, column: 1 }); 'p'`);
|
|
64
|
-
await cdp.eval(pipSid, `document.querySelector('.monaco-editor textarea').focus(); document.activeElement.className`);
|
|
65
|
-
await typeAt(pipSid, "PIP2 ");
|
|
66
|
-
R.typingInPip = await ev(`({ line1: ${E}.getModel().getLineContent(1), pass: ${E}.getModel().getLineContent(1).startsWith('PIP2 MAIN1 ') })`);
|
|
67
|
-
R.shotTyped = await h.pipShot(pipSid, "spike-02c-editor-in-pip-typed.png");
|
|
68
|
-
|
|
69
|
-
// Resize: wrapper style (automaticLayout RO path) + pip resizeTo via trusted click
|
|
70
|
-
R.resizeViaStyle = await ev(`(async () => { const w = ${W}; const ed = ${E}; const before = [ed.getLayoutInfo().width, ed.getLayoutInfo().height]; w.style.height = '50%'; w.style.width = '70%';
|
|
71
|
-
await new Promise(r => setTimeout(r, 800)); const after = [ed.getLayoutInfo().width, ed.getLayoutInfo().height]; w.style.height = '100%'; w.style.width = '100%'; await new Promise(r => setTimeout(r, 800));
|
|
72
|
-
return { before, after, restored: [ed.getLayoutInfo().width, ed.getLayoutInfo().height], relayout: before[0] !== after[0] }; })()`);
|
|
73
|
-
R.resizeViaWindow = await (async () => {
|
|
74
|
-
const pt = await cdp.eval<any>(pipSid, `(() => { const b = document.createElement('button'); b.id = 'rz'; b.textContent = 'rz'; b.style.cssText = 'position:fixed;right:4px;bottom:4px;z-index:99999'; b.onclick = () => window.resizeTo(700, 450); document.body.append(b); const r = b.getBoundingClientRect(); return { x: r.x + r.width / 2, y: r.y + r.height / 2 }; })()`);
|
|
75
|
-
const before = await ev<any>(`[${E}.getLayoutInfo().width, ${E}.getLayoutInfo().height]`);
|
|
76
|
-
await cdp.click(pipSid, pt.x, pt.y);
|
|
77
|
-
const s: unknown[] = [];
|
|
78
|
-
for (const ms of [300, 1000, 3000]) { await sleep(ms); s.push(await ev(`({ afterMs: ${ms}, layout: [${E}.getLayoutInfo().width, ${E}.getLayoutInfo().height], pip: [window.__spike.pip.innerWidth, window.__spike.pip.innerHeight] })`)); }
|
|
79
|
-
await cdp.eval(pipSid, `document.getElementById('rz').remove(); 'x'`);
|
|
80
|
-
return { before, samples: s };
|
|
81
|
-
})();
|
|
82
|
-
R.shotResized = await h.pipShot(pipSid, "spike-02d-editor-in-pip-resized.png");
|
|
83
|
-
|
|
84
|
-
// React onClick in PiP: the toolbar "Wrap" button toggles wordWrap through a zustand store → Monaco option
|
|
85
|
-
R.reactClickInPip = await (async () => {
|
|
86
|
-
const pt = await cdp.eval<any>(pipSid, `(() => { const b = [...document.querySelectorAll('button')].find(b => b.textContent.trim() === 'Wrap'); if (!b) return null; const r = b.getBoundingClientRect(); return { x: r.x + r.width / 2, y: r.y + r.height / 2 }; })()`);
|
|
87
|
-
if (!pt) return "no Wrap button in pip";
|
|
88
|
-
const before = await ev(wordWrapExpr);
|
|
89
|
-
await ev(`window.__spike.probe = { mainDocClick: 0, pipDocClick: 0, wrapperClick: 0, reactRootClick: 0 }; 'r'`);
|
|
90
|
-
await cdp.click(pipSid, pt.x, pt.y);
|
|
91
|
-
await sleep(600);
|
|
92
|
-
return { wordWrapBefore: before, wordWrapAfter: await ev(wordWrapExpr), probe: await ev(`({ ...window.__spike.probe })`) };
|
|
93
|
-
})();
|
|
94
|
-
|
|
95
|
-
// Widgets: trigger suggest (Ctrl+Space) in PiP and see where the widget renders
|
|
96
|
-
R.suggestWidget = await (async () => {
|
|
97
|
-
await ev(`${E}.setPosition({ lineNumber: 7, column: 1 }); 'p'`);
|
|
98
|
-
await cdp.eval(pipSid, `document.querySelector('.monaco-editor textarea').focus(); 'f'`);
|
|
99
|
-
await cdp.typeText(pipSid, "spi");
|
|
100
|
-
await sleep(1200);
|
|
101
|
-
const r = await ev(`(() => { const w = ${W}; const sw = w.querySelector('.suggest-widget'); const mainSw = document.querySelector('.suggest-widget');
|
|
102
|
-
return { inWrapper: !!sw, visible: sw ? sw.classList.contains('visible') : null, inMainDoc: !!mainSw, overflowContainer: !!w.querySelector('.overflowingContentWidgets'), fixedOverflow: ${E}.getOption(window.monaco.editor.EditorOption.fixedOverflowWidgets) }; })()`);
|
|
103
|
-
await h.pipShot(pipSid, "spike-02e-editor-in-pip-suggest.png");
|
|
104
|
-
await cdp.pressKey(pipSid, "Escape", "Escape", 27);
|
|
105
|
-
for (let i = 0; i < 3; i++) await cdp.pressKey(pipSid, "Backspace", "Backspace", 8);
|
|
106
|
-
return r;
|
|
107
|
-
})();
|
|
108
|
-
|
|
109
|
-
// Move back, then undo history: Ctrl+Z x2 should remove "PIP2 " then "MAIN1 "
|
|
110
|
-
R.pullbackAttemptsWhileInPip = await ev(`({ attempts: window.__spike.pullbackAttempts, stillInPip: ${W}.ownerDocument !== document })`);
|
|
111
|
-
R.back = await ev(`(async () => { const S = window.__spike; const w = ${W}; const r = S.moveBack(w); await new Promise(res => setTimeout(res, 800)); return { ...r, layout: [${E}.getLayoutInfo().width, ${E}.getLayoutInfo().height], line1: ${E}.getModel().getLineContent(1) }; })()`);
|
|
112
|
-
await ev(`window.__spike.pip.close(); 'c'`);
|
|
113
|
-
await sleep(500);
|
|
114
|
-
await ev(`${E}.focus(); 'f'`);
|
|
115
|
-
await cdp.pressKey(sid, "z", "KeyZ", 90, undefined, 2); // Ctrl+Z
|
|
116
|
-
await sleep(300);
|
|
117
|
-
const afterUndo1 = await ev(`${E}.getModel().getLineContent(1)`);
|
|
118
|
-
await cdp.pressKey(sid, "z", "KeyZ", 90, undefined, 2);
|
|
119
|
-
await sleep(300);
|
|
120
|
-
const afterUndo2 = await ev(`${E}.getModel().getLineContent(1)`);
|
|
121
|
-
await ev(`${E}.setPosition({ lineNumber: 1, column: 1 }); ${E}.focus(); 'f'`);
|
|
122
|
-
await typeAt(sid, "BACK3 ");
|
|
123
|
-
R.afterReturn = await ev(`(async () => { const S = window.__spike; const w = ${W}; const ed = ${E}; const btn = [...w.querySelectorAll('button')].find(b => b.textContent.trim() === 'Wrap'); const ww0 = ${wordWrapExpr}; btn && btn.click(); await new Promise(r => setTimeout(r, 500));
|
|
124
|
-
return { afterUndo1: ${JSON.stringify(afterUndo1)}, afterUndo2: ${JSON.stringify(afterUndo2)}, undoPass: ${JSON.stringify(afterUndo2)}.startsWith('export const spikeLine1'), line1AfterTyping: ed.getModel().getLineContent(1), typingPass: ed.getModel().getLineContent(1).startsWith('BACK3 '), reactWrapToggle: { before: ww0, after: ${wordWrapExpr} } }; })()`);
|
|
125
|
-
// restore wordWrap + undo the BACK3 edit so the scratch file autosaves clean-ish
|
|
126
|
-
await ev(`(async () => { const w = ${W}; const btn = [...w.querySelectorAll('button')].find(b => b.textContent.trim() === 'Wrap'); if (${wordWrapExpr} !== 'off' && btn) btn.click(); ${E}.trigger('spike', 'undo', null); return 'ok'; })()`);
|
|
127
|
-
await cdp.screenshot(sid, "C:/Users/PC/ppm/plans/reports/screenshots/spike-04-editor-after-return.png");
|
|
128
|
-
await saveResults("pip-results-editor.json", R);
|
|
129
|
-
cdp.close();
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
// Debug: isolate "keys ignored" — round-tripped terminal vs fresh terminal, term.input() vs keyboard.
|
|
2
|
-
import { connectApp, saveResults, sleep } from "./pip-spike-common";
|
|
3
|
-
|
|
4
|
-
const R: Record<string, unknown> = {};
|
|
5
|
-
const h = await connectApp();
|
|
6
|
-
const { ev, cdp, sid } = h;
|
|
7
|
-
await cdp.send("Emulation.setFocusEmulationEnabled", { enabled: true }, sid);
|
|
8
|
-
|
|
9
|
-
const T1 = `window.__spike.findTerminal(window.__spike.tw)`;
|
|
10
|
-
// 1. term.input on the round-tripped terminal
|
|
11
|
-
await h.openViaUrl("/project/ppm/terminal/1");
|
|
12
|
-
await sleep(500);
|
|
13
|
-
R.inputApiRoundTripped = await ev(`(async () => { const S = window.__spike; const t = ${T1}; S.dataLog = []; t.input('echo VIA-INPUT-API\\r', true);
|
|
14
|
-
await new Promise(r => setTimeout(r, 1500)); return { dataLog: S.dataLog, echoed: S.termText(t, 80).includes('VIA-INPUT-API'), tail: S.termText(t, 3), rows: t.rows, cols: t.cols, visible: t.element.getBoundingClientRect().height }; })()`);
|
|
15
|
-
|
|
16
|
-
// 2. Fresh terminal tab (never moved): trusted keys
|
|
17
|
-
await h.openViaUrl("/project/ppm/terminal/2");
|
|
18
|
-
const Q2 = `document.querySelector('[data-tab-pool-id^="terminal:2"]')`;
|
|
19
|
-
await h.waitFor(`${Q2} && ${Q2}.querySelector('.xterm-helper-textarea')`, 15000, "terminal 2");
|
|
20
|
-
await sleep(3000); // shell boot
|
|
21
|
-
await ev(`window.__spike.tw2 = ${Q2}; window.__spike.t2 = window.__spike.findTerminal(window.__spike.tw2); window.__spike.dataLog2 = []; window.__spike.t2.onData(d => window.__spike.dataLog2.push(d)); 'ok'`);
|
|
22
|
-
await ev(`window.__spike.tw2.querySelector('.xterm-helper-textarea').focus(); 'f'`);
|
|
23
|
-
await cdp.typeText(sid, "echo FRESH-TERM");
|
|
24
|
-
await cdp.pressKey(sid, "Enter", "Enter", 13, "\r");
|
|
25
|
-
await sleep(1500);
|
|
26
|
-
R.freshTerminalTrustedKeys = await ev(`(() => { const S = window.__spike; const t = S.t2; return { id: S.tw2.dataset.tabPoolId, dataLog: S.dataLog2.join(''), echoed: S.termText(t, 80).includes('FRESH-TERM'), tail: S.termText(t, 3), rows: t.rows, cols: t.cols }; })()`);
|
|
27
|
-
|
|
28
|
-
// 3. Back to the round-tripped terminal: trusted keys with focus emulation on
|
|
29
|
-
await h.openViaUrl("/project/ppm/terminal/1");
|
|
30
|
-
await sleep(500);
|
|
31
|
-
await ev(`window.__spike.dataLog = []; window.__spike.tw.querySelector('.xterm-helper-textarea').focus(); 'f'`);
|
|
32
|
-
await cdp.typeText(sid, "echo RT-KEYS");
|
|
33
|
-
await cdp.pressKey(sid, "Enter", "Enter", 13, "\r");
|
|
34
|
-
await sleep(1500);
|
|
35
|
-
R.roundTrippedTrustedKeys = await ev(`(() => { const S = window.__spike; const t = ${T1}; return { dataLog: S.dataLog.join(''), echoed: S.termText(t, 80).includes('RT-KEYS'), tail: S.termText(t, 3),
|
|
36
|
-
textareaIsTermTextarea: t.textarea === S.tw.querySelector('.xterm-helper-textarea'), textareaDoc: t.textarea.ownerDocument === document, elementDoc: t.element.ownerDocument === document }; })()`);
|
|
37
|
-
await saveResults("pip-results-input-isolation.json", R);
|
|
38
|
-
cdp.close();
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
// Debug: which keyboard events reach the xterm textarea (main doc) under CDP input; effect of focus emulation.
|
|
2
|
-
import { connectApp, saveResults, sleep } from "./pip-spike-common";
|
|
3
|
-
|
|
4
|
-
const TAB = "terminal:1@panel-8281c2e3";
|
|
5
|
-
const Q = `document.querySelector('[data-tab-pool-id="${TAB}"]')`;
|
|
6
|
-
const R: Record<string, unknown> = {};
|
|
7
|
-
const h = await connectApp();
|
|
8
|
-
const { ev, cdp, sid } = h;
|
|
9
|
-
|
|
10
|
-
await ev(`(() => { const S = window.__spike; if (S.pip && !S.pip.closed) { if (S.tw && S.tw.ownerDocument !== document) S.moveBack(S.tw); S.pip.close(); } S.pip = null; return 'reset'; })()`);
|
|
11
|
-
await h.openViaUrl("/project/ppm/terminal/1");
|
|
12
|
-
await h.waitFor(`${Q} && ${Q}.style.display !== 'none'`, 15000, "terminal visible");
|
|
13
|
-
await ev(`window.__spike.tw = ${Q}; (() => { const S = window.__spike; const ta = S.tw.querySelector('.xterm-helper-textarea'); S.keyLog = [];
|
|
14
|
-
if (!S.keyProbe) { for (const t of ['keydown','keypress','input','beforeinput','keyup']) ta.addEventListener(t, e => S.keyLog.push(t + ':' + (e.key ?? e.data ?? '') + ':' + e.isTrusted)); S.keyProbe = true; }
|
|
15
|
-
return 'probe'; })()`);
|
|
16
|
-
|
|
17
|
-
async function probe(label: string) {
|
|
18
|
-
await ev(`window.__spike.keyLog = []; window.__spike.dataLog = []; window.__spike.tw.querySelector('.xterm-helper-textarea').focus(); 'f'`);
|
|
19
|
-
await cdp.typeText(sid, "ab");
|
|
20
|
-
await sleep(300);
|
|
21
|
-
R[label] = await ev(`({ hasFocus: document.hasFocus(), vis: document.visibilityState, active: document.activeElement && document.activeElement.className, keyLog: window.__spike.keyLog, dataLog: window.__spike.dataLog })`);
|
|
22
|
-
}
|
|
23
|
-
await probe("noEmulation");
|
|
24
|
-
await cdp.send("Page.bringToFront", {}, sid);
|
|
25
|
-
await sleep(300);
|
|
26
|
-
await probe("afterBringToFront");
|
|
27
|
-
await cdp.send("Emulation.setFocusEmulationEnabled", { enabled: true }, sid);
|
|
28
|
-
await sleep(300);
|
|
29
|
-
await probe("withFocusEmulation");
|
|
30
|
-
// Clean the typed junk from the shell line
|
|
31
|
-
await cdp.pressKey(sid, "Escape", "Escape", 27);
|
|
32
|
-
for (let i = 0; i < 8; i++) await cdp.pressKey(sid, "Backspace", "Backspace", 8);
|
|
33
|
-
await saveResults("pip-results-key-probe.json", R);
|
|
34
|
-
cdp.close();
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
// Verify: do node-level event listeners survive adoption into a Document PiP window? Minimal, controlled.
|
|
2
|
-
import { connectApp, saveResults, sleep } from "./pip-spike-common";
|
|
3
|
-
|
|
4
|
-
const R: Record<string, unknown> = {};
|
|
5
|
-
const h = await connectApp();
|
|
6
|
-
const { ev, cdp, sid } = h;
|
|
7
|
-
|
|
8
|
-
async function listenersOf(expr: string) {
|
|
9
|
-
const r = await cdp.send("Runtime.evaluate", { expression: expr }, sid);
|
|
10
|
-
if (!r.result?.objectId) return "no object";
|
|
11
|
-
const l = await cdp.send("DOMDebugger.getEventListeners", { objectId: r.result.objectId }, sid);
|
|
12
|
-
return (l.listeners as any[]).map((x) => `${x.type}${x.useCapture ? "(c)" : ""}`).sort();
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
// Fresh probe nodes in the main doc with listeners; a plain iframe-less popup for comparison is not possible w/o gesture, so PiP only.
|
|
16
|
-
await ev(`(() => { const S = window.__spike; S.probeDiv = document.createElement('div'); S.probeTa = document.createElement('textarea'); S.probeDiv.append(S.probeTa);
|
|
17
|
-
S.probeHits = { div: 0, ta: 0 }; S.probeDiv.addEventListener('click', () => S.probeHits.div++, true); S.probeTa.addEventListener('keydown', () => S.probeHits.ta++); S.probeTa.addEventListener('input', () => S.probeHits.ta++, true);
|
|
18
|
-
document.body.append(S.probeDiv); return 'ok'; })()`);
|
|
19
|
-
R.before = { div: await listenersOf("window.__spike.probeDiv"), ta: await listenersOf("window.__spike.probeTa") };
|
|
20
|
-
|
|
21
|
-
// Also take the fresh terminal wrapper (tw2) along, checking its listeners right after adoption while PiP is open
|
|
22
|
-
R.tw2Before = { ta: await listenersOf("window.__spike.tw2.querySelector('.xterm-helper-textarea')"), xterm: await listenersOf("window.__spike.tw2.querySelector('.xterm')") };
|
|
23
|
-
|
|
24
|
-
R.move = await h.runGesture("pip-listener-test", `async () => {
|
|
25
|
-
const S = window.__spike; if (S.pip && !S.pip.closed) S.pip.close();
|
|
26
|
-
const pip = await documentPictureInPicture.requestWindow({ width: 800, height: 500 }); S.pip = pip; S.copyStyles(pip.document);
|
|
27
|
-
pip.document.body.append(S.probeDiv);
|
|
28
|
-
const moved = S.moveToPip(pip, S.tw2);
|
|
29
|
-
await new Promise(r => setTimeout(r, 300));
|
|
30
|
-
// Fire synthetic events on the adopted probe nodes: do the listeners run?
|
|
31
|
-
S.probeHits = { div: 0, ta: 0 }; S.probeDiv.dispatchEvent(new MouseEvent('click', { bubbles: true })); S.probeTa.dispatchEvent(new KeyboardEvent('keydown', { key: 'a', bubbles: true })); S.probeTa.dispatchEvent(new InputEvent('input', { data: 'a', inputType: 'insertText', bubbles: true }));
|
|
32
|
-
return { moved, probeDivDoc: S.probeDiv.ownerDocument === pip.document, hitsAfterAdoption: { ...S.probeHits } };
|
|
33
|
-
}`);
|
|
34
|
-
R.afterAdoption = { div: await listenersOf("window.__spike.probeDiv"), ta: await listenersOf("window.__spike.probeTa") };
|
|
35
|
-
R.tw2AfterAdoption = { ta: await listenersOf("window.__spike.tw2.querySelector('.xterm-helper-textarea')"), xterm: await listenersOf("window.__spike.tw2.querySelector('.xterm')") };
|
|
36
|
-
|
|
37
|
-
// Type into the adopted fresh terminal via its PiP target (trusted)
|
|
38
|
-
const pipSid = await h.attachPip();
|
|
39
|
-
if (pipSid) {
|
|
40
|
-
await cdp.send("Emulation.setFocusEmulationEnabled", { enabled: true }, pipSid);
|
|
41
|
-
await cdp.eval(pipSid, `document.querySelector('.xterm-helper-textarea').focus(); 'f'`);
|
|
42
|
-
await ev(`window.__spike.dataLog2 = []; 'r'`);
|
|
43
|
-
await cdp.typeText(pipSid, "echo PIP-FRESH");
|
|
44
|
-
await cdp.pressKey(pipSid, "Enter", "Enter", 13, "\r");
|
|
45
|
-
await sleep(1200);
|
|
46
|
-
R.tw2TypingInPip = await ev(`({ dataLog: window.__spike.dataLog2.join(''), echoed: window.__spike.termText(window.__spike.t2, 60).includes('PIP-FRESH') })`);
|
|
47
|
-
}
|
|
48
|
-
// Move back while the PiP is still open, then check listeners again
|
|
49
|
-
R.back = await ev(`(() => { const S = window.__spike; const r = S.moveBack(S.tw2); document.body.append(S.probeDiv); S.probeHits = { div: 0, ta: 0 }; S.probeDiv.dispatchEvent(new MouseEvent('click', { bubbles: true })); S.probeTa.dispatchEvent(new KeyboardEvent('keydown', { key: 'a', bubbles: true })); return { ...r, hitsAfterReturn: { ...S.probeHits } }; })()`);
|
|
50
|
-
R.afterReturn = { div: await listenersOf("window.__spike.probeDiv"), ta: await listenersOf("window.__spike.probeTa") };
|
|
51
|
-
R.tw2AfterReturn = { ta: await listenersOf("window.__spike.tw2.querySelector('.xterm-helper-textarea')") };
|
|
52
|
-
await ev(`window.__spike.pip.close(); 'c'`);
|
|
53
|
-
await saveResults("pip-results-listener-survival.json", R);
|
|
54
|
-
cdp.close();
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
// Debug: compare registered DOM listeners on the round-tripped vs fresh xterm textarea (DOMDebugger.getEventListeners).
|
|
2
|
-
import { connectApp, saveResults } from "./pip-spike-common";
|
|
3
|
-
|
|
4
|
-
const R: Record<string, unknown> = {};
|
|
5
|
-
const h = await connectApp();
|
|
6
|
-
const { cdp, sid } = h;
|
|
7
|
-
|
|
8
|
-
async function listeners(label: string, expr: string) {
|
|
9
|
-
const r = await cdp.send("Runtime.evaluate", { expression: expr }, sid);
|
|
10
|
-
if (!r.result?.objectId) { R[label] = "no object: " + JSON.stringify(r.result); return; }
|
|
11
|
-
const l = await cdp.send("DOMDebugger.getEventListeners", { objectId: r.result.objectId }, sid);
|
|
12
|
-
R[label] = (l.listeners as any[]).map((x) => `${x.type}${x.useCapture ? "(capture)" : ""}${x.passive ? "(passive)" : ""} @${x.lineNumber}:${x.columnNumber}`).sort();
|
|
13
|
-
}
|
|
14
|
-
await listeners("roundTrippedTextarea", `window.__spike.tw.querySelector('.xterm-helper-textarea')`);
|
|
15
|
-
await listeners("freshTextarea", `window.__spike.tw2.querySelector('.xterm-helper-textarea')`);
|
|
16
|
-
await listeners("roundTrippedXtermEl", `window.__spike.tw.querySelector('.xterm')`);
|
|
17
|
-
await listeners("freshXtermEl", `window.__spike.tw2.querySelector('.xterm')`);
|
|
18
|
-
await saveResults("pip-results-listeners.json", R);
|
|
19
|
-
cdp.close();
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
// Debug: does a synchronous moveBack inside the PiP 'pagehide' handler preserve listeners? Plus canvas inventory.
|
|
2
|
-
import { connectApp, saveResults, sleep } from "./pip-spike-common";
|
|
3
|
-
|
|
4
|
-
const R: Record<string, unknown> = {};
|
|
5
|
-
const h = await connectApp();
|
|
6
|
-
const { ev, cdp, sid } = h;
|
|
7
|
-
await cdp.send("Emulation.setFocusEmulationEnabled", { enabled: true }, sid);
|
|
8
|
-
|
|
9
|
-
async function listenersOf(expr: string) {
|
|
10
|
-
const r = await cdp.send("Runtime.evaluate", { expression: expr }, sid);
|
|
11
|
-
if (!r.result?.objectId) return "no object";
|
|
12
|
-
const l = await cdp.send("DOMDebugger.getEventListeners", { objectId: r.result.objectId }, sid);
|
|
13
|
-
return (l.listeners as any[]).map((x) => `${x.type}${x.useCapture ? "(c)" : ""}`).sort();
|
|
14
|
-
}
|
|
15
|
-
R.t2TextareaListenersNow = await listenersOf("window.__spike.tw2.querySelector('.xterm-helper-textarea')");
|
|
16
|
-
R.t2Canvases = await ev(`[...window.__spike.tw2.querySelectorAll('canvas')].map(c => ({ cls: c.className, parent: c.parentElement.className, w: c.width, h: c.height, gl: !!c.getContext('webgl2') }))`);
|
|
17
|
-
|
|
18
|
-
// Fresh terminal 3 for a clean pagehide test
|
|
19
|
-
await h.openViaUrl("/project/ppm/terminal/3");
|
|
20
|
-
const Q3 = `document.querySelector('[data-tab-pool-id^="terminal:3"]')`;
|
|
21
|
-
await h.waitFor(`${Q3} && ${Q3}.style.display !== 'none' && ${Q3}.querySelector('.xterm-helper-textarea')`, 15000, "terminal 3");
|
|
22
|
-
await sleep(2500);
|
|
23
|
-
await ev(`window.__spike.tw3 = ${Q3}; window.__spike.t3 = window.__spike.findTerminal(window.__spike.tw3); 'ok'`);
|
|
24
|
-
R.t3Before = await listenersOf("window.__spike.tw3.querySelector('.xterm-helper-textarea')");
|
|
25
|
-
async function typeMarker(marker: string) {
|
|
26
|
-
await ev(`window.__spike.tw3.querySelector('.xterm-helper-textarea').focus(); 'f'`);
|
|
27
|
-
await cdp.typeText(sid, `echo ${marker}`);
|
|
28
|
-
await cdp.pressKey(sid, "Enter", "Enter", 13, "\r");
|
|
29
|
-
await sleep(1300);
|
|
30
|
-
return ev(`window.__spike.termText(window.__spike.t3, 60).includes(${JSON.stringify(marker)})`);
|
|
31
|
-
}
|
|
32
|
-
R.t3Baseline = await typeMarker("T3-BASE");
|
|
33
|
-
|
|
34
|
-
// A: pagehide handler moves back synchronously, then pip.close()
|
|
35
|
-
R.pagehideA = await h.runGesture("pip-pagehide-a", `async () => {
|
|
36
|
-
const S = window.__spike; const w = S.tw3; S.phLog = [];
|
|
37
|
-
const pip = await documentPictureInPicture.requestWindow({ width: 800, height: 500 }); S.pip = pip; S.copyStyles(pip.document); S.moveToPip(pip, w);
|
|
38
|
-
pip.addEventListener('pagehide', (e) => { S.phLog.push('pagehide owner=' + (w.ownerDocument === pip.document ? 'pip' : 'other') + ' persisted=' + e.persisted); S.moveBack(w); S.phLog.push('moved back, owner main=' + (w.ownerDocument === document)); });
|
|
39
|
-
pip.addEventListener('unload', () => S.phLog.push('unload'));
|
|
40
|
-
await new Promise(r => setTimeout(r, 400));
|
|
41
|
-
const beforeClose = { owner: w.ownerDocument === pip.document ? 'pip' : 'main' };
|
|
42
|
-
pip.close();
|
|
43
|
-
await new Promise(r => setTimeout(r, 400));
|
|
44
|
-
return { beforeClose, phLog: S.phLog, ownerAfter: w.ownerDocument === document ? 'main' : 'other', closed: pip.closed };
|
|
45
|
-
}`);
|
|
46
|
-
R.t3AfterA = await listenersOf("window.__spike.tw3.querySelector('.xterm-helper-textarea')");
|
|
47
|
-
R.t3TypingAfterA = await typeMarker("T3-AFTER-A");
|
|
48
|
-
|
|
49
|
-
// B: explicit moveBack BEFORE close (the known-good path) as control
|
|
50
|
-
R.controlB = await h.runGesture("pip-pagehide-b", `async () => {
|
|
51
|
-
const S = window.__spike; const w = S.tw3;
|
|
52
|
-
const pip = await documentPictureInPicture.requestWindow({ width: 800, height: 500 }); S.pip = pip; S.copyStyles(pip.document); S.moveToPip(pip, w);
|
|
53
|
-
await new Promise(r => setTimeout(r, 400)); S.moveBack(w); pip.close(); await new Promise(r => setTimeout(r, 400));
|
|
54
|
-
return { ownerAfter: w.ownerDocument === document ? 'main' : 'other' };
|
|
55
|
-
}`);
|
|
56
|
-
R.t3AfterB = await listenersOf("window.__spike.tw3.querySelector('.xterm-helper-textarea')");
|
|
57
|
-
R.t3TypingAfterB = await typeMarker("T3-AFTER-B");
|
|
58
|
-
await saveResults("pip-results-pagehide.json", R);
|
|
59
|
-
cdp.close();
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
// Debug: ResizeObserver (created in main window) vs PiP window resizes; does pip 'resize' + manual fit() work?
|
|
2
|
-
import { connectApp, saveResults, sleep } from "./pip-spike-common";
|
|
3
|
-
|
|
4
|
-
const R: Record<string, unknown> = {};
|
|
5
|
-
const h = await connectApp();
|
|
6
|
-
const { ev, cdp, sid } = h;
|
|
7
|
-
await cdp.send("Emulation.setFocusEmulationEnabled", { enabled: true }, sid);
|
|
8
|
-
await h.openViaUrl("/project/ppm/terminal/3");
|
|
9
|
-
await sleep(500);
|
|
10
|
-
const W = `window.__spike.tw3`, T = `window.__spike.t3`;
|
|
11
|
-
|
|
12
|
-
R.move = await h.runGesture("pip-resize", `async () => {
|
|
13
|
-
const S = window.__spike; const w = ${W}; const t = ${T};
|
|
14
|
-
const pip = await documentPictureInPicture.requestWindow({ width: 900, height: 600 }); S.pip = pip; S.copyStyles(pip.document); S.moveToPip(pip, w);
|
|
15
|
-
S.roLog = []; const ro = new ResizeObserver(es => S.roLog.push('main-RO ' + Math.round(es[0].contentRect.width) + 'x' + Math.round(es[0].contentRect.height))); ro.observe(w);
|
|
16
|
-
const pipRo = new pip.ResizeObserver(es => S.roLog.push('pip-RO ' + Math.round(es[0].contentRect.width) + 'x' + Math.round(es[0].contentRect.height))); pipRo.observe(w);
|
|
17
|
-
pip.addEventListener('resize', () => S.roLog.push('pip-resize-event ' + pip.innerWidth + 'x' + pip.innerHeight));
|
|
18
|
-
await new Promise(r => setTimeout(r, 500));
|
|
19
|
-
return { pipSize: [pip.innerWidth, pip.innerHeight], rowsCols: [t.rows, t.cols], roLog: S.roLog.slice() };
|
|
20
|
-
}`);
|
|
21
|
-
const pipSid = await h.attachPip();
|
|
22
|
-
await cdp.send("Emulation.setFocusEmulationEnabled", { enabled: true }, pipSid!);
|
|
23
|
-
// resizeTo inside a trusted click in the PiP
|
|
24
|
-
const pt = await cdp.eval<any>(pipSid!, `(() => { const b = document.createElement('button'); b.id = 'rz'; b.textContent = 'rz'; b.style.cssText = 'position:fixed;right:4px;bottom:4px;z-index:99999'; b.onclick = () => window.resizeTo(700, 450); document.body.append(b); const r = b.getBoundingClientRect(); return { x: r.x + r.width / 2, y: r.y + r.height / 2 }; })()`);
|
|
25
|
-
await ev(`window.__spike.roLog = []; 'r'`);
|
|
26
|
-
await cdp.click(pipSid!, pt.x, pt.y);
|
|
27
|
-
const samples: unknown[] = [];
|
|
28
|
-
for (const ms of [300, 1000, 3000]) {
|
|
29
|
-
await sleep(ms);
|
|
30
|
-
samples.push(await ev(`({ afterMs: ${ms}, pip: [window.__spike.pip.innerWidth, window.__spike.pip.innerHeight], wrapper: [${W}.offsetWidth, ${W}.offsetHeight], rowsCols: [${T}.rows, ${T}.cols], roLog: window.__spike.roLog.slice() })`));
|
|
31
|
-
}
|
|
32
|
-
R.afterResizeTo = samples;
|
|
33
|
-
// Nudge: force a main-document rendering update; does the main RO now deliver?
|
|
34
|
-
R.afterMainNudge = await ev(`(async () => { document.body.style.outline = '1px solid transparent'; document.body.offsetWidth; await new Promise(r => setTimeout(r, 600)); document.body.style.outline = ''; return { rowsCols: [${T}.rows, ${T}.cols], roLog: window.__spike.roLog.slice() }; })()`);
|
|
35
|
-
// Glue candidate: manual fit via the FitAddon reached through the fiber (fitRef) — or xterm's proposeDimensions
|
|
36
|
-
R.manualFit = await ev(`(() => { const S = window.__spike; const t = ${T}; const w = ${W}; let fit = null; let f = S.fiberOf(w.querySelector('.xterm').parentElement);
|
|
37
|
-
for (let d = 0; f && d < 40 && !fit; d++, f = f.return) { let hk = f.memoizedState; for (let i = 0; hk && i < 200; i++, hk = hk.next) { const c = hk.memoizedState && hk.memoizedState.current; if (c && typeof c.fit === 'function' && typeof c.proposeDimensions === 'function') { fit = c; break; } } }
|
|
38
|
-
if (!fit) return 'no fitAddon'; const before = [t.rows, t.cols]; const proposed = fit.proposeDimensions(); fit.fit(); return { before, proposed, after: [t.rows, t.cols] }; })()`);
|
|
39
|
-
await h.pipShot(pipSid, "spike-01e-terminal-in-pip-after-manual-fit.png");
|
|
40
|
-
await ev(`(() => { const S = window.__spike; S.moveBack(${W}); S.pip.close(); return 'done'; })()`);
|
|
41
|
-
await saveResults("pip-results-resize.json", R);
|
|
42
|
-
cdp.close();
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
// Stage 1: authenticate the spike Chrome, open terminal + editor tabs, verify instances reachable.
|
|
2
|
-
import { Database } from "bun:sqlite";
|
|
3
|
-
import { homedir } from "node:os";
|
|
4
|
-
import { join } from "node:path";
|
|
5
|
-
import { CdpClient, sleep } from "./cdp-client";
|
|
6
|
-
|
|
7
|
-
const PORT = 9333;
|
|
8
|
-
const APP = "http://localhost:5173";
|
|
9
|
-
const helpers = await Bun.file(join(import.meta.dir, "pip-page-helpers.js")).text();
|
|
10
|
-
|
|
11
|
-
const db = new Database(join(homedir(), ".ppm", "ppm.dev.db"), { readonly: true });
|
|
12
|
-
const token = JSON.parse((db.query("SELECT value FROM config WHERE key='auth'").get() as any).value).token as string;
|
|
13
|
-
|
|
14
|
-
const cdp = await CdpClient.connect(PORT);
|
|
15
|
-
const page = (await cdp.targets()).find((t) => t.type === "page" && t.url.startsWith(APP));
|
|
16
|
-
if (!page) throw new Error("no app page target: " + JSON.stringify(await cdp.targets()));
|
|
17
|
-
const sid = await cdp.attach(page.targetId);
|
|
18
|
-
await cdp.send("Page.enable", {}, sid);
|
|
19
|
-
await cdp.send("Runtime.enable", {}, sid);
|
|
20
|
-
|
|
21
|
-
async function waitFor(expr: string, timeoutMs = 20000, label = expr) {
|
|
22
|
-
const t0 = Date.now();
|
|
23
|
-
while (Date.now() - t0 < timeoutMs) {
|
|
24
|
-
if (await cdp.eval<boolean>(sid, `!!(${expr})`)) return;
|
|
25
|
-
await sleep(250);
|
|
26
|
-
}
|
|
27
|
-
throw new Error(`timeout waiting: ${label}`);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// Auth
|
|
31
|
-
const hasToken = await cdp.eval<boolean>(sid, `localStorage.getItem('ppm-auth-token') === ${JSON.stringify(token)}`);
|
|
32
|
-
if (!hasToken) {
|
|
33
|
-
await cdp.eval(sid, `localStorage.setItem('ppm-auth-token', ${JSON.stringify(token)}); 'set'`);
|
|
34
|
-
await cdp.send("Page.navigate", { url: `${APP}/project/ppm` }, sid);
|
|
35
|
-
await sleep(1500);
|
|
36
|
-
}
|
|
37
|
-
await waitFor(`document.querySelector('[data-panel-drop-zone]')`, 30000, "app shell");
|
|
38
|
-
console.log("app shell ready, url:", await cdp.eval(sid, "location.href"));
|
|
39
|
-
|
|
40
|
-
// Open terminal via URL routing (pushState + popstate → autoOpenFromUrl)
|
|
41
|
-
async function openViaUrl(path: string) {
|
|
42
|
-
await cdp.eval(sid, `history.pushState(null, '', ${JSON.stringify(path)}); dispatchEvent(new PopStateEvent('popstate')); 'ok'`);
|
|
43
|
-
}
|
|
44
|
-
await openViaUrl("/project/ppm/terminal/1");
|
|
45
|
-
await waitFor(`document.querySelector('[data-tab-pool-id^="terminal"] .xterm-helper-textarea')`, 20000, "xterm");
|
|
46
|
-
await openViaUrl("/project/ppm/editor/.spike/scratch-editor-target.ts");
|
|
47
|
-
await waitFor(`document.querySelector('[data-tab-pool-id^="editor"] .monaco-editor .view-lines')`, 30000, "monaco");
|
|
48
|
-
|
|
49
|
-
await cdp.eval(sid, helpers);
|
|
50
|
-
const info = await cdp.eval(sid, `(() => {
|
|
51
|
-
const S = window.__spike;
|
|
52
|
-
const tw = document.querySelector('[data-tab-pool-id^="terminal"]');
|
|
53
|
-
const ew = document.querySelector('[data-tab-pool-id^="editor"]');
|
|
54
|
-
const term = S.findTerminal(tw); const ed = S.findEditor(ew);
|
|
55
|
-
return {
|
|
56
|
-
wrappers: [...document.querySelectorAll('[data-tab-pool-id]')].map(w => ({ id: w.dataset.tabPoolId, display: w.style.display, parent: w.parentElement?.className })),
|
|
57
|
-
termFound: !!term, termSize: term && { rows: term.rows, cols: term.cols }, termTail: term && S.termText(term, 5),
|
|
58
|
-
editorFound: !!ed, editorLine1: ed && ed.getModel().getLineContent(1), layout: ed && ed.getLayoutInfo().width,
|
|
59
|
-
htmlClass: document.documentElement.className, sheets: document.styleSheets.length, monacoGlobal: !!window.monaco,
|
|
60
|
-
};
|
|
61
|
-
})()`);
|
|
62
|
-
console.log(JSON.stringify(info, null, 2));
|
|
63
|
-
cdp.close();
|