atoo-studio 0.0.1 → 0.0.2
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/LICENSE +21 -0
- package/README.github.md +322 -0
- package/README.md +112 -0
- package/README.npm.md +112 -0
- package/bin/atoo-studio.js +90 -0
- package/dist/src/agents/claude-code-terminal/adapter.d.ts +42 -0
- package/dist/src/agents/claude-code-terminal/adapter.js +166 -0
- package/dist/src/agents/claude-code-terminal/index.d.ts +13 -0
- package/dist/src/agents/claude-code-terminal/index.js +45 -0
- package/dist/src/agents/claude-code-terminal/spawner.d.ts +9 -0
- package/dist/src/agents/claude-code-terminal/spawner.js +37 -0
- package/dist/src/agents/claude-code-terminal-chatro/adapter.d.ts +51 -0
- package/dist/src/agents/claude-code-terminal-chatro/adapter.js +301 -0
- package/dist/src/agents/claude-code-terminal-chatro/index.d.ts +13 -0
- package/dist/src/agents/claude-code-terminal-chatro/index.js +45 -0
- package/dist/src/agents/claude-code-terminal-chatro/jsonl-watcher.d.ts +67 -0
- package/dist/src/agents/claude-code-terminal-chatro/jsonl-watcher.js +431 -0
- package/dist/src/agents/claude-code-terminal-chatro/spawner.d.ts +9 -0
- package/dist/src/agents/claude-code-terminal-chatro/spawner.js +37 -0
- package/dist/src/agents/codex-terminal/adapter.d.ts +40 -0
- package/dist/src/agents/codex-terminal/adapter.js +160 -0
- package/dist/src/agents/codex-terminal/index.d.ts +13 -0
- package/dist/src/agents/codex-terminal/index.js +47 -0
- package/dist/src/agents/codex-terminal/spawner.d.ts +9 -0
- package/dist/src/agents/codex-terminal/spawner.js +56 -0
- package/dist/src/agents/codex-terminal-chatro/adapter.d.ts +58 -0
- package/dist/src/agents/codex-terminal-chatro/adapter.js +266 -0
- package/dist/src/agents/codex-terminal-chatro/index.d.ts +13 -0
- package/dist/src/agents/codex-terminal-chatro/index.js +50 -0
- package/dist/src/agents/codex-terminal-chatro/jsonl-watcher.d.ts +36 -0
- package/dist/src/agents/codex-terminal-chatro/jsonl-watcher.js +205 -0
- package/dist/src/agents/codex-terminal-chatro/spawner.d.ts +9 -0
- package/dist/src/agents/codex-terminal-chatro/spawner.js +57 -0
- package/dist/src/agents/lib/chain-builder.d.ts +21 -0
- package/dist/src/agents/lib/chain-builder.js +139 -0
- package/dist/src/agents/lib/claude/fs-sessions.d.ts +31 -0
- package/dist/src/agents/lib/claude/fs-sessions.js +329 -0
- package/dist/src/agents/lib/claude/jsonl-writer.d.ts +32 -0
- package/dist/src/agents/lib/claude/jsonl-writer.js +342 -0
- package/dist/src/agents/lib/claude/workspace-trust.d.ts +1 -0
- package/dist/src/agents/lib/claude/workspace-trust.js +29 -0
- package/dist/src/agents/lib/codex/fs-sessions.d.ts +34 -0
- package/dist/src/agents/lib/codex/fs-sessions.js +255 -0
- package/dist/src/agents/lib/codex/jsonl-mapper.d.ts +11 -0
- package/dist/src/agents/lib/codex/jsonl-mapper.js +154 -0
- package/dist/src/agents/lib/codex/jsonl-writer.d.ts +8 -0
- package/dist/src/agents/lib/codex/jsonl-writer.js +440 -0
- package/dist/src/agents/lib/fs-tracking.d.ts +36 -0
- package/dist/src/agents/lib/fs-tracking.js +109 -0
- package/dist/src/agents/lib/pty-activity-tracker.d.ts +37 -0
- package/dist/src/agents/lib/pty-activity-tracker.js +105 -0
- package/dist/src/agents/lib/session-id-utils.d.ts +46 -0
- package/dist/src/agents/lib/session-id-utils.js +147 -0
- package/dist/src/agents/lib/session-precreate.d.ts +17 -0
- package/dist/src/agents/lib/session-precreate.js +177 -0
- package/dist/src/agents/registry.d.ts +72 -0
- package/dist/src/agents/registry.js +337 -0
- package/dist/src/agents/types.d.ts +135 -0
- package/dist/src/agents/types.js +1 -0
- package/dist/src/auth/crypto-key.d.ts +6 -0
- package/dist/src/auth/crypto-key.js +45 -0
- package/dist/src/auth/middleware.d.ts +18 -0
- package/dist/src/auth/middleware.js +54 -0
- package/dist/src/auth/password.d.ts +2 -0
- package/dist/src/auth/password.js +12 -0
- package/dist/src/auth/session.d.ts +10 -0
- package/dist/src/auth/session.js +33 -0
- package/dist/src/auth/totp.d.ts +12 -0
- package/dist/src/auth/totp.js +61 -0
- package/dist/src/auth/webauthn.d.ts +6 -0
- package/dist/src/auth/webauthn.js +117 -0
- package/dist/src/config.d.ts +10 -0
- package/dist/src/config.js +16 -0
- package/dist/src/database/connection-manager.d.ts +25 -0
- package/dist/src/database/connection-manager.js +211 -0
- package/dist/src/database/discovery/container.d.ts +6 -0
- package/dist/src/database/discovery/container.js +226 -0
- package/dist/src/database/discovery/env-parser.d.ts +9 -0
- package/dist/src/database/discovery/env-parser.js +525 -0
- package/dist/src/database/discovery/local-files.d.ts +6 -0
- package/dist/src/database/discovery/local-files.js +58 -0
- package/dist/src/database/discovery/port-scan.d.ts +7 -0
- package/dist/src/database/discovery/port-scan.js +61 -0
- package/dist/src/database/drivers/cassandra.d.ts +12 -0
- package/dist/src/database/drivers/cassandra.js +91 -0
- package/dist/src/database/drivers/clickhouse.d.ts +11 -0
- package/dist/src/database/drivers/clickhouse.js +127 -0
- package/dist/src/database/drivers/elasticsearch.d.ts +12 -0
- package/dist/src/database/drivers/elasticsearch.js +169 -0
- package/dist/src/database/drivers/influxdb.d.ts +14 -0
- package/dist/src/database/drivers/influxdb.js +194 -0
- package/dist/src/database/drivers/memcached.d.ts +11 -0
- package/dist/src/database/drivers/memcached.js +117 -0
- package/dist/src/database/drivers/mongodb.d.ts +12 -0
- package/dist/src/database/drivers/mongodb.js +128 -0
- package/dist/src/database/drivers/mysql.d.ts +11 -0
- package/dist/src/database/drivers/mysql.js +112 -0
- package/dist/src/database/drivers/neo4j.d.ts +11 -0
- package/dist/src/database/drivers/neo4j.js +158 -0
- package/dist/src/database/drivers/postgresql.d.ts +11 -0
- package/dist/src/database/drivers/postgresql.js +133 -0
- package/dist/src/database/drivers/redis.d.ts +11 -0
- package/dist/src/database/drivers/redis.js +91 -0
- package/dist/src/database/drivers/sqlite.d.ts +10 -0
- package/dist/src/database/drivers/sqlite.js +100 -0
- package/dist/src/database/query-stream.d.ts +5 -0
- package/dist/src/database/query-stream.js +75 -0
- package/dist/src/database/types.d.ts +71 -0
- package/dist/src/database/types.js +1 -0
- package/dist/src/events/index.d.ts +3 -0
- package/dist/src/events/index.js +3 -0
- package/dist/src/events/types.d.ts +214 -0
- package/dist/src/events/types.js +22 -0
- package/dist/src/events/wire.d.ts +114 -0
- package/dist/src/events/wire.js +296 -0
- package/dist/src/fs-monitor-types.d.ts +24 -0
- package/dist/src/fs-monitor-types.js +1 -0
- package/dist/src/fs-monitor.d.ts +80 -0
- package/dist/src/fs-monitor.js +637 -0
- package/dist/src/handlers/auth.d.ts +1 -0
- package/dist/src/handlers/auth.js +170 -0
- package/dist/src/handlers/changes.d.ts +1 -0
- package/dist/src/handlers/changes.js +203 -0
- package/dist/src/handlers/containers.d.ts +12 -0
- package/dist/src/handlers/containers.js +379 -0
- package/dist/src/handlers/databases.d.ts +3 -0
- package/dist/src/handlers/databases.js +327 -0
- package/dist/src/handlers/environments.d.ts +3 -0
- package/dist/src/handlers/environments.js +286 -0
- package/dist/src/handlers/github.d.ts +1 -0
- package/dist/src/handlers/github.js +153 -0
- package/dist/src/handlers/projects.d.ts +1 -0
- package/dist/src/handlers/projects.js +895 -0
- package/dist/src/handlers/ssh.d.ts +1 -0
- package/dist/src/handlers/ssh.js +162 -0
- package/dist/src/handlers/users.d.ts +1 -0
- package/dist/src/handlers/users.js +195 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +228 -0
- package/dist/src/mcp/config.d.ts +32 -0
- package/dist/src/mcp/config.js +227 -0
- package/dist/src/mcp/server.d.ts +1 -0
- package/dist/src/mcp/server.js +574 -0
- package/dist/src/serial/cuse-device.d.ts +19 -0
- package/dist/src/serial/cuse-device.js +260 -0
- package/dist/src/serial/manager.d.ts +63 -0
- package/dist/src/serial/manager.js +206 -0
- package/dist/src/serial/pty-pair.d.ts +16 -0
- package/dist/src/serial/pty-pair.js +68 -0
- package/dist/src/services/fs-browser.d.ts +14 -0
- package/dist/src/services/fs-browser.js +98 -0
- package/dist/src/services/git-ops.d.ts +78 -0
- package/dist/src/services/git-ops.js +288 -0
- package/dist/src/services/github-ops.d.ts +104 -0
- package/dist/src/services/github-ops.js +192 -0
- package/dist/src/services/obfuscation.d.ts +2 -0
- package/dist/src/services/obfuscation.js +16 -0
- package/dist/src/services/preview/headless-backend.d.ts +62 -0
- package/dist/src/services/preview/headless-backend.js +698 -0
- package/dist/src/services/preview/injected-scripts.d.ts +9 -0
- package/dist/src/services/preview/injected-scripts.js +232 -0
- package/dist/src/services/preview/preview-backend.d.ts +92 -0
- package/dist/src/services/preview/preview-backend.js +15 -0
- package/dist/src/services/preview/universal-setter.d.ts +7 -0
- package/dist/src/services/preview/universal-setter.js +46 -0
- package/dist/src/services/preview-manager.d.ts +50 -0
- package/dist/src/services/preview-manager.js +216 -0
- package/dist/src/services/project-watcher.d.ts +6 -0
- package/dist/src/services/project-watcher.js +307 -0
- package/dist/src/services/remote-fs-browser.d.ts +11 -0
- package/dist/src/services/remote-fs-browser.js +50 -0
- package/dist/src/services/remote-git-ops.d.ts +71 -0
- package/dist/src/services/remote-git-ops.js +215 -0
- package/dist/src/services/session-search.d.ts +56 -0
- package/dist/src/services/session-search.js +303 -0
- package/dist/src/services/ssh-manager.d.ts +44 -0
- package/dist/src/services/ssh-manager.js +359 -0
- package/dist/src/session-writer.d.ts +9 -0
- package/dist/src/session-writer.js +66 -0
- package/dist/src/spawner.d.ts +56 -0
- package/dist/src/spawner.js +135 -0
- package/dist/src/state/db.d.ts +214 -0
- package/dist/src/state/db.js +897 -0
- package/dist/src/state/store.d.ts +37 -0
- package/dist/src/state/store.js +108 -0
- package/dist/src/state/types.d.ts +13 -0
- package/dist/src/state/types.js +1 -0
- package/dist/src/web/devtools-proxy.d.ts +7 -0
- package/dist/src/web/devtools-proxy.js +176 -0
- package/dist/src/web/port-proxy.d.ts +15 -0
- package/dist/src/web/port-proxy.js +124 -0
- package/dist/src/web/preview-ws.d.ts +5 -0
- package/dist/src/web/preview-ws.js +207 -0
- package/dist/src/web/server.d.ts +6 -0
- package/dist/src/web/server.js +1694 -0
- package/dist/src/ws/agent-ws.d.ts +5 -0
- package/dist/src/ws/agent-ws.js +93 -0
- package/frontend/dist/assets/_basePickBy-B-LibQ4-.js +1 -0
- package/frontend/dist/assets/_baseUniq-CprifHap.js +1 -0
- package/frontend/dist/assets/_createAssigner-ByDUqGii.js +1 -0
- package/frontend/dist/assets/abap-DuT-3z4x.js +1 -0
- package/frontend/dist/assets/addon-fit-CxQet2ja.js +1 -0
- package/frontend/dist/assets/addon-web-links-D_jRkPIl.js +1 -0
- package/frontend/dist/assets/apex-B-em86xX.js +1 -0
- package/frontend/dist/assets/api-SUPuHhSY.js +2 -0
- package/frontend/dist/assets/arc-Z0_eVteO.js +1 -0
- package/frontend/dist/assets/architecture-PBZL5I3N-hvVXGhqd.js +1 -0
- package/frontend/dist/assets/architectureDiagram-2XIMDMQ5-DiHPxX4j.js +36 -0
- package/frontend/dist/assets/array-CwG8vNfn.js +1 -0
- package/frontend/dist/assets/auth-store-R7eW5SVu.js +1 -0
- package/frontend/dist/assets/azcli-Bg9wQloi.js +1 -0
- package/frontend/dist/assets/bat-BM46z99L.js +1 -0
- package/frontend/dist/assets/bicep-DcBsJUfh.js +2 -0
- package/frontend/dist/assets/blockDiagram-WCTKOSBZ-C40u_hLo.js +132 -0
- package/frontend/dist/assets/c4Diagram-IC4MRINW-Ct7LjWFQ.js +10 -0
- package/frontend/dist/assets/cameligo-zw7JTtim.js +1 -0
- package/frontend/dist/assets/channel-ClCsE6HN.js +1 -0
- package/frontend/dist/assets/chunk-4BX2VUAB-zZ6P90VO.js +1 -0
- package/frontend/dist/assets/chunk-55IACEB6-DXllTDQl.js +1 -0
- package/frontend/dist/assets/chunk-7E7YKBS2-7zRaOLjj.js +1 -0
- package/frontend/dist/assets/chunk-7R4GIKGN-Csst1274.js +80 -0
- package/frontend/dist/assets/chunk-C72U2L5F-_JbQPbLN.js +1 -0
- package/frontend/dist/assets/chunk-CFjPhJqf.js +1 -0
- package/frontend/dist/assets/chunk-EGIJ26TM-B--aFyPw.js +1 -0
- package/frontend/dist/assets/chunk-FMBD7UC4-DVR34RNb.js +15 -0
- package/frontend/dist/assets/chunk-GEFDOKGD-CnmN6cC8.js +2 -0
- package/frontend/dist/assets/chunk-JSJVCQXG-CWxHBzeJ.js +1 -0
- package/frontend/dist/assets/chunk-KX2RTZJC-DkRk56s7.js +1 -0
- package/frontend/dist/assets/chunk-KYZI473N-DCCsG2dK.js +53 -0
- package/frontend/dist/assets/chunk-L3YUKLVL-C-DkZTMr.js +1 -0
- package/frontend/dist/assets/chunk-MX3YWQON-OUdzv5sZ.js +1 -0
- package/frontend/dist/assets/chunk-NQ4KR5QH-Bpu9FsM7.js +220 -0
- package/frontend/dist/assets/chunk-O4XLMI2P-BMLK6_ib.js +7 -0
- package/frontend/dist/assets/chunk-OZEHJAEY-CNNiJtG0.js +1 -0
- package/frontend/dist/assets/chunk-PQ6SQG4A-evVHD3KM.js +1 -0
- package/frontend/dist/assets/chunk-PU5JKC2W-DPFTYuvl.js +70 -0
- package/frontend/dist/assets/chunk-QZHKN3VN-JRdddPvu.js +1 -0
- package/frontend/dist/assets/chunk-R5LLSJPH-CHQzVVOV.js +1 -0
- package/frontend/dist/assets/chunk-WL4C6EOR-BNFU6IIi.js +189 -0
- package/frontend/dist/assets/chunk-XIRO2GV7-98T93G85.js +1 -0
- package/frontend/dist/assets/chunk-XZSTWKYB-BcW3cyNp.js +94 -0
- package/frontend/dist/assets/chunk-YBOYWFTD-BgKO1qAJ.js +1 -0
- package/frontend/dist/assets/classDiagram-VBA2DB6C-DikXzgcD.js +1 -0
- package/frontend/dist/assets/classDiagram-v2-RAHNMMFH-D7E3tQUK.js +1 -0
- package/frontend/dist/assets/clojure-FspFoNNQ.js +1 -0
- package/frontend/dist/assets/clone-mOXuZa7C.js +1 -0
- package/frontend/dist/assets/codicon-ngg6Pgfi.ttf +0 -0
- package/frontend/dist/assets/coffee-13n8Bk2W.js +1 -0
- package/frontend/dist/assets/cose-bilkent-S5V4N54A-zUOWQqLe.js +1 -0
- package/frontend/dist/assets/cpp-BVm2xGEs.js +1 -0
- package/frontend/dist/assets/csharp-D2kAWmUm.js +1 -0
- package/frontend/dist/assets/csp-Ezvgpf0e.js +1 -0
- package/frontend/dist/assets/css-CYxRwcFy.js +3 -0
- package/frontend/dist/assets/css.worker-Cd5h-ZOL.js +89 -0
- package/frontend/dist/assets/cssMode-CrXej49V.js +1 -0
- package/frontend/dist/assets/cypher-jg3SGErc.js +1 -0
- package/frontend/dist/assets/cytoscape.esm-kyyvzxNV.js +321 -0
- package/frontend/dist/assets/dagre-DH4bgZO7.js +1 -0
- package/frontend/dist/assets/dagre-KLK3FWXG-DNSqDkwT.js +4 -0
- package/frontend/dist/assets/dart-179jqhK4.js +1 -0
- package/frontend/dist/assets/defaultLocale-Dda4OpKy.js +1 -0
- package/frontend/dist/assets/diagram-E7M64L7V-RqPNT5Vs.js +24 -0
- package/frontend/dist/assets/diagram-IFDJBPK2-B-5NRyaE.js +43 -0
- package/frontend/dist/assets/diagram-P4PSJMXO-BrP69Hk0.js +24 -0
- package/frontend/dist/assets/dist-CU_Nb1G5.js +1 -0
- package/frontend/dist/assets/dockerfile-CIAtSGxS.js +1 -0
- package/frontend/dist/assets/ecl-CGVKfDxD.js +1 -0
- package/frontend/dist/assets/editor-Br_kD0ds.css +1 -0
- package/frontend/dist/assets/editor.api2-YXkDn0Gm.js +872 -0
- package/frontend/dist/assets/editor.main-fBaXZjJ0.js +6 -0
- package/frontend/dist/assets/elixir-BZ-6w0y3.js +1 -0
- package/frontend/dist/assets/erDiagram-INFDFZHY-BYiB9NYg.js +70 -0
- package/frontend/dist/assets/flow9-CVuOjTMv.js +1 -0
- package/frontend/dist/assets/flowDiagram-PKNHOUZH-Cwq47rsR.js +162 -0
- package/frontend/dist/assets/freemarker2-DM-pztJU.js +3 -0
- package/frontend/dist/assets/fsharp-q0pGJYr6.js +1 -0
- package/frontend/dist/assets/ganttDiagram-A5KZAMGK-Dnx3szD9.js +292 -0
- package/frontend/dist/assets/gitGraph-HDMCJU4V-COlTQ7bA.js +1 -0
- package/frontend/dist/assets/gitGraphDiagram-K3NZZRJ6-BaUxboNc.js +65 -0
- package/frontend/dist/assets/go-dzSPfdEO.js +1 -0
- package/frontend/dist/assets/graphlib-kEFlkt3U.js +1 -0
- package/frontend/dist/assets/graphql-CG4OUoEV.js +1 -0
- package/frontend/dist/assets/handlebars-BbK53Vec.js +1 -0
- package/frontend/dist/assets/hcl-Cy14JPk3.js +1 -0
- package/frontend/dist/assets/html-DYtTQNOG.js +1 -0
- package/frontend/dist/assets/html.worker-BjVEKLoU.js +502 -0
- package/frontend/dist/assets/htmlMode-C6GTouth.js +1 -0
- package/frontend/dist/assets/index-DMLxes_u.js +157 -0
- package/frontend/dist/assets/index-DmzeqkB1.css +1 -0
- package/frontend/dist/assets/info-3K5VOQVL-DBtHyA4C.js +1 -0
- package/frontend/dist/assets/infoDiagram-LFFYTUFH-yBXLgMPI.js +2 -0
- package/frontend/dist/assets/ini-Pbg8HGVD.js +1 -0
- package/frontend/dist/assets/init-D6KNwrax.js +1 -0
- package/frontend/dist/assets/ishikawaDiagram-PHBUUO56-Bld4two_.js +70 -0
- package/frontend/dist/assets/java-BmVu6Qrl.js +1 -0
- package/frontend/dist/assets/javascript-PbfQEdcJ.js +1 -0
- package/frontend/dist/assets/journeyDiagram-4ABVD52K-4HyMd4R2.js +139 -0
- package/frontend/dist/assets/json.worker-DqU5Wxnl.js +58 -0
- package/frontend/dist/assets/jsonMode-CASsGppE.js +7 -0
- package/frontend/dist/assets/julia-3cGnieBq.js +1 -0
- package/frontend/dist/assets/kanban-definition-K7BYSVSG-DpgsZmpG.js +89 -0
- package/frontend/dist/assets/katex-CEw3x5bf.js +261 -0
- package/frontend/dist/assets/kotlin-BuWkVcfV.js +1 -0
- package/frontend/dist/assets/less-CJ_VPy2C.js +2 -0
- package/frontend/dist/assets/lexon-BygAuZPu.js +1 -0
- package/frontend/dist/assets/line-CA_wh_TY.js +1 -0
- package/frontend/dist/assets/linear-BAcLW45z.js +1 -0
- package/frontend/dist/assets/liquid-kz84dle6.js +1 -0
- package/frontend/dist/assets/lspLanguageFeatures-C7hAHFn1.js +4 -0
- package/frontend/dist/assets/lua-C8Xs3dCx.js +1 -0
- package/frontend/dist/assets/m3-DTJeKBk4.js +1 -0
- package/frontend/dist/assets/markdown-QCgx8JqZ.js +1 -0
- package/frontend/dist/assets/math-D0YcMJAn.js +1 -0
- package/frontend/dist/assets/mdx-yRw0ap-E.js +1 -0
- package/frontend/dist/assets/mermaid-parser.core-DAeTodBQ.js +4 -0
- package/frontend/dist/assets/mindmap-definition-YRQLILUH-CoNlFyVl.js +68 -0
- package/frontend/dist/assets/mips-DopWaYgE.js +1 -0
- package/frontend/dist/assets/monaco.contribution-DeY0Qei-.js +2 -0
- package/frontend/dist/assets/msdax-BDis4ARV.js +1 -0
- package/frontend/dist/assets/mysql-BV6MLsOI.js +1 -0
- package/frontend/dist/assets/objective-c-B1UuzKs6.js +1 -0
- package/frontend/dist/assets/ordinal-jM7S0YHN.js +1 -0
- package/frontend/dist/assets/packet-RMMSAZCW-FF6-Tmai.js +1 -0
- package/frontend/dist/assets/pascal-BkvESCrc.js +1 -0
- package/frontend/dist/assets/pascaligo-lTy0kZYr.js +1 -0
- package/frontend/dist/assets/path-DNPd7Py7.js +1 -0
- package/frontend/dist/assets/perl-CrtUPXLV.js +1 -0
- package/frontend/dist/assets/pgsql-B9IbNWx2.js +1 -0
- package/frontend/dist/assets/php-CXvQBY2p.js +1 -0
- package/frontend/dist/assets/pie-UPGHQEXC-CFvXY2o-.js +1 -0
- package/frontend/dist/assets/pieDiagram-SKSYHLDU-CM_hbCcn.js +30 -0
- package/frontend/dist/assets/pla-DxBxuqWu.js +1 -0
- package/frontend/dist/assets/postiats-OkEuT5YF.js +1 -0
- package/frontend/dist/assets/powerquery-CMx5Tq4K.js +1 -0
- package/frontend/dist/assets/powershell-CstRxrEc.js +1 -0
- package/frontend/dist/assets/preload-helper-D4M6sveU.js +1 -0
- package/frontend/dist/assets/protobuf-Bx0Z-uRj.js +2 -0
- package/frontend/dist/assets/pug--W8vanWl.js +1 -0
- package/frontend/dist/assets/python-DA0rnlw3.js +1 -0
- package/frontend/dist/assets/qsharp-CRtr0YbN.js +1 -0
- package/frontend/dist/assets/quadrantDiagram-337W2JSQ-B3n3IUhC.js +7 -0
- package/frontend/dist/assets/r-C6E1d6iv.js +1 -0
- package/frontend/dist/assets/radar-KQ55EAFF-MPZu7SdX.js +1 -0
- package/frontend/dist/assets/razor-yd73uata.js +1 -0
- package/frontend/dist/assets/redis-Dx13voP3.js +1 -0
- package/frontend/dist/assets/redshift-D66HwlyV.js +1 -0
- package/frontend/dist/assets/requirementDiagram-Z7DCOOCP-CorP7L7F.js +73 -0
- package/frontend/dist/assets/restructuredtext-DQT2NKJ2.js +1 -0
- package/frontend/dist/assets/rough.esm-DxAX5Vpo.js +1 -0
- package/frontend/dist/assets/ruby-iFXI8hwH.js +1 -0
- package/frontend/dist/assets/rust-CSKiei34.js +1 -0
- package/frontend/dist/assets/sankeyDiagram-WA2Y5GQK-RDx6Bd-B.js +10 -0
- package/frontend/dist/assets/sb-Bo3ttdP2.js +1 -0
- package/frontend/dist/assets/scala-BC1D-Nxp.js +1 -0
- package/frontend/dist/assets/scheme-Z4OAo4Lv.js +1 -0
- package/frontend/dist/assets/scss-BvrdPs6B.js +3 -0
- package/frontend/dist/assets/sequenceDiagram-2WXFIKYE-JMqJSFq6.js +145 -0
- package/frontend/dist/assets/shell-Bh_aCyF-.js +1 -0
- package/frontend/dist/assets/solidity-CWHj6tSe.js +1 -0
- package/frontend/dist/assets/sophia-raoNtKtm.js +1 -0
- package/frontend/dist/assets/sparql-XzmoGnue.js +1 -0
- package/frontend/dist/assets/sql-BD0i9Gvg.js +1 -0
- package/frontend/dist/assets/src-Bn-kKzs7.js +1 -0
- package/frontend/dist/assets/st-DtVKyms6.js +1 -0
- package/frontend/dist/assets/stateDiagram-RAJIS63D-CgFfENdy.js +1 -0
- package/frontend/dist/assets/stateDiagram-v2-FVOUBMTO-C4Hh2P-U.js +1 -0
- package/frontend/dist/assets/swift--UZs77wT.js +1 -0
- package/frontend/dist/assets/systemverilog-CDnBSWUd.js +1 -0
- package/frontend/dist/assets/tcl-DdCEuTHZ.js +1 -0
- package/frontend/dist/assets/timeline-definition-YZTLITO2-BnatPBR5.js +61 -0
- package/frontend/dist/assets/treemap-KZPCXAKY-qb1Pl9la.js +1 -0
- package/frontend/dist/assets/ts.worker-DyPAEIuH.js +67719 -0
- package/frontend/dist/assets/tsMode-iuvyEpyO.js +11 -0
- package/frontend/dist/assets/twig-SSL-Altf.js +1 -0
- package/frontend/dist/assets/typescript-17918Hud.js +1 -0
- package/frontend/dist/assets/typespec-BT7S0ETg.js +1 -0
- package/frontend/dist/assets/vb-CrIgucua.js +1 -0
- package/frontend/dist/assets/vennDiagram-LZ73GAT5-DygS4Zzd.js +34 -0
- package/frontend/dist/assets/wgsl-BeKc3oEp.js +298 -0
- package/frontend/dist/assets/workers-DTfwKVoM.js +1 -0
- package/frontend/dist/assets/xml-CBMr_Wbw.js +1 -0
- package/frontend/dist/assets/xterm-BrP-ENHg.css +1 -0
- package/frontend/dist/assets/xterm-CBX2m0YM.js +36 -0
- package/frontend/dist/assets/xychartDiagram-JWTSCODW-D6wY1Jwd.js +7 -0
- package/frontend/dist/assets/yaml-CTjCH7Bv.js +1 -0
- package/frontend/dist/fonts/inter-300.ttf +0 -0
- package/frontend/dist/fonts/inter-400.ttf +0 -0
- package/frontend/dist/fonts/inter-500.ttf +0 -0
- package/frontend/dist/fonts/inter-600.ttf +0 -0
- package/frontend/dist/fonts/inter-700.ttf +0 -0
- package/frontend/dist/index.html +49 -0
- package/frontend/dist/logo_192x192.png +0 -0
- package/frontend/dist/logo_32x32.png +0 -0
- package/frontend/dist/logo_512x512.png +0 -0
- package/frontend/dist/logo_64x64.png +0 -0
- package/frontend/dist/logobg_192x192.png +0 -0
- package/frontend/dist/logobg_512x512.png +0 -0
- package/frontend/dist/logobg_64x64.png +0 -0
- package/frontend/dist/manifest.json +25 -0
- package/frontend/dist/sw.js +22 -0
- package/package.json +74 -7
- package/preload/Makefile +12 -0
- package/preload/atoo-studio-preload.c +647 -0
- package/preload/atoo-studio-preload.so +0 -0
- package/setup-cuse.sh +260 -0
- package/setup.sh +81 -0
- package/src/serial/native/binding.gyp +10 -0
- package/src/serial/native/pty_pair.c +222 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Injected scripts for Shadow Overlay interception.
|
|
3
|
+
* These scripts run inside the headless Chrome page via
|
|
4
|
+
* Page.addScriptToEvaluateOnNewDocument and intercept native
|
|
5
|
+
* controls that don't render in CDP screencast frames.
|
|
6
|
+
*
|
|
7
|
+
* Communication back to the server uses Runtime.addBinding.
|
|
8
|
+
*/
|
|
9
|
+
export declare function getInjectedScript(): string;
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Injected scripts for Shadow Overlay interception.
|
|
3
|
+
* These scripts run inside the headless Chrome page via
|
|
4
|
+
* Page.addScriptToEvaluateOnNewDocument and intercept native
|
|
5
|
+
* controls that don't render in CDP screencast frames.
|
|
6
|
+
*
|
|
7
|
+
* Communication back to the server uses Runtime.addBinding.
|
|
8
|
+
*/
|
|
9
|
+
export function getInjectedScript() {
|
|
10
|
+
return `(function() {
|
|
11
|
+
'use strict';
|
|
12
|
+
if (window.__atoo_injected) return;
|
|
13
|
+
window.__atoo_injected = true;
|
|
14
|
+
|
|
15
|
+
// === UTILITY: Build a unique CSS selector path for an element ===
|
|
16
|
+
function getSelectorPath(el) {
|
|
17
|
+
var parts = [];
|
|
18
|
+
while (el && el !== document.body && el !== document.documentElement) {
|
|
19
|
+
var selector = el.tagName.toLowerCase();
|
|
20
|
+
if (el.id) {
|
|
21
|
+
parts.unshift('#' + CSS.escape(el.id));
|
|
22
|
+
break;
|
|
23
|
+
}
|
|
24
|
+
var parent = el.parentElement;
|
|
25
|
+
if (parent) {
|
|
26
|
+
var siblings = Array.from(parent.children).filter(function(c) {
|
|
27
|
+
return c.tagName === el.tagName;
|
|
28
|
+
});
|
|
29
|
+
if (siblings.length > 1) {
|
|
30
|
+
selector += ':nth-of-type(' + (siblings.indexOf(el) + 1) + ')';
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
parts.unshift(selector);
|
|
34
|
+
el = parent;
|
|
35
|
+
}
|
|
36
|
+
return parts.join(' > ');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function getRect(el) {
|
|
40
|
+
var r = el.getBoundingClientRect();
|
|
41
|
+
return { x: r.x, y: r.y, width: r.width, height: r.height };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// === SELECT INTERCEPTION ===
|
|
45
|
+
document.addEventListener('mousedown', function(e) {
|
|
46
|
+
var el = e.target;
|
|
47
|
+
// Walk up to find a <select> (handles clicking on the arrow, etc.)
|
|
48
|
+
while (el && el.tagName !== 'SELECT') el = el.parentElement;
|
|
49
|
+
if (!el) return;
|
|
50
|
+
|
|
51
|
+
// Don't intercept <select multiple> — it renders as a native list box, not a dropdown
|
|
52
|
+
if (el.multiple) return;
|
|
53
|
+
|
|
54
|
+
// Only intercept if the binding is available — otherwise let native behavior work
|
|
55
|
+
if (typeof window.__atoo_selectOpened !== 'function') return;
|
|
56
|
+
|
|
57
|
+
e.preventDefault();
|
|
58
|
+
e.stopPropagation();
|
|
59
|
+
e.stopImmediatePropagation();
|
|
60
|
+
|
|
61
|
+
var options = [];
|
|
62
|
+
for (var i = 0; i < el.options.length; i++) {
|
|
63
|
+
var opt = el.options[i];
|
|
64
|
+
var group = opt.parentElement && opt.parentElement.tagName === 'OPTGROUP'
|
|
65
|
+
? opt.parentElement.label : null;
|
|
66
|
+
options.push({
|
|
67
|
+
value: opt.value,
|
|
68
|
+
text: opt.textContent || opt.innerText,
|
|
69
|
+
selected: opt.selected,
|
|
70
|
+
disabled: opt.disabled,
|
|
71
|
+
group: group,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
try {
|
|
76
|
+
window.__atoo_selectOpened(JSON.stringify({
|
|
77
|
+
rect: getRect(el),
|
|
78
|
+
options: options,
|
|
79
|
+
selectedIndex: el.selectedIndex,
|
|
80
|
+
multiple: el.multiple,
|
|
81
|
+
selectorPath: getSelectorPath(el),
|
|
82
|
+
}));
|
|
83
|
+
} catch (err) { /* binding not available */ }
|
|
84
|
+
}, true);
|
|
85
|
+
|
|
86
|
+
// === INPUT PICKER INTERCEPTION ===
|
|
87
|
+
var PICKER_TYPES = ['date', 'time', 'datetime-local', 'month', 'week', 'color'];
|
|
88
|
+
var pickerFiredAt = 0;
|
|
89
|
+
|
|
90
|
+
function firePickerOpened(el) {
|
|
91
|
+
// Only intercept if the binding is actually available — otherwise let the input work normally
|
|
92
|
+
console.log('[atoo] firePickerOpened called, type=' + el.type + ', binding=' + typeof window.__atoo_pickerOpened);
|
|
93
|
+
if (typeof window.__atoo_pickerOpened !== 'function') {
|
|
94
|
+
console.log('[atoo] pickerOpened binding NOT available');
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
pickerFiredAt = Date.now();
|
|
98
|
+
try {
|
|
99
|
+
var payload = JSON.stringify({
|
|
100
|
+
type: el.type,
|
|
101
|
+
value: el.value,
|
|
102
|
+
min: el.min || null,
|
|
103
|
+
max: el.max || null,
|
|
104
|
+
step: el.step || null,
|
|
105
|
+
rect: getRect(el),
|
|
106
|
+
selectorPath: getSelectorPath(el),
|
|
107
|
+
});
|
|
108
|
+
console.log('[atoo] calling pickerOpened with:', payload);
|
|
109
|
+
window.__atoo_pickerOpened(payload);
|
|
110
|
+
console.log('[atoo] pickerOpened call returned');
|
|
111
|
+
return true;
|
|
112
|
+
} catch (err) {
|
|
113
|
+
console.log('[atoo] pickerOpened call FAILED:', err);
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function findPickerInput(target) {
|
|
119
|
+
var el = target;
|
|
120
|
+
while (el && el.tagName !== 'INPUT') el = el.parentElement;
|
|
121
|
+
if (!el || PICKER_TYPES.indexOf(el.type) === -1) return null;
|
|
122
|
+
return el;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
document.addEventListener('mousedown', function(e) {
|
|
126
|
+
console.log('[atoo] mousedown target:', e.target.tagName, e.target.type || '');
|
|
127
|
+
var el = findPickerInput(e.target);
|
|
128
|
+
if (!el) return;
|
|
129
|
+
|
|
130
|
+
console.log('[atoo] picker input found:', el.type);
|
|
131
|
+
// Try to fire the binding — only block default behavior if successful
|
|
132
|
+
if (!firePickerOpened(el)) return;
|
|
133
|
+
|
|
134
|
+
e.preventDefault();
|
|
135
|
+
e.stopPropagation();
|
|
136
|
+
e.stopImmediatePropagation();
|
|
137
|
+
}, true);
|
|
138
|
+
|
|
139
|
+
// Fallback: click listener in case mousedown doesn't fire reliably via CDP
|
|
140
|
+
document.addEventListener('click', function(e) {
|
|
141
|
+
var el = findPickerInput(e.target);
|
|
142
|
+
if (!el) return;
|
|
143
|
+
// Skip if mousedown already handled this (within 500ms)
|
|
144
|
+
if (Date.now() - pickerFiredAt < 500) return;
|
|
145
|
+
|
|
146
|
+
if (!firePickerOpened(el)) return;
|
|
147
|
+
|
|
148
|
+
e.preventDefault();
|
|
149
|
+
e.stopPropagation();
|
|
150
|
+
e.stopImmediatePropagation();
|
|
151
|
+
}, true);
|
|
152
|
+
|
|
153
|
+
// === TOOLTIP INTERCEPTION ===
|
|
154
|
+
var tooltipTimer = null;
|
|
155
|
+
var currentTooltipEl = null;
|
|
156
|
+
|
|
157
|
+
document.addEventListener('mouseover', function(e) {
|
|
158
|
+
var el = e.target;
|
|
159
|
+
while (el && !el.getAttribute('title')) el = el.parentElement;
|
|
160
|
+
if (!el || !el.getAttribute('title')) return;
|
|
161
|
+
|
|
162
|
+
var title = el.getAttribute('title');
|
|
163
|
+
// Remove native title to prevent browser tooltip
|
|
164
|
+
el.removeAttribute('title');
|
|
165
|
+
el.dataset.atooTitle = title;
|
|
166
|
+
currentTooltipEl = el;
|
|
167
|
+
|
|
168
|
+
clearTimeout(tooltipTimer);
|
|
169
|
+
tooltipTimer = setTimeout(function() {
|
|
170
|
+
try {
|
|
171
|
+
window.__atoo_tooltipShow(JSON.stringify({
|
|
172
|
+
text: title,
|
|
173
|
+
rect: getRect(el),
|
|
174
|
+
}));
|
|
175
|
+
} catch (err) { /* binding not available */ }
|
|
176
|
+
}, 500);
|
|
177
|
+
}, true);
|
|
178
|
+
|
|
179
|
+
document.addEventListener('mouseout', function(e) {
|
|
180
|
+
clearTimeout(tooltipTimer);
|
|
181
|
+
// Restore title attribute
|
|
182
|
+
if (currentTooltipEl && currentTooltipEl.dataset.atooTitle) {
|
|
183
|
+
currentTooltipEl.setAttribute('title', currentTooltipEl.dataset.atooTitle);
|
|
184
|
+
delete currentTooltipEl.dataset.atooTitle;
|
|
185
|
+
currentTooltipEl = null;
|
|
186
|
+
}
|
|
187
|
+
try {
|
|
188
|
+
window.__atoo_tooltipHide('{}');
|
|
189
|
+
} catch (err) { /* binding not available */ }
|
|
190
|
+
}, true);
|
|
191
|
+
|
|
192
|
+
// === CLIPBOARD COPY INTERCEPTION ===
|
|
193
|
+
document.addEventListener('copy', function() {
|
|
194
|
+
var sel = window.getSelection();
|
|
195
|
+
var text = sel ? sel.toString() : '';
|
|
196
|
+
if (text) {
|
|
197
|
+
try {
|
|
198
|
+
window.__atoo_clipboard(JSON.stringify({ text: text }));
|
|
199
|
+
} catch (err) { /* binding not available */ }
|
|
200
|
+
}
|
|
201
|
+
}, true);
|
|
202
|
+
|
|
203
|
+
// === CONTEXT MENU INTERCEPTION ===
|
|
204
|
+
document.addEventListener('contextmenu', function(e) {
|
|
205
|
+
e.preventDefault();
|
|
206
|
+
e.stopPropagation();
|
|
207
|
+
e.stopImmediatePropagation();
|
|
208
|
+
|
|
209
|
+
var sel = window.getSelection();
|
|
210
|
+
var selectedText = sel ? sel.toString() : '';
|
|
211
|
+
var link = null;
|
|
212
|
+
var el = e.target;
|
|
213
|
+
while (el) {
|
|
214
|
+
if (el.tagName === 'A' && el.href) { link = el; break; }
|
|
215
|
+
el = el.parentElement;
|
|
216
|
+
}
|
|
217
|
+
var img = e.target.closest ? e.target.closest('img') : null;
|
|
218
|
+
|
|
219
|
+
try {
|
|
220
|
+
window.__atoo_contextMenu(JSON.stringify({
|
|
221
|
+
x: e.clientX,
|
|
222
|
+
y: e.clientY,
|
|
223
|
+
selectedText: selectedText,
|
|
224
|
+
linkHref: link ? link.href : null,
|
|
225
|
+
linkText: link ? (link.textContent || '').trim() : null,
|
|
226
|
+
imgSrc: img ? img.src : null,
|
|
227
|
+
}));
|
|
228
|
+
} catch (err) { /* binding not available */ }
|
|
229
|
+
}, true);
|
|
230
|
+
|
|
231
|
+
})();`;
|
|
232
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { WebSocket } from 'ws';
|
|
2
|
+
export interface PendingDialog {
|
|
3
|
+
resolve: (accept: boolean, promptText?: string) => void;
|
|
4
|
+
timeout: ReturnType<typeof setTimeout>;
|
|
5
|
+
}
|
|
6
|
+
export interface PreviewViewport {
|
|
7
|
+
width: number;
|
|
8
|
+
height: number;
|
|
9
|
+
deviceScaleFactor: number;
|
|
10
|
+
isMobile: boolean;
|
|
11
|
+
hasTouch: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface PreviewInstanceBase {
|
|
14
|
+
id: string;
|
|
15
|
+
targetPort: number;
|
|
16
|
+
/** CDP port — only available in headless mode */
|
|
17
|
+
cdpPort?: number;
|
|
18
|
+
headerHost?: string;
|
|
19
|
+
protocol: 'http' | 'https';
|
|
20
|
+
viewport: PreviewViewport;
|
|
21
|
+
quality: number;
|
|
22
|
+
wsClients: Set<WebSocket>;
|
|
23
|
+
lastActivity: number;
|
|
24
|
+
recording: boolean;
|
|
25
|
+
recordedFrames: {
|
|
26
|
+
data: Buffer;
|
|
27
|
+
timestamp: number;
|
|
28
|
+
}[];
|
|
29
|
+
lastFrameTime: number;
|
|
30
|
+
lastStreamRestart: number;
|
|
31
|
+
pendingDialogs: Map<string, PendingDialog>;
|
|
32
|
+
pendingAuthRequests: Map<string, {
|
|
33
|
+
requestId: string;
|
|
34
|
+
timeout: ReturnType<typeof setTimeout>;
|
|
35
|
+
}>;
|
|
36
|
+
downloadDir: string;
|
|
37
|
+
}
|
|
38
|
+
export interface CreatePreviewOpts {
|
|
39
|
+
targetPort: number;
|
|
40
|
+
headerHost?: string;
|
|
41
|
+
protocol?: 'http' | 'https';
|
|
42
|
+
width?: number;
|
|
43
|
+
height?: number;
|
|
44
|
+
dpr?: number;
|
|
45
|
+
isMobile?: boolean;
|
|
46
|
+
hasTouch?: boolean;
|
|
47
|
+
quality?: number;
|
|
48
|
+
}
|
|
49
|
+
export interface PreviewBackend {
|
|
50
|
+
readonly mode: 'headless';
|
|
51
|
+
create(key: string, opts: CreatePreviewOpts): Promise<PreviewInstanceBase>;
|
|
52
|
+
destroy(instance: PreviewInstanceBase): Promise<void>;
|
|
53
|
+
setViewport(instance: PreviewInstanceBase, viewport: {
|
|
54
|
+
width: number;
|
|
55
|
+
height: number;
|
|
56
|
+
dpr?: number;
|
|
57
|
+
isMobile?: boolean;
|
|
58
|
+
hasTouch?: boolean;
|
|
59
|
+
}): Promise<void>;
|
|
60
|
+
setQuality(instance: PreviewInstanceBase, quality: number): Promise<void>;
|
|
61
|
+
navigate(instance: PreviewInstanceBase, url: string): Promise<void>;
|
|
62
|
+
reload(instance: PreviewInstanceBase): Promise<void>;
|
|
63
|
+
dispatchMouseEvent(instance: PreviewInstanceBase, params: any): Promise<void>;
|
|
64
|
+
dispatchKeyEvent(instance: PreviewInstanceBase, params: any): Promise<void>;
|
|
65
|
+
insertText(instance: PreviewInstanceBase, text: string): Promise<void>;
|
|
66
|
+
dispatchScrollEvent(instance: PreviewInstanceBase, params: {
|
|
67
|
+
x: number;
|
|
68
|
+
y: number;
|
|
69
|
+
deltaX: number;
|
|
70
|
+
deltaY: number;
|
|
71
|
+
}): Promise<void>;
|
|
72
|
+
screenshot(instance: PreviewInstanceBase, fullPage?: boolean): Promise<string>;
|
|
73
|
+
handleDialogResponse(instance: PreviewInstanceBase, dialogId: string, accept: boolean, promptText?: string): void;
|
|
74
|
+
handleFileChooserResponse(instance: PreviewInstanceBase, backendNodeId: number, files: string[]): Promise<void>;
|
|
75
|
+
getDownloadPath(instance: PreviewInstanceBase, guid: string): string | null;
|
|
76
|
+
handleSelectResponse(instance: PreviewInstanceBase, selectorPath: string, value: string): Promise<void>;
|
|
77
|
+
handlePickerResponse(instance: PreviewInstanceBase, selectorPath: string, value: string, inputType: string): Promise<void>;
|
|
78
|
+
handleAuthResponse(instance: PreviewInstanceBase, requestId: string, username: string, password: string): void;
|
|
79
|
+
handleAuthCancel(instance: PreviewInstanceBase, requestId: string): void;
|
|
80
|
+
handleContextMenuAction(instance: PreviewInstanceBase, action: string, params: any): Promise<void>;
|
|
81
|
+
startRecording(instance: PreviewInstanceBase): void;
|
|
82
|
+
stopRecording(instance: PreviewInstanceBase): Promise<string>;
|
|
83
|
+
/** Restart screencast/stream if stalled */
|
|
84
|
+
restartStream(instance: PreviewInstanceBase): Promise<void>;
|
|
85
|
+
/** Cleanup on startup (e.g. orphaned processes/containers) */
|
|
86
|
+
cleanupOrphans(): void;
|
|
87
|
+
shutdown(): Promise<void>;
|
|
88
|
+
}
|
|
89
|
+
/** Broadcast a JSON message to all connected WS clients */
|
|
90
|
+
export declare function broadcastJson(instance: PreviewInstanceBase, data: object): void;
|
|
91
|
+
/** Broadcast a binary frame to all connected WS clients */
|
|
92
|
+
export declare function broadcastBinary(instance: PreviewInstanceBase, data: Buffer): void;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Broadcast a JSON message to all connected WS clients */
|
|
2
|
+
export function broadcastJson(instance, data) {
|
|
3
|
+
const msg = JSON.stringify(data);
|
|
4
|
+
for (const ws of instance.wsClients) {
|
|
5
|
+
if (ws.readyState === 1)
|
|
6
|
+
ws.send(msg);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
/** Broadcast a binary frame to all connected WS clients */
|
|
10
|
+
export function broadcastBinary(instance, data) {
|
|
11
|
+
for (const ws of instance.wsClients) {
|
|
12
|
+
if (ws.readyState === 1)
|
|
13
|
+
ws.send(data);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Universal Setter — sets form element values bypassing framework guards.
|
|
3
|
+
*
|
|
4
|
+
* Uses the native prototype descriptor trick to bypass React/Vue/Angular
|
|
5
|
+
* controlled component state, then fires proper input + change events.
|
|
6
|
+
*/
|
|
7
|
+
export declare function buildUniversalSetterExpression(selectorPath: string, value: string): string;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Universal Setter — sets form element values bypassing framework guards.
|
|
3
|
+
*
|
|
4
|
+
* Uses the native prototype descriptor trick to bypass React/Vue/Angular
|
|
5
|
+
* controlled component state, then fires proper input + change events.
|
|
6
|
+
*/
|
|
7
|
+
export function buildUniversalSetterExpression(selectorPath, value) {
|
|
8
|
+
const escapedSelector = JSON.stringify(selectorPath);
|
|
9
|
+
const escapedValue = JSON.stringify(value);
|
|
10
|
+
return `(function() {
|
|
11
|
+
var el = document.querySelector(${escapedSelector});
|
|
12
|
+
if (!el) return false;
|
|
13
|
+
|
|
14
|
+
var tag = el.tagName;
|
|
15
|
+
var proto;
|
|
16
|
+
if (tag === 'SELECT') {
|
|
17
|
+
proto = HTMLSelectElement.prototype;
|
|
18
|
+
} else if (tag === 'TEXTAREA') {
|
|
19
|
+
proto = HTMLTextAreaElement.prototype;
|
|
20
|
+
} else {
|
|
21
|
+
proto = HTMLInputElement.prototype;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
var desc = Object.getOwnPropertyDescriptor(proto, 'value');
|
|
25
|
+
if (desc && desc.set) {
|
|
26
|
+
desc.set.call(el, ${escapedValue});
|
|
27
|
+
} else {
|
|
28
|
+
el.value = ${escapedValue};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// For <select>, also set selectedIndex
|
|
32
|
+
if (tag === 'SELECT') {
|
|
33
|
+
for (var i = 0; i < el.options.length; i++) {
|
|
34
|
+
if (el.options[i].value === ${escapedValue}) {
|
|
35
|
+
el.selectedIndex = i;
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Fire events that frameworks listen to
|
|
42
|
+
el.dispatchEvent(new Event('input', { bubbles: true }));
|
|
43
|
+
el.dispatchEvent(new Event('change', { bubbles: true }));
|
|
44
|
+
return true;
|
|
45
|
+
})()`;
|
|
46
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { PreviewInstanceBase, CreatePreviewOpts } from './preview/preview-backend.js';
|
|
2
|
+
export type { PreviewInstanceBase as PreviewInstance, CreatePreviewOpts } from './preview/preview-backend.js';
|
|
3
|
+
declare class PreviewManager {
|
|
4
|
+
private instances;
|
|
5
|
+
private backend;
|
|
6
|
+
private cleanupTimer;
|
|
7
|
+
private initialized;
|
|
8
|
+
constructor();
|
|
9
|
+
private init;
|
|
10
|
+
private ensureInitialized;
|
|
11
|
+
get backendMode(): string;
|
|
12
|
+
private makeKey;
|
|
13
|
+
get(projectId: string, tabId: string): PreviewInstanceBase | undefined;
|
|
14
|
+
create(projectId: string, tabId: string, opts: CreatePreviewOpts): Promise<PreviewInstanceBase>;
|
|
15
|
+
destroy(projectId: string, tabId: string): Promise<void>;
|
|
16
|
+
destroyAllForProject(projectId: string): Promise<void>;
|
|
17
|
+
setViewport(projectId: string, tabId: string, viewport: {
|
|
18
|
+
width: number;
|
|
19
|
+
height: number;
|
|
20
|
+
dpr?: number;
|
|
21
|
+
isMobile?: boolean;
|
|
22
|
+
hasTouch?: boolean;
|
|
23
|
+
}): Promise<void>;
|
|
24
|
+
setQuality(projectId: string, tabId: string, quality: number): Promise<void>;
|
|
25
|
+
navigate(projectId: string, tabId: string, url: string): Promise<void>;
|
|
26
|
+
reload(projectId: string, tabId: string): Promise<void>;
|
|
27
|
+
dispatchMouseEvent(projectId: string, tabId: string, params: any): Promise<void>;
|
|
28
|
+
dispatchKeyEvent(projectId: string, tabId: string, params: any): Promise<void>;
|
|
29
|
+
insertText(projectId: string, tabId: string, text: string): Promise<void>;
|
|
30
|
+
dispatchScrollEvent(projectId: string, tabId: string, params: {
|
|
31
|
+
x: number;
|
|
32
|
+
y: number;
|
|
33
|
+
deltaX: number;
|
|
34
|
+
deltaY: number;
|
|
35
|
+
}): Promise<void>;
|
|
36
|
+
handleDialogResponse(projectId: string, tabId: string, dialogId: string, accept: boolean, promptText?: string): void;
|
|
37
|
+
handleFileChooserResponse(projectId: string, tabId: string, backendNodeId: number, files: string[]): Promise<void>;
|
|
38
|
+
getDownloadPath(projectId: string, tabId: string, guid: string): string | null;
|
|
39
|
+
handleSelectResponse(projectId: string, tabId: string, selectorPath: string, value: string): Promise<void>;
|
|
40
|
+
handlePickerResponse(projectId: string, tabId: string, selectorPath: string, value: string, inputType: string): Promise<void>;
|
|
41
|
+
handleAuthResponse(projectId: string, tabId: string, requestId: string, username: string, password: string): void;
|
|
42
|
+
handleAuthCancel(projectId: string, tabId: string, requestId: string): void;
|
|
43
|
+
handleContextMenuAction(projectId: string, tabId: string, action: string, params: any): Promise<void>;
|
|
44
|
+
screenshot(projectId: string, tabId: string, fullPage?: boolean): Promise<string>;
|
|
45
|
+
startRecording(projectId: string, tabId: string): void;
|
|
46
|
+
stopRecording(projectId: string, tabId: string): Promise<string>;
|
|
47
|
+
private cleanupInactive;
|
|
48
|
+
shutdown(): Promise<void>;
|
|
49
|
+
}
|
|
50
|
+
export declare const previewManager: PreviewManager;
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { HeadlessBackend } from './preview/headless-backend.js';
|
|
2
|
+
const INACTIVITY_TIMEOUT = 5 * 60 * 1000; // 5 minutes
|
|
3
|
+
const CLEANUP_INTERVAL = 10 * 1000; // 10 seconds (also serves as stream watchdog)
|
|
4
|
+
class PreviewManager {
|
|
5
|
+
instances = new Map();
|
|
6
|
+
backend;
|
|
7
|
+
cleanupTimer = null;
|
|
8
|
+
initialized = false;
|
|
9
|
+
constructor() {
|
|
10
|
+
this.cleanupTimer = setInterval(() => this.cleanupInactive(), CLEANUP_INTERVAL);
|
|
11
|
+
// Backend selection is deferred to init() since it's async
|
|
12
|
+
this.init();
|
|
13
|
+
}
|
|
14
|
+
async init() {
|
|
15
|
+
// Force headless CDP mode (shadow overlay interception requires it)
|
|
16
|
+
this.backend = new HeadlessBackend();
|
|
17
|
+
console.log('[preview] Using headless backend (forced)');
|
|
18
|
+
this.backend.cleanupOrphans();
|
|
19
|
+
this.initialized = true;
|
|
20
|
+
}
|
|
21
|
+
async ensureInitialized() {
|
|
22
|
+
// Spin until init() completes (typically < 100ms)
|
|
23
|
+
while (!this.initialized) {
|
|
24
|
+
await new Promise(r => setTimeout(r, 50));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
get backendMode() {
|
|
28
|
+
return this.backend?.mode || 'initializing';
|
|
29
|
+
}
|
|
30
|
+
makeKey(projectId, tabId) {
|
|
31
|
+
return `${projectId}/${tabId}`;
|
|
32
|
+
}
|
|
33
|
+
get(projectId, tabId) {
|
|
34
|
+
return this.instances.get(this.makeKey(projectId, tabId));
|
|
35
|
+
}
|
|
36
|
+
// --- Public API (delegates to backend) ---
|
|
37
|
+
async create(projectId, tabId, opts) {
|
|
38
|
+
await this.ensureInitialized();
|
|
39
|
+
const key = this.makeKey(projectId, tabId);
|
|
40
|
+
// Destroy existing instance if any
|
|
41
|
+
if (this.instances.has(key)) {
|
|
42
|
+
await this.destroy(projectId, tabId);
|
|
43
|
+
}
|
|
44
|
+
const instance = await this.backend.create(key, opts);
|
|
45
|
+
this.instances.set(key, instance);
|
|
46
|
+
return instance;
|
|
47
|
+
}
|
|
48
|
+
async destroy(projectId, tabId) {
|
|
49
|
+
const key = this.makeKey(projectId, tabId);
|
|
50
|
+
const instance = this.instances.get(key);
|
|
51
|
+
if (!instance)
|
|
52
|
+
return;
|
|
53
|
+
this.instances.delete(key);
|
|
54
|
+
await this.backend.destroy(instance);
|
|
55
|
+
}
|
|
56
|
+
async destroyAllForProject(projectId) {
|
|
57
|
+
const prefix = `${projectId}/`;
|
|
58
|
+
const keys = Array.from(this.instances.keys()).filter(k => k.startsWith(prefix));
|
|
59
|
+
for (const key of keys) {
|
|
60
|
+
const [pid, tid] = key.split('/');
|
|
61
|
+
await this.destroy(pid, tid);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
async setViewport(projectId, tabId, viewport) {
|
|
65
|
+
const instance = this.get(projectId, tabId);
|
|
66
|
+
if (!instance)
|
|
67
|
+
return;
|
|
68
|
+
await this.backend.setViewport(instance, viewport);
|
|
69
|
+
}
|
|
70
|
+
async setQuality(projectId, tabId, quality) {
|
|
71
|
+
const instance = this.get(projectId, tabId);
|
|
72
|
+
if (!instance)
|
|
73
|
+
return;
|
|
74
|
+
await this.backend.setQuality(instance, quality);
|
|
75
|
+
}
|
|
76
|
+
async navigate(projectId, tabId, url) {
|
|
77
|
+
const instance = this.get(projectId, tabId);
|
|
78
|
+
if (!instance)
|
|
79
|
+
return;
|
|
80
|
+
await this.backend.navigate(instance, url);
|
|
81
|
+
}
|
|
82
|
+
async reload(projectId, tabId) {
|
|
83
|
+
const instance = this.get(projectId, tabId);
|
|
84
|
+
if (!instance)
|
|
85
|
+
return;
|
|
86
|
+
await this.backend.reload(instance);
|
|
87
|
+
}
|
|
88
|
+
async dispatchMouseEvent(projectId, tabId, params) {
|
|
89
|
+
const instance = this.get(projectId, tabId);
|
|
90
|
+
if (!instance)
|
|
91
|
+
return;
|
|
92
|
+
await this.backend.dispatchMouseEvent(instance, params);
|
|
93
|
+
}
|
|
94
|
+
async dispatchKeyEvent(projectId, tabId, params) {
|
|
95
|
+
const instance = this.get(projectId, tabId);
|
|
96
|
+
if (!instance)
|
|
97
|
+
return;
|
|
98
|
+
await this.backend.dispatchKeyEvent(instance, params);
|
|
99
|
+
}
|
|
100
|
+
async insertText(projectId, tabId, text) {
|
|
101
|
+
const instance = this.get(projectId, tabId);
|
|
102
|
+
if (!instance)
|
|
103
|
+
return;
|
|
104
|
+
await this.backend.insertText(instance, text);
|
|
105
|
+
}
|
|
106
|
+
async dispatchScrollEvent(projectId, tabId, params) {
|
|
107
|
+
const instance = this.get(projectId, tabId);
|
|
108
|
+
if (!instance)
|
|
109
|
+
return;
|
|
110
|
+
await this.backend.dispatchScrollEvent(instance, params);
|
|
111
|
+
}
|
|
112
|
+
handleDialogResponse(projectId, tabId, dialogId, accept, promptText) {
|
|
113
|
+
const instance = this.get(projectId, tabId);
|
|
114
|
+
if (!instance)
|
|
115
|
+
return;
|
|
116
|
+
this.backend.handleDialogResponse(instance, dialogId, accept, promptText);
|
|
117
|
+
}
|
|
118
|
+
async handleFileChooserResponse(projectId, tabId, backendNodeId, files) {
|
|
119
|
+
const instance = this.get(projectId, tabId);
|
|
120
|
+
if (!instance)
|
|
121
|
+
return;
|
|
122
|
+
await this.backend.handleFileChooserResponse(instance, backendNodeId, files);
|
|
123
|
+
}
|
|
124
|
+
getDownloadPath(projectId, tabId, guid) {
|
|
125
|
+
const instance = this.get(projectId, tabId);
|
|
126
|
+
if (!instance)
|
|
127
|
+
return null;
|
|
128
|
+
return this.backend.getDownloadPath(instance, guid);
|
|
129
|
+
}
|
|
130
|
+
// --- Shadow overlay response handlers ---
|
|
131
|
+
async handleSelectResponse(projectId, tabId, selectorPath, value) {
|
|
132
|
+
const instance = this.get(projectId, tabId);
|
|
133
|
+
if (!instance)
|
|
134
|
+
return;
|
|
135
|
+
await this.backend.handleSelectResponse(instance, selectorPath, value);
|
|
136
|
+
}
|
|
137
|
+
async handlePickerResponse(projectId, tabId, selectorPath, value, inputType) {
|
|
138
|
+
const instance = this.get(projectId, tabId);
|
|
139
|
+
if (!instance)
|
|
140
|
+
return;
|
|
141
|
+
await this.backend.handlePickerResponse(instance, selectorPath, value, inputType);
|
|
142
|
+
}
|
|
143
|
+
handleAuthResponse(projectId, tabId, requestId, username, password) {
|
|
144
|
+
const instance = this.get(projectId, tabId);
|
|
145
|
+
if (!instance)
|
|
146
|
+
return;
|
|
147
|
+
this.backend.handleAuthResponse(instance, requestId, username, password);
|
|
148
|
+
}
|
|
149
|
+
handleAuthCancel(projectId, tabId, requestId) {
|
|
150
|
+
const instance = this.get(projectId, tabId);
|
|
151
|
+
if (!instance)
|
|
152
|
+
return;
|
|
153
|
+
this.backend.handleAuthCancel(instance, requestId);
|
|
154
|
+
}
|
|
155
|
+
async handleContextMenuAction(projectId, tabId, action, params) {
|
|
156
|
+
const instance = this.get(projectId, tabId);
|
|
157
|
+
if (!instance)
|
|
158
|
+
return;
|
|
159
|
+
await this.backend.handleContextMenuAction(instance, action, params);
|
|
160
|
+
}
|
|
161
|
+
async screenshot(projectId, tabId, fullPage) {
|
|
162
|
+
const instance = this.get(projectId, tabId);
|
|
163
|
+
if (!instance)
|
|
164
|
+
throw new Error('Preview instance not found');
|
|
165
|
+
return this.backend.screenshot(instance, fullPage);
|
|
166
|
+
}
|
|
167
|
+
startRecording(projectId, tabId) {
|
|
168
|
+
const instance = this.get(projectId, tabId);
|
|
169
|
+
if (!instance)
|
|
170
|
+
return;
|
|
171
|
+
this.backend.startRecording(instance);
|
|
172
|
+
}
|
|
173
|
+
async stopRecording(projectId, tabId) {
|
|
174
|
+
const instance = this.get(projectId, tabId);
|
|
175
|
+
if (!instance)
|
|
176
|
+
throw new Error('Preview instance not found');
|
|
177
|
+
return this.backend.stopRecording(instance);
|
|
178
|
+
}
|
|
179
|
+
// --- Cleanup ---
|
|
180
|
+
cleanupInactive() {
|
|
181
|
+
const now = Date.now();
|
|
182
|
+
for (const [key, instance] of this.instances) {
|
|
183
|
+
if (instance.wsClients.size === 0 && now - instance.lastActivity > INACTIVITY_TIMEOUT) {
|
|
184
|
+
const [projectId, tabId] = key.split('/');
|
|
185
|
+
console.log(`[preview] Cleaning up inactive instance ${key}`);
|
|
186
|
+
this.destroy(projectId, tabId);
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
// Watchdog: restart stream only if user interacted recently but no frames arrived.
|
|
190
|
+
// CDP screencast only fires on repaints — a static page with no visual changes
|
|
191
|
+
// produces zero frames, which is normal, not a stall.
|
|
192
|
+
if (instance.wsClients.size > 0 &&
|
|
193
|
+
now - instance.lastFrameTime > 5000 &&
|
|
194
|
+
instance.lastActivity > instance.lastFrameTime &&
|
|
195
|
+
now - instance.lastStreamRestart > 30_000) {
|
|
196
|
+
console.log(`[preview] Stream stalled for ${key}, restarting...`);
|
|
197
|
+
instance.lastStreamRestart = now;
|
|
198
|
+
this.backend.restartStream(instance).catch(() => { });
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
async shutdown() {
|
|
203
|
+
if (this.cleanupTimer) {
|
|
204
|
+
clearInterval(this.cleanupTimer);
|
|
205
|
+
this.cleanupTimer = null;
|
|
206
|
+
}
|
|
207
|
+
for (const [key] of this.instances) {
|
|
208
|
+
const [projectId, tabId] = key.split('/');
|
|
209
|
+
await this.destroy(projectId, tabId);
|
|
210
|
+
}
|
|
211
|
+
if (this.backend) {
|
|
212
|
+
await this.backend.shutdown();
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
export const previewManager = new PreviewManager();
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function reconcileWorktrees(projectId: string, projectPath: string): void;
|
|
2
|
+
export declare function watchProject(projectId: string, projectPath: string): void;
|
|
3
|
+
export declare function unwatchProject(projectId: string): void;
|
|
4
|
+
export declare function watchEnvironmentProjects(envId: string): void;
|
|
5
|
+
export declare function unwatchAll(): void;
|
|
6
|
+
export declare function isWatching(projectId: string): boolean;
|