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,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared file-tracking utilities for all agent types.
|
|
3
|
+
*
|
|
4
|
+
* Level 1: LD_PRELOAD — intercepts syscalls for precise before-snapshots
|
|
5
|
+
* Level 2: inotify — kernel-level fs.watch (started via fsMonitor.watchPid)
|
|
6
|
+
* Level 3: Tool-result fallback — detects Write/Edit/NotebookEdit from JSONL events
|
|
7
|
+
*/
|
|
8
|
+
import fs from 'fs';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import os from 'os';
|
|
11
|
+
import { fsMonitor } from '../../fs-monitor.js';
|
|
12
|
+
const PRELOAD_SO_PATH = path.resolve(path.dirname(new URL(import.meta.url).pathname), '..', '..', '..', 'preload', 'atoo-studio-preload.so');
|
|
13
|
+
const PRELOAD_SOCKET_PATH = path.join(os.homedir(), '.atoo-studio', 'preload.sock');
|
|
14
|
+
/**
|
|
15
|
+
* Add LD_PRELOAD environment variables to an env record.
|
|
16
|
+
* Only adds them if the preload .so exists on disk.
|
|
17
|
+
*/
|
|
18
|
+
export function addPreloadEnv(env, preloadSessionId) {
|
|
19
|
+
if (fs.existsSync(PRELOAD_SO_PATH)) {
|
|
20
|
+
env.LD_PRELOAD = PRELOAD_SO_PATH;
|
|
21
|
+
env.ATOO_SESSION_ID = preloadSessionId;
|
|
22
|
+
env.ATOO_SOCKET_PATH = PRELOAD_SOCKET_PATH;
|
|
23
|
+
env.UV_USE_IO_URING = '0';
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Initialize all three levels of file change detection for an agent session.
|
|
28
|
+
*
|
|
29
|
+
* Call this after spawning the CLI process and obtaining the envId/pid.
|
|
30
|
+
*/
|
|
31
|
+
export function initFileTracking(opts) {
|
|
32
|
+
// Level 2: inotify
|
|
33
|
+
fsMonitor.watchPid(opts.sessionId, opts.pid, opts.cwd);
|
|
34
|
+
// Level 1: Register preload session mapping (if preload was enabled)
|
|
35
|
+
if (opts.preloadSessionId) {
|
|
36
|
+
fsMonitor.registerSessionMapping(opts.preloadSessionId, opts.sessionId);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// ═══════════════════════════════════════════════════════
|
|
40
|
+
// Level 3: Tool-result fallback — detect file changes from JSONL events
|
|
41
|
+
// ═══════════════════════════════════════════════════════
|
|
42
|
+
/**
|
|
43
|
+
* Tracks pending tool_use blocks and detects completed file-modifying tools.
|
|
44
|
+
* Create one instance per agent session and call `processEvent()` for each
|
|
45
|
+
* SessionEvent received from the JSONL watcher.
|
|
46
|
+
*/
|
|
47
|
+
export class ToolResultFileTracker {
|
|
48
|
+
pendingToolUses = new Map();
|
|
49
|
+
sessionId;
|
|
50
|
+
constructor(sessionId) {
|
|
51
|
+
this.sessionId = sessionId;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Process a SessionEvent. Indexes tool_use blocks from assistant messages
|
|
55
|
+
* and detects tool_result blocks from user messages, notifying fsMonitor
|
|
56
|
+
* for Write/Edit/NotebookEdit completions.
|
|
57
|
+
*/
|
|
58
|
+
processEvent(event) {
|
|
59
|
+
if (event.type === 'assistant') {
|
|
60
|
+
this.indexToolUses(event);
|
|
61
|
+
}
|
|
62
|
+
else if (event.type === 'user') {
|
|
63
|
+
this.matchToolResults(event);
|
|
64
|
+
}
|
|
65
|
+
else if (event.type === 'result') {
|
|
66
|
+
// Clean up stale pending tool uses at end of turn
|
|
67
|
+
this.pendingToolUses.clear();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
indexToolUses(event) {
|
|
71
|
+
const content = event.message?.content;
|
|
72
|
+
if (!Array.isArray(content))
|
|
73
|
+
return;
|
|
74
|
+
for (const block of content) {
|
|
75
|
+
if (block.type === 'tool_use' && block.id && block.name) {
|
|
76
|
+
this.pendingToolUses.set(block.id, {
|
|
77
|
+
name: block.name,
|
|
78
|
+
input: block.input || {},
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
matchToolResults(event) {
|
|
84
|
+
const content = event.message?.content;
|
|
85
|
+
if (!Array.isArray(content))
|
|
86
|
+
return;
|
|
87
|
+
for (const block of content) {
|
|
88
|
+
if (block.type === 'tool_result' && block.tool_use_id) {
|
|
89
|
+
const toolUse = this.pendingToolUses.get(block.tool_use_id);
|
|
90
|
+
if (toolUse && !block.is_error) {
|
|
91
|
+
this.notifyIfFileChange(toolUse);
|
|
92
|
+
this.pendingToolUses.delete(block.tool_use_id);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
notifyIfFileChange(toolUse) {
|
|
98
|
+
const { name, input } = toolUse;
|
|
99
|
+
if (name === 'Write' && input.file_path) {
|
|
100
|
+
fsMonitor.notifyToolChange(this.sessionId, input.file_path, 'Write');
|
|
101
|
+
}
|
|
102
|
+
else if (name === 'Edit' && input.file_path) {
|
|
103
|
+
fsMonitor.notifyToolChange(this.sessionId, input.file_path, 'Edit');
|
|
104
|
+
}
|
|
105
|
+
else if (name === 'NotebookEdit' && input.notebook_path) {
|
|
106
|
+
fsMonitor.notifyToolChange(this.sessionId, input.notebook_path, 'Edit');
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PTY-based activity status tracker.
|
|
3
|
+
*
|
|
4
|
+
* Encapsulates the burst-detection algorithm that determines whether an
|
|
5
|
+
* agent session is 'open', 'active', or needs 'attention'.
|
|
6
|
+
*
|
|
7
|
+
* Terminal-based agent adapters create an instance and feed it PTY data.
|
|
8
|
+
* Future non-terminal agents can implement their own status logic without
|
|
9
|
+
* using this class — the Agent interface only requires emitting status events.
|
|
10
|
+
*/
|
|
11
|
+
export type ActivityStatus = 'open' | 'active' | 'attention';
|
|
12
|
+
export declare class PtyActivityTracker {
|
|
13
|
+
private onStatusChange;
|
|
14
|
+
private userIsViewing;
|
|
15
|
+
private currentStatus;
|
|
16
|
+
private burstStartTime;
|
|
17
|
+
private burstPromoted;
|
|
18
|
+
private burstIdleTimer;
|
|
19
|
+
private preBurstStatus;
|
|
20
|
+
constructor(onStatusChange: (status: ActivityStatus) => void);
|
|
21
|
+
/**
|
|
22
|
+
* Call when PTY produces output.
|
|
23
|
+
* Only visible content (after ANSI stripping) counts as activity.
|
|
24
|
+
*/
|
|
25
|
+
onPtyData(data: string): void;
|
|
26
|
+
/** Called when the user focuses this session's tab. */
|
|
27
|
+
onFocused(): void;
|
|
28
|
+
/** Called when the user leaves this session's tab. */
|
|
29
|
+
onBlurred(): void;
|
|
30
|
+
/** Get current activity status. */
|
|
31
|
+
getStatus(): ActivityStatus;
|
|
32
|
+
/** Clean up timers. */
|
|
33
|
+
dispose(): void;
|
|
34
|
+
/** PTY has been silent for BURST_IDLE_MS — the burst is over. */
|
|
35
|
+
private onBurstIdle;
|
|
36
|
+
private setStatus;
|
|
37
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PTY-based activity status tracker.
|
|
3
|
+
*
|
|
4
|
+
* Encapsulates the burst-detection algorithm that determines whether an
|
|
5
|
+
* agent session is 'open', 'active', or needs 'attention'.
|
|
6
|
+
*
|
|
7
|
+
* Terminal-based agent adapters create an instance and feed it PTY data.
|
|
8
|
+
* Future non-terminal agents can implement their own status logic without
|
|
9
|
+
* using this class — the Agent interface only requires emitting status events.
|
|
10
|
+
*/
|
|
11
|
+
const BURST_IDLE_MS = 1000; // 1s of PTY silence = burst ended
|
|
12
|
+
const BURST_PROMOTE_MS = 3000; // 3s of sustained output = real work (not a re-render)
|
|
13
|
+
// Strip standard CSI escape sequences, keep visible characters (including Unicode)
|
|
14
|
+
const ANSI_RE = /\x1b\[[0-9;]*[a-zA-Z]/g;
|
|
15
|
+
export class PtyActivityTracker {
|
|
16
|
+
onStatusChange;
|
|
17
|
+
userIsViewing = false;
|
|
18
|
+
currentStatus = 'open';
|
|
19
|
+
burstStartTime = null;
|
|
20
|
+
burstPromoted = false;
|
|
21
|
+
burstIdleTimer = null;
|
|
22
|
+
preBurstStatus = 'open';
|
|
23
|
+
constructor(onStatusChange) {
|
|
24
|
+
this.onStatusChange = onStatusChange;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Call when PTY produces output.
|
|
28
|
+
* Only visible content (after ANSI stripping) counts as activity.
|
|
29
|
+
*/
|
|
30
|
+
onPtyData(data) {
|
|
31
|
+
const stripped = data.replace(ANSI_RE, '').replace(/[\r\n]+/g, ' ').trim();
|
|
32
|
+
if (!stripped)
|
|
33
|
+
return;
|
|
34
|
+
const now = Date.now();
|
|
35
|
+
// New burst: record pre-burst status and start time
|
|
36
|
+
if (this.burstStartTime === null) {
|
|
37
|
+
this.preBurstStatus = this.currentStatus;
|
|
38
|
+
this.burstStartTime = now;
|
|
39
|
+
this.burstPromoted = false;
|
|
40
|
+
}
|
|
41
|
+
// Check if burst should be promoted (sustained output >= BURST_PROMOTE_MS)
|
|
42
|
+
if (!this.burstPromoted && (now - this.burstStartTime) >= BURST_PROMOTE_MS) {
|
|
43
|
+
this.burstPromoted = true;
|
|
44
|
+
}
|
|
45
|
+
// Set active instantly for responsive UX
|
|
46
|
+
this.setStatus('active');
|
|
47
|
+
// Reset the idle timer — burst continues as long as data keeps flowing
|
|
48
|
+
if (this.burstIdleTimer)
|
|
49
|
+
clearTimeout(this.burstIdleTimer);
|
|
50
|
+
this.burstIdleTimer = setTimeout(() => this.onBurstIdle(), BURST_IDLE_MS);
|
|
51
|
+
}
|
|
52
|
+
/** Called when the user focuses this session's tab. */
|
|
53
|
+
onFocused() {
|
|
54
|
+
this.userIsViewing = true;
|
|
55
|
+
if (this.currentStatus === 'attention') {
|
|
56
|
+
this.setStatus('open');
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/** Called when the user leaves this session's tab. */
|
|
60
|
+
onBlurred() {
|
|
61
|
+
this.userIsViewing = false;
|
|
62
|
+
}
|
|
63
|
+
/** Get current activity status. */
|
|
64
|
+
getStatus() {
|
|
65
|
+
return this.currentStatus;
|
|
66
|
+
}
|
|
67
|
+
/** Clean up timers. */
|
|
68
|
+
dispose() {
|
|
69
|
+
if (this.burstIdleTimer) {
|
|
70
|
+
clearTimeout(this.burstIdleTimer);
|
|
71
|
+
this.burstIdleTimer = null;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/** PTY has been silent for BURST_IDLE_MS — the burst is over. */
|
|
75
|
+
onBurstIdle() {
|
|
76
|
+
const wasPromoted = this.burstPromoted;
|
|
77
|
+
// Clear burst tracking
|
|
78
|
+
this.burstStartTime = null;
|
|
79
|
+
this.burstPromoted = false;
|
|
80
|
+
this.burstIdleTimer = null;
|
|
81
|
+
if (wasPromoted) {
|
|
82
|
+
if (this.userIsViewing) {
|
|
83
|
+
this.setStatus('open');
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
this.setStatus('attention');
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
// Short burst (re-render, keystroke echo) — revert, but respect viewing state
|
|
91
|
+
if (this.userIsViewing) {
|
|
92
|
+
this.setStatus('open');
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
this.setStatus(this.preBurstStatus);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
setStatus(status) {
|
|
100
|
+
if (status !== this.currentStatus) {
|
|
101
|
+
this.currentStatus = status;
|
|
102
|
+
this.onStatusChange(status);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export type LinkType = 'chain' | 'fork';
|
|
2
|
+
/**
|
|
3
|
+
* Strip any prefix (agent_, sess_) and dashes to get raw hex from a session ID.
|
|
4
|
+
*/
|
|
5
|
+
export declare function toRawHex(sessionId: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* Generate a parent-linked UUID with a chain/fork discriminator.
|
|
8
|
+
*
|
|
9
|
+
* Layout: {parent's last 16 hex}{c|f}{random 15 hex} = 32 hex total
|
|
10
|
+
*
|
|
11
|
+
* @param parentSessionId - The parent session ID (any format: agent_xxx, sess_xxx, bare UUID)
|
|
12
|
+
* @param linkType - 'chain' for continuation sessions, 'fork' for branched sessions
|
|
13
|
+
* @returns A UUID-formatted string with embedded parent link and discriminator
|
|
14
|
+
*/
|
|
15
|
+
export declare function buildLinkedUuid(parentSessionId: string, linkType: LinkType): string;
|
|
16
|
+
/**
|
|
17
|
+
* Parse the link type from a session ID by inspecting the discriminator at hex position 16.
|
|
18
|
+
*
|
|
19
|
+
* @returns 'chain', 'fork', or null if no discriminator is present (root/old-format session)
|
|
20
|
+
*/
|
|
21
|
+
export declare function parseLinkType(sessionId: string): LinkType | null;
|
|
22
|
+
/**
|
|
23
|
+
* Get the parent link portion (first 16 hex chars) from a session ID.
|
|
24
|
+
* This corresponds to the parent's last 16 hex chars.
|
|
25
|
+
*/
|
|
26
|
+
export declare function getParentLink(sessionId: string): string;
|
|
27
|
+
/**
|
|
28
|
+
* Walk a session chain backward from a starting session ID.
|
|
29
|
+
* Returns all chain-linked session IDs in order from oldest to newest (starting session last).
|
|
30
|
+
*
|
|
31
|
+
* Only follows 'chain' links (discriminator 'c'). Fork links are ignored.
|
|
32
|
+
*
|
|
33
|
+
* @param sessionId - The session to start walking from
|
|
34
|
+
* @param allSessionIds - All known session IDs to search through
|
|
35
|
+
* @returns Array of session IDs forming the chain, oldest first
|
|
36
|
+
*/
|
|
37
|
+
export declare function walkChain(sessionId: string, allSessionIds: string[]): string[];
|
|
38
|
+
/**
|
|
39
|
+
* Resolve the chain head (most recent session) for a given session ID.
|
|
40
|
+
* Walks the full chain (backward then forward) and returns the last entry.
|
|
41
|
+
*
|
|
42
|
+
* @param sessionId - Any session in the chain
|
|
43
|
+
* @param allSessionIds - All known session IDs to search through
|
|
44
|
+
* @returns The most recent session UUID in the chain
|
|
45
|
+
*/
|
|
46
|
+
export declare function resolveChainHead(sessionId: string, allSessionIds: string[]): string;
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session ID utilities for parent-linked UUIDs with chain/fork discrimination.
|
|
3
|
+
*
|
|
4
|
+
* Session ID schema:
|
|
5
|
+
* {last 16 hex of parent}{discriminator}{random 15 hex} = 32 hex, formatted as UUID
|
|
6
|
+
*
|
|
7
|
+
* Discriminator at hex position 16:
|
|
8
|
+
* 'c' = chain link (continuation session, replaces compaction)
|
|
9
|
+
* 'f' = fork (branched session)
|
|
10
|
+
*
|
|
11
|
+
* Root sessions (no parent) have no discriminator — they're standard UUIDs.
|
|
12
|
+
*/
|
|
13
|
+
import crypto from 'crypto';
|
|
14
|
+
const DISCRIMINATOR = {
|
|
15
|
+
chain: 'c',
|
|
16
|
+
fork: 'f',
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Strip any prefix (agent_, sess_) and dashes to get raw hex from a session ID.
|
|
20
|
+
*/
|
|
21
|
+
export function toRawHex(sessionId) {
|
|
22
|
+
return sessionId.replace(/^(agent_|sess_)/, '').replace(/-/g, '');
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Format 32 hex chars as a UUID string (8-4-4-4-12).
|
|
26
|
+
*/
|
|
27
|
+
function formatAsUuid(hex) {
|
|
28
|
+
return [
|
|
29
|
+
hex.slice(0, 8),
|
|
30
|
+
hex.slice(8, 12),
|
|
31
|
+
hex.slice(12, 16),
|
|
32
|
+
hex.slice(16, 20),
|
|
33
|
+
hex.slice(20, 32),
|
|
34
|
+
].join('-');
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Generate a parent-linked UUID with a chain/fork discriminator.
|
|
38
|
+
*
|
|
39
|
+
* Layout: {parent's last 16 hex}{c|f}{random 15 hex} = 32 hex total
|
|
40
|
+
*
|
|
41
|
+
* @param parentSessionId - The parent session ID (any format: agent_xxx, sess_xxx, bare UUID)
|
|
42
|
+
* @param linkType - 'chain' for continuation sessions, 'fork' for branched sessions
|
|
43
|
+
* @returns A UUID-formatted string with embedded parent link and discriminator
|
|
44
|
+
*/
|
|
45
|
+
export function buildLinkedUuid(parentSessionId, linkType) {
|
|
46
|
+
const parentRaw = toRawHex(parentSessionId);
|
|
47
|
+
const last16 = parentRaw.slice(-16);
|
|
48
|
+
const disc = DISCRIMINATOR[linkType];
|
|
49
|
+
const randomHex = crypto.randomBytes(8).toString('hex').slice(0, 15); // 15 hex chars
|
|
50
|
+
const newHex = last16 + disc + randomHex;
|
|
51
|
+
return formatAsUuid(newHex);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Parse the link type from a session ID by inspecting the discriminator at hex position 16.
|
|
55
|
+
*
|
|
56
|
+
* @returns 'chain', 'fork', or null if no discriminator is present (root/old-format session)
|
|
57
|
+
*/
|
|
58
|
+
export function parseLinkType(sessionId) {
|
|
59
|
+
const hex = toRawHex(sessionId);
|
|
60
|
+
if (hex.length < 32)
|
|
61
|
+
return null;
|
|
62
|
+
const disc = hex[16];
|
|
63
|
+
if (disc === 'c')
|
|
64
|
+
return 'chain';
|
|
65
|
+
if (disc === 'f')
|
|
66
|
+
return 'fork';
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Get the parent link portion (first 16 hex chars) from a session ID.
|
|
71
|
+
* This corresponds to the parent's last 16 hex chars.
|
|
72
|
+
*/
|
|
73
|
+
export function getParentLink(sessionId) {
|
|
74
|
+
return toRawHex(sessionId).slice(0, 16);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Walk a session chain backward from a starting session ID.
|
|
78
|
+
* Returns all chain-linked session IDs in order from oldest to newest (starting session last).
|
|
79
|
+
*
|
|
80
|
+
* Only follows 'chain' links (discriminator 'c'). Fork links are ignored.
|
|
81
|
+
*
|
|
82
|
+
* @param sessionId - The session to start walking from
|
|
83
|
+
* @param allSessionIds - All known session IDs to search through
|
|
84
|
+
* @returns Array of session IDs forming the chain, oldest first
|
|
85
|
+
*/
|
|
86
|
+
export function walkChain(sessionId, allSessionIds) {
|
|
87
|
+
// Build lookup: last16 hex → session ID
|
|
88
|
+
const last16Map = new Map();
|
|
89
|
+
for (const id of allSessionIds) {
|
|
90
|
+
const hex = toRawHex(id);
|
|
91
|
+
if (hex.length >= 16) {
|
|
92
|
+
last16Map.set(hex.slice(-16), id);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const chain = [sessionId];
|
|
96
|
+
let current = sessionId;
|
|
97
|
+
// Walk backward: current's first16 = parent's last16, but only if it's a chain link
|
|
98
|
+
while (true) {
|
|
99
|
+
const linkType = parseLinkType(current);
|
|
100
|
+
if (linkType !== 'chain')
|
|
101
|
+
break;
|
|
102
|
+
const parentLink = getParentLink(current);
|
|
103
|
+
const parentId = last16Map.get(parentLink);
|
|
104
|
+
if (!parentId || parentId === current || chain.includes(parentId))
|
|
105
|
+
break;
|
|
106
|
+
chain.unshift(parentId);
|
|
107
|
+
current = parentId;
|
|
108
|
+
}
|
|
109
|
+
return chain;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Resolve the chain head (most recent session) for a given session ID.
|
|
113
|
+
* Walks the full chain (backward then forward) and returns the last entry.
|
|
114
|
+
*
|
|
115
|
+
* @param sessionId - Any session in the chain
|
|
116
|
+
* @param allSessionIds - All known session IDs to search through
|
|
117
|
+
* @returns The most recent session UUID in the chain
|
|
118
|
+
*/
|
|
119
|
+
export function resolveChainHead(sessionId, allSessionIds) {
|
|
120
|
+
// First walk backward to find the chain root
|
|
121
|
+
const backwardChain = walkChain(sessionId, allSessionIds);
|
|
122
|
+
const root = backwardChain[0];
|
|
123
|
+
// Build forward lookup: parent's last16 hex → child session IDs (chain links only)
|
|
124
|
+
const childrenOf = new Map();
|
|
125
|
+
for (const id of allSessionIds) {
|
|
126
|
+
if (parseLinkType(id) !== 'chain')
|
|
127
|
+
continue;
|
|
128
|
+
const parentLink = getParentLink(id);
|
|
129
|
+
const children = childrenOf.get(parentLink) || [];
|
|
130
|
+
children.push(id);
|
|
131
|
+
childrenOf.set(parentLink, children);
|
|
132
|
+
}
|
|
133
|
+
// Walk forward from root, following chain children
|
|
134
|
+
let current = root;
|
|
135
|
+
const visited = new Set([current]);
|
|
136
|
+
while (true) {
|
|
137
|
+
const currentLast16 = toRawHex(current).slice(-16);
|
|
138
|
+
const children = childrenOf.get(currentLast16) || [];
|
|
139
|
+
// Filter to unvisited chain children
|
|
140
|
+
const next = children.find(c => !visited.has(c));
|
|
141
|
+
if (!next)
|
|
142
|
+
break;
|
|
143
|
+
visited.add(next);
|
|
144
|
+
current = next;
|
|
145
|
+
}
|
|
146
|
+
return current;
|
|
147
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pre-create a Claude Code session JSONL file with a minimal seed conversation.
|
|
3
|
+
* Claude Code requires at least a user+assistant message pair to accept --resume.
|
|
4
|
+
*
|
|
5
|
+
* @returns The generated session UUID
|
|
6
|
+
*/
|
|
7
|
+
export declare function precreateClaudeSession(cwd: string, initialMessage?: string): string;
|
|
8
|
+
/**
|
|
9
|
+
* Pre-create a Codex session JSONL file by cloning the header (session_meta +
|
|
10
|
+
* developer prompt) from the most recent real Codex session and replacing the UUID.
|
|
11
|
+
* Codex requires the real developer prompt (permissions, sandbox config) to accept resume.
|
|
12
|
+
*
|
|
13
|
+
* @returns The generated session UUID
|
|
14
|
+
*/
|
|
15
|
+
export declare function precreateCodexSession(cwd: string): string;
|
|
16
|
+
/** Find the most recently modified Codex session JSONL file. */
|
|
17
|
+
export declare function findMostRecentCodexSession(): string | null;
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pre-create session files with minimal seed content so the CLI accepts --resume.
|
|
3
|
+
* The CLI is then started with --resume <uuid>, adopting our pre-created UUID.
|
|
4
|
+
* This eliminates hook-based or filesystem-based session UUID discovery.
|
|
5
|
+
*/
|
|
6
|
+
import crypto from 'crypto';
|
|
7
|
+
import fs from 'fs';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
import os from 'os';
|
|
10
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
11
|
+
const CLAUDE_PROJECTS_DIR = path.join(os.homedir(), '.claude', 'projects');
|
|
12
|
+
const CODEX_SESSIONS_DIR = path.join(os.homedir(), '.codex', 'sessions');
|
|
13
|
+
/**
|
|
14
|
+
* Pre-create a Claude Code session JSONL file with a minimal seed conversation.
|
|
15
|
+
* Claude Code requires at least a user+assistant message pair to accept --resume.
|
|
16
|
+
*
|
|
17
|
+
* @returns The generated session UUID
|
|
18
|
+
*/
|
|
19
|
+
export function precreateClaudeSession(cwd, initialMessage) {
|
|
20
|
+
const uuid = uuidv4();
|
|
21
|
+
const resolvedCwd = path.resolve(cwd);
|
|
22
|
+
let dirHash = resolvedCwd.replace(/[^a-zA-Z0-9]/g, '-');
|
|
23
|
+
if (dirHash.length > 200) {
|
|
24
|
+
const suffix = crypto.createHash('sha256').update(resolvedCwd).digest('hex').slice(0, 12);
|
|
25
|
+
dirHash = `${dirHash.slice(0, 200)}-${suffix}`;
|
|
26
|
+
}
|
|
27
|
+
const projectDir = path.join(CLAUDE_PROJECTS_DIR, dirHash);
|
|
28
|
+
const now = new Date().toISOString();
|
|
29
|
+
const userUuid = uuidv4();
|
|
30
|
+
const assistantUuid = uuidv4();
|
|
31
|
+
let greeting = 'Hello from Atoo Studio — Agentic Development Environment!';
|
|
32
|
+
if (initialMessage) {
|
|
33
|
+
greeting += '\n\n' + initialMessage;
|
|
34
|
+
}
|
|
35
|
+
const userEvent = JSON.stringify({
|
|
36
|
+
parentUuid: null,
|
|
37
|
+
isSidechain: false,
|
|
38
|
+
userType: 'external',
|
|
39
|
+
cwd: resolvedCwd,
|
|
40
|
+
sessionId: uuid,
|
|
41
|
+
type: 'user',
|
|
42
|
+
message: { role: 'user', content: greeting },
|
|
43
|
+
uuid: userUuid,
|
|
44
|
+
timestamp: now,
|
|
45
|
+
permissionMode: 'bypassPermissions',
|
|
46
|
+
});
|
|
47
|
+
const assistantEvent = JSON.stringify({
|
|
48
|
+
parentUuid: userUuid,
|
|
49
|
+
isSidechain: false,
|
|
50
|
+
userType: 'external',
|
|
51
|
+
cwd: resolvedCwd,
|
|
52
|
+
sessionId: uuid,
|
|
53
|
+
type: 'assistant',
|
|
54
|
+
message: {
|
|
55
|
+
role: 'assistant',
|
|
56
|
+
content: [{ type: 'text', text: 'Hello! How can I help you today?' }],
|
|
57
|
+
model: 'claude-sonnet-4-6',
|
|
58
|
+
stop_reason: 'end_turn',
|
|
59
|
+
},
|
|
60
|
+
uuid: assistantUuid,
|
|
61
|
+
timestamp: now,
|
|
62
|
+
});
|
|
63
|
+
fs.mkdirSync(projectDir, { recursive: true });
|
|
64
|
+
fs.writeFileSync(path.join(projectDir, `${uuid}.jsonl`), userEvent + '\n' + assistantEvent + '\n', { mode: 0o600 });
|
|
65
|
+
return uuid;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Pre-create a Codex session JSONL file by cloning the header (session_meta +
|
|
69
|
+
* developer prompt) from the most recent real Codex session and replacing the UUID.
|
|
70
|
+
* Codex requires the real developer prompt (permissions, sandbox config) to accept resume.
|
|
71
|
+
*
|
|
72
|
+
* @returns The generated session UUID
|
|
73
|
+
*/
|
|
74
|
+
export function precreateCodexSession(cwd) {
|
|
75
|
+
const uuid = uuidv4();
|
|
76
|
+
const now = new Date();
|
|
77
|
+
const year = now.getUTCFullYear();
|
|
78
|
+
const month = String(now.getUTCMonth() + 1).padStart(2, '0');
|
|
79
|
+
const day = String(now.getUTCDate()).padStart(2, '0');
|
|
80
|
+
const timestamp = now.toISOString().replace(/:/g, '-').replace(/\.\d+Z$/, '');
|
|
81
|
+
const dateDir = path.join(CODEX_SESSIONS_DIR, String(year), month, day);
|
|
82
|
+
fs.mkdirSync(dateDir, { recursive: true });
|
|
83
|
+
const filename = `rollout-${timestamp}-${uuid}.jsonl`;
|
|
84
|
+
const targetPath = path.join(dateDir, filename);
|
|
85
|
+
// Find the most recent real Codex session to clone its header from
|
|
86
|
+
const donorFile = findMostRecentCodexSession();
|
|
87
|
+
if (donorFile) {
|
|
88
|
+
// Read the first 2 lines (session_meta + developer prompt) from the donor
|
|
89
|
+
const content = fs.readFileSync(donorFile, 'utf-8');
|
|
90
|
+
const lines = content.split('\n').filter(l => l.trim());
|
|
91
|
+
const headerLines = lines.slice(0, 2);
|
|
92
|
+
// Replace the donor's UUID and cwd with our new values in both lines
|
|
93
|
+
const donorUuid = extractCodexUuid(headerLines[0]);
|
|
94
|
+
const resolvedCwd = path.resolve(cwd);
|
|
95
|
+
const newHeader = headerLines
|
|
96
|
+
.map(line => {
|
|
97
|
+
if (donorUuid)
|
|
98
|
+
line = line.replace(new RegExp(donorUuid, 'g'), uuid);
|
|
99
|
+
// Update cwd in session_meta payload
|
|
100
|
+
try {
|
|
101
|
+
const parsed = JSON.parse(line);
|
|
102
|
+
if (parsed?.type === 'session_meta' && parsed?.payload?.cwd) {
|
|
103
|
+
parsed.payload.cwd = resolvedCwd;
|
|
104
|
+
return JSON.stringify(parsed);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
catch { }
|
|
108
|
+
return line;
|
|
109
|
+
})
|
|
110
|
+
.join('\n') + '\n';
|
|
111
|
+
fs.writeFileSync(targetPath, newHeader, { mode: 0o600 });
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
// No donor session found — write minimal session_meta (may not resume, but won't crash)
|
|
115
|
+
const sessionMeta = JSON.stringify({
|
|
116
|
+
timestamp: now.toISOString(),
|
|
117
|
+
type: 'session_meta',
|
|
118
|
+
payload: {
|
|
119
|
+
id: uuid,
|
|
120
|
+
timestamp: now.toISOString(),
|
|
121
|
+
cwd: path.resolve(cwd),
|
|
122
|
+
originator: 'codex_cli_rs',
|
|
123
|
+
source: 'cli',
|
|
124
|
+
model_provider: 'openai',
|
|
125
|
+
git: {},
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
fs.writeFileSync(targetPath, sessionMeta + '\n', { mode: 0o600 });
|
|
129
|
+
}
|
|
130
|
+
return uuid;
|
|
131
|
+
}
|
|
132
|
+
/** Find the most recently modified Codex session JSONL file. */
|
|
133
|
+
export function findMostRecentCodexSession() {
|
|
134
|
+
try {
|
|
135
|
+
let best = null;
|
|
136
|
+
// Walk ~/.codex/sessions/YYYY/MM/DD/ directories (most recent first)
|
|
137
|
+
const years = fs.readdirSync(CODEX_SESSIONS_DIR).sort().reverse();
|
|
138
|
+
for (const year of years.slice(0, 2)) {
|
|
139
|
+
const yearDir = path.join(CODEX_SESSIONS_DIR, year);
|
|
140
|
+
const months = fs.readdirSync(yearDir).sort().reverse();
|
|
141
|
+
for (const month of months.slice(0, 2)) {
|
|
142
|
+
const monthDir = path.join(yearDir, month);
|
|
143
|
+
const days = fs.readdirSync(monthDir).sort().reverse();
|
|
144
|
+
for (const day of days.slice(0, 3)) {
|
|
145
|
+
const dayDir = path.join(monthDir, day);
|
|
146
|
+
const files = fs.readdirSync(dayDir).filter(f => f.endsWith('.jsonl'));
|
|
147
|
+
for (const f of files) {
|
|
148
|
+
const filePath = path.join(dayDir, f);
|
|
149
|
+
try {
|
|
150
|
+
const stat = fs.statSync(filePath);
|
|
151
|
+
if (!best || stat.mtimeMs > best.mtime) {
|
|
152
|
+
best = { path: filePath, mtime: stat.mtimeMs };
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
catch { }
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
if (best)
|
|
159
|
+
return best.path; // Found recent files, no need to keep searching
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return best?.path ?? null;
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/** Extract the session UUID from a Codex session_meta JSON line. */
|
|
169
|
+
function extractCodexUuid(line) {
|
|
170
|
+
try {
|
|
171
|
+
const parsed = JSON.parse(line);
|
|
172
|
+
return parsed?.payload?.id ?? null;
|
|
173
|
+
}
|
|
174
|
+
catch {
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
}
|