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,342 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reconstruct Claude Code JSONL from SessionEvent[] for fork/resume.
|
|
3
|
+
*
|
|
4
|
+
* This is the critical cross-agent bridge: it builds proper Claude JSONL
|
|
5
|
+
* events from the canonical SessionEvent type. Events from ANY agent
|
|
6
|
+
* (Claude, future Codex/Gemini) can be reconstructed into Claude's format,
|
|
7
|
+
* enabling cross-agent session resumability.
|
|
8
|
+
*
|
|
9
|
+
* Claude Code JSONL format (what `claude --resume <uuid>` expects):
|
|
10
|
+
* {"type":"user","uuid":"...","sessionId":"...","parentUuid":"...","message":{"role":"user","content":"..."}}
|
|
11
|
+
* {"type":"assistant","uuid":"...","sessionId":"...","parentUuid":"...","message":{"role":"assistant","content":[...],"model":"...","stop_reason":"..."}}
|
|
12
|
+
* {"type":"system","uuid":"...","sessionId":"...","subtype":"init","model":"...","permissionMode":"..."}
|
|
13
|
+
*/
|
|
14
|
+
import fs from 'fs';
|
|
15
|
+
import path from 'path';
|
|
16
|
+
import os from 'os';
|
|
17
|
+
import crypto from 'crypto';
|
|
18
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
19
|
+
import { buildLinkedUuid } from '../session-id-utils.js';
|
|
20
|
+
/**
|
|
21
|
+
* Convert an absolute directory path to the Claude project dir hash format.
|
|
22
|
+
* Replaces all non-alphanumeric chars with '-'.
|
|
23
|
+
* e.g. /home/furti/myproject -> -home-furti-myproject
|
|
24
|
+
*/
|
|
25
|
+
function projectDirHash(directory) {
|
|
26
|
+
const hashed = directory.replace(/[^a-zA-Z0-9]/g, '-');
|
|
27
|
+
if (hashed.length <= 200)
|
|
28
|
+
return hashed;
|
|
29
|
+
const suffix = crypto.createHash('sha256').update(directory).digest('hex').slice(0, 12);
|
|
30
|
+
return `${hashed.slice(0, 200)}-${suffix}`;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Build common envelope fields for a Claude JSONL event.
|
|
34
|
+
*/
|
|
35
|
+
function buildEnvelope(event, sessionId, uuid, parentUuid) {
|
|
36
|
+
const env = {
|
|
37
|
+
type: event.type,
|
|
38
|
+
uuid,
|
|
39
|
+
sessionId,
|
|
40
|
+
parentUuid,
|
|
41
|
+
};
|
|
42
|
+
if (event.timestamp)
|
|
43
|
+
env.timestamp = event.timestamp;
|
|
44
|
+
if (event.cwd)
|
|
45
|
+
env.cwd = event.cwd;
|
|
46
|
+
if (event.gitBranch)
|
|
47
|
+
env.gitBranch = event.gitBranch;
|
|
48
|
+
if (event.version)
|
|
49
|
+
env.version = event.version;
|
|
50
|
+
if (event.slug)
|
|
51
|
+
env.slug = event.slug;
|
|
52
|
+
if (event.userType)
|
|
53
|
+
env.userType = event.userType;
|
|
54
|
+
env.isSidechain = event.isSidechain ?? false;
|
|
55
|
+
if (event.isSynthetic)
|
|
56
|
+
env.isSynthetic = event.isSynthetic;
|
|
57
|
+
if (event.agentId)
|
|
58
|
+
env.agentId = event.agentId;
|
|
59
|
+
if (event.parent_tool_use_id)
|
|
60
|
+
env.parent_tool_use_id = event.parent_tool_use_id;
|
|
61
|
+
return env;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Reconstruct a UserEvent as a Claude JSONL event.
|
|
65
|
+
*/
|
|
66
|
+
function reconstructUser(event, sessionId, uuid, parentUuid) {
|
|
67
|
+
const out = buildEnvelope(event, sessionId, uuid, parentUuid);
|
|
68
|
+
out.message = {
|
|
69
|
+
role: 'user',
|
|
70
|
+
content: event.message.content,
|
|
71
|
+
};
|
|
72
|
+
if (event.toolUseResult)
|
|
73
|
+
out.toolUseResult = event.toolUseResult;
|
|
74
|
+
if (event.permissionMode)
|
|
75
|
+
out.permissionMode = event.permissionMode;
|
|
76
|
+
return out;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Reconstruct an AssistantEvent as a Claude JSONL event.
|
|
80
|
+
*/
|
|
81
|
+
function reconstructAssistant(event, sessionId, uuid, parentUuid) {
|
|
82
|
+
const out = buildEnvelope(event, sessionId, uuid, parentUuid);
|
|
83
|
+
out.message = {
|
|
84
|
+
role: 'assistant',
|
|
85
|
+
content: event.message.content,
|
|
86
|
+
};
|
|
87
|
+
if (event.message.model)
|
|
88
|
+
out.message.model = event.message.model;
|
|
89
|
+
if (event.message.stop_reason !== undefined)
|
|
90
|
+
out.message.stop_reason = event.message.stop_reason;
|
|
91
|
+
if (event.message.usage)
|
|
92
|
+
out.message.usage = event.message.usage;
|
|
93
|
+
return out;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Reconstruct a SystemEvent as a Claude JSONL event.
|
|
97
|
+
*/
|
|
98
|
+
function reconstructSystem(event, sessionId, uuid, parentUuid) {
|
|
99
|
+
const out = buildEnvelope(event, sessionId, uuid, parentUuid);
|
|
100
|
+
if (event.subtype)
|
|
101
|
+
out.subtype = event.subtype;
|
|
102
|
+
if (event.model)
|
|
103
|
+
out.model = event.model;
|
|
104
|
+
if (event.permissionMode)
|
|
105
|
+
out.permissionMode = event.permissionMode;
|
|
106
|
+
if (event.durationMs !== undefined)
|
|
107
|
+
out.durationMs = event.durationMs;
|
|
108
|
+
if (event.content)
|
|
109
|
+
out.content = event.content;
|
|
110
|
+
if (event.hookCount !== undefined)
|
|
111
|
+
out.hookCount = event.hookCount;
|
|
112
|
+
if (event.hookInfos)
|
|
113
|
+
out.hookInfos = event.hookInfos;
|
|
114
|
+
if (event.hookErrors)
|
|
115
|
+
out.hookErrors = event.hookErrors;
|
|
116
|
+
if (event.hasOutput !== undefined)
|
|
117
|
+
out.hasOutput = event.hasOutput;
|
|
118
|
+
if (event.preventedContinuation !== undefined)
|
|
119
|
+
out.preventedContinuation = event.preventedContinuation;
|
|
120
|
+
if (event.url)
|
|
121
|
+
out.url = event.url;
|
|
122
|
+
if (event.compactMetadata)
|
|
123
|
+
out.compactMetadata = event.compactMetadata;
|
|
124
|
+
if (event.message)
|
|
125
|
+
out.message = event.message;
|
|
126
|
+
return out;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Reconstruct a ResultEvent as a Claude JSONL event.
|
|
130
|
+
*/
|
|
131
|
+
function reconstructResult(event, sessionId, uuid, parentUuid) {
|
|
132
|
+
const out = buildEnvelope(event, sessionId, uuid, parentUuid);
|
|
133
|
+
if (event.subtype)
|
|
134
|
+
out.subtype = event.subtype;
|
|
135
|
+
if (event.result)
|
|
136
|
+
out.result = event.result;
|
|
137
|
+
if (event.message)
|
|
138
|
+
out.message = event.message;
|
|
139
|
+
return out;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Reconstruct a ControlRequestEvent as a Claude JSONL event.
|
|
143
|
+
*/
|
|
144
|
+
function reconstructControlRequest(event, sessionId, uuid, parentUuid) {
|
|
145
|
+
const out = buildEnvelope(event, sessionId, uuid, parentUuid);
|
|
146
|
+
if (event.request_id)
|
|
147
|
+
out.request_id = event.request_id;
|
|
148
|
+
if (event.request)
|
|
149
|
+
out.request = event.request;
|
|
150
|
+
return out;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Reconstruct a ControlResponseEvent as a Claude JSONL event.
|
|
154
|
+
*/
|
|
155
|
+
function reconstructControlResponse(event, sessionId, uuid, parentUuid) {
|
|
156
|
+
const out = buildEnvelope(event, sessionId, uuid, parentUuid);
|
|
157
|
+
if (event.response)
|
|
158
|
+
out.response = event.response;
|
|
159
|
+
return out;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Reconstruct a single SessionEvent as a Claude JSONL event object.
|
|
163
|
+
* Maps from the canonical SessionEvent type to Claude's expected format.
|
|
164
|
+
*
|
|
165
|
+
* Events that don't map to conversational messages (progress, file-history-snapshot,
|
|
166
|
+
* last-prompt, queue-operation) are skipped — Claude --resume doesn't need them.
|
|
167
|
+
*/
|
|
168
|
+
function toClaudeJsonlEvent(event, sessionId, uuid, parentUuid) {
|
|
169
|
+
switch (event.type) {
|
|
170
|
+
case 'user':
|
|
171
|
+
return reconstructUser(event, sessionId, uuid, parentUuid);
|
|
172
|
+
case 'assistant':
|
|
173
|
+
return reconstructAssistant(event, sessionId, uuid, parentUuid);
|
|
174
|
+
case 'system':
|
|
175
|
+
return reconstructSystem(event, sessionId, uuid, parentUuid);
|
|
176
|
+
case 'result':
|
|
177
|
+
return reconstructResult(event, sessionId, uuid, parentUuid);
|
|
178
|
+
case 'control_request':
|
|
179
|
+
return reconstructControlRequest(event, sessionId, uuid, parentUuid);
|
|
180
|
+
case 'control_response':
|
|
181
|
+
return reconstructControlResponse(event, sessionId, uuid, parentUuid);
|
|
182
|
+
// Skip non-conversational events — not needed for resume
|
|
183
|
+
case 'progress':
|
|
184
|
+
case 'file-history-snapshot':
|
|
185
|
+
case 'last-prompt':
|
|
186
|
+
case 'queue-operation':
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
// ═══════════════════════════════════════════════════════
|
|
191
|
+
// Public API
|
|
192
|
+
// ═══════════════════════════════════════════════════════
|
|
193
|
+
/**
|
|
194
|
+
* Reconstruct SessionEvent[] as a Claude Code JSONL file for `claude --resume`.
|
|
195
|
+
* Path: ~/.claude/projects/<project-dir-hash>/<targetUuid>.jsonl
|
|
196
|
+
*
|
|
197
|
+
* Each SessionEvent is reconstructed into Claude's native JSONL format
|
|
198
|
+
* from its typed fields — not passed through as raw JSON. This enables
|
|
199
|
+
* cross-agent forking: events from any agent type can be written as
|
|
200
|
+
* valid Claude JSONL.
|
|
201
|
+
*
|
|
202
|
+
* @param events - Array of SessionEvents to write
|
|
203
|
+
* @param targetUuid - The UUID for the new session file (no "sess_" prefix)
|
|
204
|
+
* @param directory - The project working directory (for path hashing)
|
|
205
|
+
* @returns The full path to the written JSONL file
|
|
206
|
+
*/
|
|
207
|
+
export function writeForkedClaudeJsonl(events, targetUuid, directory) {
|
|
208
|
+
const dirHash = projectDirHash(path.resolve(directory));
|
|
209
|
+
const projectDir = path.join(os.homedir(), '.claude', 'projects', dirHash);
|
|
210
|
+
const jsonlPath = path.join(projectDir, `${targetUuid}.jsonl`);
|
|
211
|
+
// Ensure directory exists
|
|
212
|
+
fs.mkdirSync(projectDir, { recursive: true });
|
|
213
|
+
// Build UUID remap: old UUID -> new UUID (preserves parentUuid chain)
|
|
214
|
+
const uuidMap = new Map();
|
|
215
|
+
for (const event of events) {
|
|
216
|
+
if (event.uuid) {
|
|
217
|
+
uuidMap.set(event.uuid, uuidv4());
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
// First pass: determine which events will be written (not filtered out)
|
|
221
|
+
const writtenUuids = new Set();
|
|
222
|
+
for (const event of events) {
|
|
223
|
+
// Check if toClaudeJsonlEvent would produce output for this event type
|
|
224
|
+
const isConversational = ['user', 'assistant', 'system', 'result', 'control_request', 'control_response'].includes(event.type);
|
|
225
|
+
if (isConversational && event.uuid) {
|
|
226
|
+
writtenUuids.add(uuidMap.get(event.uuid));
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
const lines = [];
|
|
230
|
+
let lastUuid = null;
|
|
231
|
+
for (const event of events) {
|
|
232
|
+
const newUuid = (event.uuid && uuidMap.get(event.uuid)) || uuidv4();
|
|
233
|
+
// Resolve parentUuid: if the parent event was filtered out (e.g. progress),
|
|
234
|
+
// fall back to lastUuid to keep the conversation tree connected.
|
|
235
|
+
let newParentUuid;
|
|
236
|
+
if (event.parentUuid) {
|
|
237
|
+
const remapped = uuidMap.get(event.parentUuid) || null;
|
|
238
|
+
newParentUuid = (remapped && writtenUuids.has(remapped)) ? remapped : lastUuid;
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
newParentUuid = lastUuid;
|
|
242
|
+
}
|
|
243
|
+
const jsonlEvent = toClaudeJsonlEvent(event, targetUuid, newUuid, newParentUuid);
|
|
244
|
+
if (jsonlEvent) {
|
|
245
|
+
lines.push(JSON.stringify(jsonlEvent));
|
|
246
|
+
lastUuid = newUuid;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
fs.writeFileSync(jsonlPath, lines.join('\n') + '\n');
|
|
250
|
+
console.log(`[claude-jsonl-writer] Reconstructed ${lines.length} events to ${jsonlPath}`);
|
|
251
|
+
return jsonlPath;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Fork a slice of SessionEvents into a resumable JSONL file.
|
|
255
|
+
* Handles event slicing, range-fork synthetic init, UUID generation, and writing.
|
|
256
|
+
*
|
|
257
|
+
* @returns The resume UUID, or null if the fork point wasn't found.
|
|
258
|
+
*/
|
|
259
|
+
/**
|
|
260
|
+
* Fork a slice of SessionEvents into a resumable JSONL file.
|
|
261
|
+
* Handles event slicing, range-fork synthetic init, UUID generation, and writing.
|
|
262
|
+
*
|
|
263
|
+
* The returned UUID is parent-linked: its first 16 hex chars are the last 16 hex chars
|
|
264
|
+
* of the parent session ID, enabling tree-view reconstruction in session history.
|
|
265
|
+
*
|
|
266
|
+
* @returns The resume UUID, or null if the fork point wasn't found.
|
|
267
|
+
*/
|
|
268
|
+
export function forkEventsToResumable(events, afterEventUuid, directory, parentSessionId, fromEventUuid) {
|
|
269
|
+
if (events.length === 0)
|
|
270
|
+
return null;
|
|
271
|
+
const forkIdx = events.findIndex((e) => e.uuid === afterEventUuid);
|
|
272
|
+
if (forkIdx === -1)
|
|
273
|
+
return null;
|
|
274
|
+
let startIdx = 0;
|
|
275
|
+
if (fromEventUuid) {
|
|
276
|
+
startIdx = events.findIndex((e) => e.uuid === fromEventUuid);
|
|
277
|
+
if (startIdx === -1 || startIdx > forkIdx)
|
|
278
|
+
return null;
|
|
279
|
+
// Ensure the range starts with a user message so we can embed the context
|
|
280
|
+
// header into it. Claude Code's --resume branches from the first user
|
|
281
|
+
// message, so a separate synthetic init would make imported events a dead
|
|
282
|
+
// branch. Walk backward to find the preceding user message if needed.
|
|
283
|
+
if (events[startIdx].type !== 'user') {
|
|
284
|
+
for (let i = startIdx - 1; i >= 0; i--) {
|
|
285
|
+
if (events[i].type === 'user') {
|
|
286
|
+
startIdx = i;
|
|
287
|
+
break;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
let sliced = events.slice(startIdx, forkIdx + 1);
|
|
293
|
+
// Event boundary integrity: if the last event is an assistant message with tool_use blocks,
|
|
294
|
+
// include the corresponding tool_result user events and any child events
|
|
295
|
+
const lastEvent = sliced[sliced.length - 1];
|
|
296
|
+
if (lastEvent?.type === 'assistant' && Array.isArray(lastEvent.message?.content)) {
|
|
297
|
+
const toolUseIds = lastEvent.message.content
|
|
298
|
+
.filter((b) => b.type === 'tool_use')
|
|
299
|
+
.map((b) => b.id);
|
|
300
|
+
if (toolUseIds.length > 0) {
|
|
301
|
+
for (let i = forkIdx + 1; i < events.length; i++) {
|
|
302
|
+
const ev = events[i];
|
|
303
|
+
if (ev.parent_tool_use_id && toolUseIds.includes(ev.parent_tool_use_id)) {
|
|
304
|
+
sliced.push(ev);
|
|
305
|
+
continue;
|
|
306
|
+
}
|
|
307
|
+
if (ev.type === 'user' && Array.isArray(ev.message?.content)) {
|
|
308
|
+
const hasMatchingResult = ev.message.content.some((item) => item.type === 'tool_result' && toolUseIds.includes(item.tool_use_id));
|
|
309
|
+
if (hasMatchingResult) {
|
|
310
|
+
sliced.push(ev);
|
|
311
|
+
continue;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
// For range forks, inject a context header into the first event's content
|
|
318
|
+
// so the model knows this is imported context. We do NOT prepend a separate
|
|
319
|
+
// synthetic user message because Claude Code's --resume creates a new branch
|
|
320
|
+
// from the first user message, which would make the imported events a dead
|
|
321
|
+
// sibling branch that's never included in context.
|
|
322
|
+
if (fromEventUuid && sliced.length > 0) {
|
|
323
|
+
const header = '[This session continues from a selected range of a previous conversation. The messages below are the selected context. Continue from where this conversation left off.]';
|
|
324
|
+
const first = sliced[0];
|
|
325
|
+
if (first.type === 'user' && first.message) {
|
|
326
|
+
// Embed the context header into the first user message. We do NOT
|
|
327
|
+
// prepend a separate synthetic user message because Claude Code's
|
|
328
|
+
// --resume creates a new branch from the first user message, which
|
|
329
|
+
// would make the imported events a dead sibling branch.
|
|
330
|
+
const msg = first.message;
|
|
331
|
+
const content = typeof msg.content === 'string'
|
|
332
|
+
? `${header}\n\n${msg.content}`
|
|
333
|
+
: Array.isArray(msg.content)
|
|
334
|
+
? [{ type: 'text', text: header }, ...msg.content]
|
|
335
|
+
: msg.content;
|
|
336
|
+
sliced[0] = { ...first, message: { ...msg, content } };
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
const targetUuid = buildLinkedUuid(parentSessionId, 'fork');
|
|
340
|
+
writeForkedClaudeJsonl(sliced, targetUuid, directory);
|
|
341
|
+
return targetUuid;
|
|
342
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function ensureWorkspaceTrust(directory: string): void;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pre-trust a workspace directory in ~/.claude.json so that
|
|
3
|
+
* Claude CLI commands don't fail with "Workspace not trusted".
|
|
4
|
+
*/
|
|
5
|
+
import fs from 'fs';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import os from 'os';
|
|
8
|
+
export function ensureWorkspaceTrust(directory) {
|
|
9
|
+
const claudeJsonPath = path.join(os.homedir(), '.claude.json');
|
|
10
|
+
try {
|
|
11
|
+
let config = {};
|
|
12
|
+
if (fs.existsSync(claudeJsonPath)) {
|
|
13
|
+
config = JSON.parse(fs.readFileSync(claudeJsonPath, 'utf-8'));
|
|
14
|
+
}
|
|
15
|
+
if (!config.projects)
|
|
16
|
+
config.projects = {};
|
|
17
|
+
const absDir = path.resolve(directory);
|
|
18
|
+
if (!config.projects[absDir])
|
|
19
|
+
config.projects[absDir] = {};
|
|
20
|
+
if (!config.projects[absDir].hasTrustDialogAccepted) {
|
|
21
|
+
config.projects[absDir].hasTrustDialogAccepted = true;
|
|
22
|
+
fs.writeFileSync(claudeJsonPath, JSON.stringify(config, null, 2));
|
|
23
|
+
console.log(`[claude] Pre-trusted workspace: ${absDir}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
console.warn(`[claude] Failed to pre-trust workspace: ${err.message}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { SessionEvent } from '../../../events/types.js';
|
|
2
|
+
export interface CodexSessionMeta {
|
|
3
|
+
uuid: string;
|
|
4
|
+
directory: string;
|
|
5
|
+
title: string;
|
|
6
|
+
lastModified: string;
|
|
7
|
+
fileSize: number;
|
|
8
|
+
eventCount: number;
|
|
9
|
+
jsonlPath: string;
|
|
10
|
+
}
|
|
11
|
+
declare class CodexSessionScanner {
|
|
12
|
+
private cache;
|
|
13
|
+
private lastScanTime;
|
|
14
|
+
scan(): Promise<CodexSessionMeta[]>;
|
|
15
|
+
private walkSessionDirs;
|
|
16
|
+
private parseQuickMeta;
|
|
17
|
+
/**
|
|
18
|
+
* Read all events from a Codex session, converting to SessionEvent[].
|
|
19
|
+
*/
|
|
20
|
+
readEvents(uuid: string): Promise<SessionEvent[]>;
|
|
21
|
+
getByUuid(uuid: string): CodexSessionMeta | undefined;
|
|
22
|
+
invalidate(): void;
|
|
23
|
+
/**
|
|
24
|
+
* Find the JSONL file path for a given session UUID.
|
|
25
|
+
*/
|
|
26
|
+
findSessionFile(uuid: string): string | null;
|
|
27
|
+
private findFileByUuid;
|
|
28
|
+
/**
|
|
29
|
+
* Return JSONL file paths for sessions matching the given cwds.
|
|
30
|
+
*/
|
|
31
|
+
getFilesForProject(cwds: string[]): Promise<string[]>;
|
|
32
|
+
}
|
|
33
|
+
export declare const codexSessionScanner: CodexSessionScanner;
|
|
34
|
+
export {};
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scan ~/.codex/sessions/ for Codex session metadata.
|
|
3
|
+
*
|
|
4
|
+
* Codex stores sessions at:
|
|
5
|
+
* ~/.codex/sessions/YYYY/MM/DD/rollout-{timestamp}-{uuid}.jsonl
|
|
6
|
+
*
|
|
7
|
+
* The UUID is extracted from the filename.
|
|
8
|
+
*/
|
|
9
|
+
import fs from 'fs';
|
|
10
|
+
import path from 'path';
|
|
11
|
+
import os from 'os';
|
|
12
|
+
import { mapCodexJsonlLine } from './jsonl-mapper.js';
|
|
13
|
+
const CODEX_SESSIONS_DIR = path.join(os.homedir(), '.codex', 'sessions');
|
|
14
|
+
const CACHE_TTL = 30_000;
|
|
15
|
+
/**
|
|
16
|
+
* Extract UUID from Codex session filename.
|
|
17
|
+
* "rollout-2026-03-08T14-42-42-019ccdaf-9532-7b01-a95d-120dfe13ec7c.jsonl"
|
|
18
|
+
* → "019ccdaf-9532-7b01-a95d-120dfe13ec7c"
|
|
19
|
+
*/
|
|
20
|
+
function extractUuidFromFilename(filename) {
|
|
21
|
+
// UUID is at the end of the filename before .jsonl
|
|
22
|
+
// Pattern: rollout-{datetime}-{uuid}.jsonl where uuid has 5 groups
|
|
23
|
+
const match = filename.match(/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.jsonl$/);
|
|
24
|
+
return match ? match[1] : null;
|
|
25
|
+
}
|
|
26
|
+
class CodexSessionScanner {
|
|
27
|
+
cache = new Map();
|
|
28
|
+
lastScanTime = 0;
|
|
29
|
+
async scan() {
|
|
30
|
+
const now = Date.now();
|
|
31
|
+
if (now - this.lastScanTime < CACHE_TTL && this.cache.size > 0) {
|
|
32
|
+
return Array.from(this.cache.values());
|
|
33
|
+
}
|
|
34
|
+
const results = [];
|
|
35
|
+
try {
|
|
36
|
+
// Walk ~/.codex/sessions/YYYY/MM/DD/
|
|
37
|
+
this.walkSessionDirs(CODEX_SESSIONS_DIR, results);
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
// ~/.codex/sessions doesn't exist
|
|
41
|
+
}
|
|
42
|
+
this.cache.clear();
|
|
43
|
+
for (const meta of results) {
|
|
44
|
+
this.cache.set(meta.uuid, meta);
|
|
45
|
+
}
|
|
46
|
+
this.lastScanTime = now;
|
|
47
|
+
return results;
|
|
48
|
+
}
|
|
49
|
+
walkSessionDirs(baseDir, results) {
|
|
50
|
+
let yearDirs;
|
|
51
|
+
try {
|
|
52
|
+
yearDirs = fs.readdirSync(baseDir);
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
for (const year of yearDirs) {
|
|
58
|
+
const yearPath = path.join(baseDir, year);
|
|
59
|
+
let monthDirs;
|
|
60
|
+
try {
|
|
61
|
+
monthDirs = fs.readdirSync(yearPath);
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
for (const month of monthDirs) {
|
|
67
|
+
const monthPath = path.join(yearPath, month);
|
|
68
|
+
let dayDirs;
|
|
69
|
+
try {
|
|
70
|
+
dayDirs = fs.readdirSync(monthPath);
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
for (const day of dayDirs) {
|
|
76
|
+
const dayPath = path.join(monthPath, day);
|
|
77
|
+
let files;
|
|
78
|
+
try {
|
|
79
|
+
files = fs.readdirSync(dayPath);
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
for (const file of files) {
|
|
85
|
+
if (!file.endsWith('.jsonl'))
|
|
86
|
+
continue;
|
|
87
|
+
const uuid = extractUuidFromFilename(file);
|
|
88
|
+
if (!uuid)
|
|
89
|
+
continue;
|
|
90
|
+
const jsonlPath = path.join(dayPath, file);
|
|
91
|
+
try {
|
|
92
|
+
const stat = fs.statSync(jsonlPath);
|
|
93
|
+
if (stat.size === 0)
|
|
94
|
+
continue;
|
|
95
|
+
// Parse first few lines for metadata
|
|
96
|
+
const meta = this.parseQuickMeta(jsonlPath, uuid, stat);
|
|
97
|
+
if (meta)
|
|
98
|
+
results.push(meta);
|
|
99
|
+
}
|
|
100
|
+
catch { /* skip */ }
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
parseQuickMeta(jsonlPath, uuid, stat) {
|
|
107
|
+
// Read first 32KB for quick metadata extraction
|
|
108
|
+
const maxBytes = Math.min(stat.size, 32 * 1024);
|
|
109
|
+
const buf = Buffer.alloc(maxBytes);
|
|
110
|
+
const fd = fs.openSync(jsonlPath, 'r');
|
|
111
|
+
fs.readSync(fd, buf, 0, maxBytes, 0);
|
|
112
|
+
fs.closeSync(fd);
|
|
113
|
+
const chunk = buf.toString('utf-8');
|
|
114
|
+
const lines = chunk.split('\n');
|
|
115
|
+
let directory = '';
|
|
116
|
+
let title = '';
|
|
117
|
+
let lineCount = 0;
|
|
118
|
+
for (const line of lines) {
|
|
119
|
+
if (!line.trim())
|
|
120
|
+
continue;
|
|
121
|
+
lineCount++;
|
|
122
|
+
try {
|
|
123
|
+
const parsed = JSON.parse(line);
|
|
124
|
+
// Extract cwd from session_meta
|
|
125
|
+
if (parsed.type === 'session_meta' && parsed.payload?.cwd) {
|
|
126
|
+
directory = parsed.payload.cwd;
|
|
127
|
+
}
|
|
128
|
+
// Extract first user message as title
|
|
129
|
+
if (!title && parsed.type === 'event_msg' && parsed.payload?.type === 'user_message') {
|
|
130
|
+
title = (parsed.payload.message || '').substring(0, 100);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
catch { /* skip */ }
|
|
134
|
+
if (directory && title)
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
if (!directory)
|
|
138
|
+
return null;
|
|
139
|
+
// Extrapolate event count
|
|
140
|
+
const bytesRead = chunk.length;
|
|
141
|
+
let eventCount = lineCount;
|
|
142
|
+
if (bytesRead > 0 && bytesRead < stat.size) {
|
|
143
|
+
eventCount = Math.round((stat.size / bytesRead) * lineCount);
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
uuid,
|
|
147
|
+
directory,
|
|
148
|
+
title: title || 'Untitled',
|
|
149
|
+
lastModified: stat.mtime.toISOString(),
|
|
150
|
+
fileSize: stat.size,
|
|
151
|
+
eventCount,
|
|
152
|
+
jsonlPath,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Read all events from a Codex session, converting to SessionEvent[].
|
|
157
|
+
*/
|
|
158
|
+
async readEvents(uuid) {
|
|
159
|
+
const meta = this.cache.get(uuid);
|
|
160
|
+
if (!meta)
|
|
161
|
+
return [];
|
|
162
|
+
const content = fs.readFileSync(meta.jsonlPath, 'utf-8');
|
|
163
|
+
const events = [];
|
|
164
|
+
for (const line of content.split('\n')) {
|
|
165
|
+
if (!line.trim())
|
|
166
|
+
continue;
|
|
167
|
+
try {
|
|
168
|
+
const parsed = JSON.parse(line);
|
|
169
|
+
const mapped = mapCodexJsonlLine(parsed);
|
|
170
|
+
events.push(...mapped);
|
|
171
|
+
}
|
|
172
|
+
catch { /* skip */ }
|
|
173
|
+
}
|
|
174
|
+
return events;
|
|
175
|
+
}
|
|
176
|
+
getByUuid(uuid) {
|
|
177
|
+
return this.cache.get(uuid);
|
|
178
|
+
}
|
|
179
|
+
invalidate() {
|
|
180
|
+
this.cache.clear();
|
|
181
|
+
this.lastScanTime = 0;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Find the JSONL file path for a given session UUID.
|
|
185
|
+
*/
|
|
186
|
+
findSessionFile(uuid) {
|
|
187
|
+
const meta = this.cache.get(uuid);
|
|
188
|
+
if (meta)
|
|
189
|
+
return meta.jsonlPath;
|
|
190
|
+
// Walk the directory to find it
|
|
191
|
+
try {
|
|
192
|
+
return this.findFileByUuid(CODEX_SESSIONS_DIR, uuid);
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
findFileByUuid(baseDir, uuid) {
|
|
199
|
+
let yearDirs;
|
|
200
|
+
try {
|
|
201
|
+
yearDirs = fs.readdirSync(baseDir);
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
206
|
+
for (const year of yearDirs) {
|
|
207
|
+
const yearPath = path.join(baseDir, year);
|
|
208
|
+
let monthDirs;
|
|
209
|
+
try {
|
|
210
|
+
monthDirs = fs.readdirSync(yearPath);
|
|
211
|
+
}
|
|
212
|
+
catch {
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
for (const month of monthDirs) {
|
|
216
|
+
const monthPath = path.join(yearPath, month);
|
|
217
|
+
let dayDirs;
|
|
218
|
+
try {
|
|
219
|
+
dayDirs = fs.readdirSync(monthPath);
|
|
220
|
+
}
|
|
221
|
+
catch {
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
for (const day of dayDirs) {
|
|
225
|
+
const dayPath = path.join(monthPath, day);
|
|
226
|
+
let files;
|
|
227
|
+
try {
|
|
228
|
+
files = fs.readdirSync(dayPath);
|
|
229
|
+
}
|
|
230
|
+
catch {
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
for (const file of files) {
|
|
234
|
+
if (file.includes(uuid) && file.endsWith('.jsonl')) {
|
|
235
|
+
return path.join(dayPath, file);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return null;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Return JSONL file paths for sessions matching the given cwds.
|
|
245
|
+
*/
|
|
246
|
+
async getFilesForProject(cwds) {
|
|
247
|
+
await this.scan();
|
|
248
|
+
const cwdSet = new Set(cwds);
|
|
249
|
+
return Array.from(this.cache.values())
|
|
250
|
+
.filter(meta => cwdSet.has(meta.directory))
|
|
251
|
+
.sort((a, b) => new Date(b.lastModified).getTime() - new Date(a.lastModified).getTime())
|
|
252
|
+
.map(meta => meta.jsonlPath);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
export const codexSessionScanner = new CodexSessionScanner();
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SessionEvent } from '../../../events/types.js';
|
|
2
|
+
interface CodexLine {
|
|
3
|
+
timestamp?: string;
|
|
4
|
+
type: string;
|
|
5
|
+
payload: any;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Convert a single parsed Codex JSONL line into zero or more SessionEvents.
|
|
9
|
+
*/
|
|
10
|
+
export declare function mapCodexJsonlLine(line: CodexLine): SessionEvent[];
|
|
11
|
+
export {};
|