agent-relay 1.3.2 → 1.5.0
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/README.md +130 -158
- package/bin/relay-pty +0 -0
- package/bin/relay-pty-darwin-arm64 +0 -0
- package/bin/relay-pty-darwin-x64 +0 -0
- package/bin/relay-pty-linux-x64 +0 -0
- package/deploy/workspace/entrypoint.sh +9 -0
- package/dist/bridge/spawner.d.ts +4 -4
- package/dist/bridge/spawner.js +58 -92
- package/dist/cli/index.d.ts +8 -6
- package/dist/cli/index.js +282 -47
- package/dist/cloud/api/daemons.js +13 -32
- package/dist/cloud/api/onboarding.js +2 -4
- package/dist/cloud/api/providers.js +6 -0
- package/dist/cloud/config.d.ts +1 -0
- package/dist/cloud/config.js +2 -0
- package/dist/cloud/db/bulk-ingest.d.ts +2 -1
- package/dist/cloud/db/drizzle.d.ts +21 -26
- package/dist/cloud/db/drizzle.js +87 -100
- package/dist/cloud/db/index.d.ts +6 -5
- package/dist/cloud/db/index.js +9 -8
- package/dist/cloud/db/schema.d.ts +1049 -1076
- package/dist/cloud/db/schema.js +59 -71
- package/dist/cloud/server.js +854 -18
- package/dist/cloud/services/persistence.d.ts +15 -15
- package/dist/cloud/services/persistence.js +14 -14
- package/dist/daemon/agent-manager.d.ts +6 -5
- package/dist/daemon/agent-manager.js +12 -8
- package/dist/daemon/channel-membership-store.d.ts +48 -0
- package/dist/daemon/channel-membership-store.js +149 -0
- package/dist/daemon/cloud-sync.d.ts +2 -0
- package/dist/daemon/cloud-sync.js +4 -0
- package/dist/daemon/connection.js +17 -9
- package/dist/daemon/router.d.ts +37 -0
- package/dist/daemon/router.js +318 -79
- package/dist/daemon/server.d.ts +15 -0
- package/dist/daemon/server.js +141 -3
- package/dist/dashboard/out/404.html +1 -0
- package/dist/dashboard/out/_next/static/IxxVRv94L1w3ReRGAiI-k/_buildManifest.js +1 -0
- package/dist/dashboard/out/_next/static/IxxVRv94L1w3ReRGAiI-k/_ssgManifest.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/116-eacf84a131b80db9.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/117-c8afed19e821a35d.js +2 -0
- package/dist/dashboard/out/_next/static/chunks/282-980c2eb8fff20123.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/532-bace199897eeab37.js +9 -0
- package/dist/dashboard/out/_next/static/chunks/64-87ab9cd6bcf2f737.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/648-acb2ff9f77cbfbd3.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/766-aa7c8c9900ff5f53.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/83-4f08122d4e7e79a6.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/847-f1f467060f32afff.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/891-a024fbe4b619cf6f.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/app/_not-found/page-60501fddbafba9dc.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/app/app/onboarding/page-f746f29e01fffc43.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/app/app/page-ffad986adfcc8b31.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/app/cloud/link/page-cfeb437f08a12ed9.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/app/connect-repos/page-03ac6f35a6654ea6.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/app/history/page-240f91e8b06ba8ac.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/app/layout-c0d118c0f92d969c.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/app/login/page-6ec54eee75877971.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/app/metrics/page-82938ab8fcf44694.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/app/page-671037943b2f2e43.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/app/pricing/page-0efa024c28ba4597.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/app/providers/page-57cbd738c6a73859.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/app/providers/setup/[provider]/page-5ab0854472b402b0.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/app/signup/page-18a4665665f6be11.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/e868780c-48e5f147c90a3a41.js +18 -0
- package/dist/dashboard/out/_next/static/chunks/fd9d1056-609918ca7b6280bb.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/framework-f66176bb897dc684.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/main-5a40a5ae29646e1b.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/main-app-6e8e8d3ef4e0192a.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/pages/_app-72b849fbd24ac258.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/pages/_error-7ba65e1336b92748.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/webpack-1cdd8ed57114d5e1.js +1 -0
- package/dist/dashboard/out/_next/static/css/4034f236dd1a3178.css +1 -0
- package/dist/dashboard/out/_next/static/css/8f9ed310f454e5a5.css +1 -0
- package/dist/dashboard/out/alt-logos/agent-relay-logo-128.png +0 -0
- package/dist/dashboard/out/alt-logos/agent-relay-logo-256.png +0 -0
- package/dist/dashboard/out/alt-logos/agent-relay-logo-32.png +0 -0
- package/dist/dashboard/out/alt-logos/agent-relay-logo-512.png +0 -0
- package/dist/dashboard/out/alt-logos/agent-relay-logo-64.png +0 -0
- package/dist/dashboard/out/alt-logos/agent-relay-logo.svg +45 -0
- package/dist/dashboard/out/alt-logos/logo.svg +38 -0
- package/dist/dashboard/out/alt-logos/monogram-logo-128.png +0 -0
- package/dist/dashboard/out/alt-logos/monogram-logo-256.png +0 -0
- package/dist/dashboard/out/alt-logos/monogram-logo-32.png +0 -0
- package/dist/dashboard/out/alt-logos/monogram-logo-512.png +0 -0
- package/dist/dashboard/out/alt-logos/monogram-logo-64.png +0 -0
- package/dist/dashboard/out/alt-logos/monogram-logo.svg +38 -0
- package/dist/dashboard/out/app/onboarding.html +1 -0
- package/dist/dashboard/out/app/onboarding.txt +7 -0
- package/dist/dashboard/out/app.html +1 -0
- package/dist/dashboard/out/app.txt +7 -0
- package/dist/dashboard/out/apple-icon.png +0 -0
- package/dist/dashboard/out/cloud/link.html +1 -0
- package/dist/dashboard/out/cloud/link.txt +7 -0
- package/dist/dashboard/out/connect-repos.html +1 -0
- package/dist/dashboard/out/connect-repos.txt +7 -0
- package/dist/dashboard/out/history.html +1 -0
- package/dist/dashboard/out/history.txt +7 -0
- package/dist/dashboard/out/index.html +1 -0
- package/dist/dashboard/out/index.txt +7 -0
- package/dist/dashboard/out/login.html +5 -0
- package/dist/dashboard/out/login.txt +7 -0
- package/dist/dashboard/out/metrics.html +1 -0
- package/dist/dashboard/out/metrics.txt +7 -0
- package/dist/dashboard/out/pricing.html +13 -0
- package/dist/dashboard/out/pricing.txt +7 -0
- package/dist/dashboard/out/providers/setup/claude.html +1 -0
- package/dist/dashboard/out/providers/setup/claude.txt +8 -0
- package/dist/dashboard/out/providers/setup/codex.html +1 -0
- package/dist/dashboard/out/providers/setup/codex.txt +8 -0
- package/dist/dashboard/out/providers.html +1 -0
- package/dist/dashboard/out/providers.txt +7 -0
- package/dist/dashboard/out/signup.html +6 -0
- package/dist/dashboard/out/signup.txt +7 -0
- package/dist/dashboard-server/metrics.d.ts +105 -0
- package/dist/dashboard-server/metrics.js +193 -0
- package/dist/dashboard-server/needs-attention.d.ts +24 -0
- package/dist/dashboard-server/needs-attention.js +78 -0
- package/dist/dashboard-server/server.d.ts +15 -0
- package/dist/dashboard-server/server.js +4753 -0
- package/dist/dashboard-server/start.d.ts +6 -0
- package/dist/dashboard-server/start.js +13 -0
- package/dist/dashboard-server/user-bridge.d.ts +132 -0
- package/dist/dashboard-server/user-bridge.js +317 -0
- package/dist/protocol/channels.d.ts +14 -8
- package/dist/protocol/channels.js +1 -1
- package/dist/protocol/index.d.ts +1 -0
- package/dist/protocol/index.js +1 -0
- package/dist/protocol/relay-pty-schemas.d.ts +209 -0
- package/dist/protocol/relay-pty-schemas.js +60 -0
- package/dist/wrapper/auth-detection.js +8 -1
- package/dist/wrapper/base-wrapper.d.ts +11 -1
- package/dist/wrapper/base-wrapper.js +67 -6
- package/dist/wrapper/client.d.ts +49 -1
- package/dist/wrapper/client.js +167 -0
- package/dist/wrapper/parser.d.ts +0 -4
- package/dist/wrapper/parser.js +38 -10
- package/dist/wrapper/pty-wrapper.d.ts +12 -1
- package/dist/wrapper/pty-wrapper.js +104 -5
- package/dist/wrapper/relay-pty-orchestrator.d.ts +270 -0
- package/dist/wrapper/relay-pty-orchestrator.js +970 -0
- package/dist/wrapper/shared.d.ts +1 -1
- package/dist/wrapper/shared.js +14 -4
- package/dist/wrapper/tmux-wrapper.d.ts +13 -1
- package/dist/wrapper/tmux-wrapper.js +143 -29
- package/package.json +9 -4
- package/scripts/postinstall.js +101 -11
- package/.trajectories/active/traj_3yx9dy148mge.json +0 -42
- package/.trajectories/agent-relay-322-324.md +0 -17
- package/.trajectories/completed/2026-01/traj_03zupyv1s7b9.json +0 -49
- package/.trajectories/completed/2026-01/traj_03zupyv1s7b9.md +0 -31
- package/.trajectories/completed/2026-01/traj_0zacdjl1g4ht.json +0 -125
- package/.trajectories/completed/2026-01/traj_0zacdjl1g4ht.md +0 -62
- package/.trajectories/completed/2026-01/traj_1dviorhnkcb5.json +0 -65
- package/.trajectories/completed/2026-01/traj_1dviorhnkcb5.md +0 -37
- package/.trajectories/completed/2026-01/traj_1g7yx6qtg4ai.json +0 -49
- package/.trajectories/completed/2026-01/traj_1g7yx6qtg4ai.md +0 -31
- package/.trajectories/completed/2026-01/traj_1k5if5snst2e.json +0 -65
- package/.trajectories/completed/2026-01/traj_1k5if5snst2e.md +0 -37
- package/.trajectories/completed/2026-01/traj_1rp3rges5811.json +0 -49
- package/.trajectories/completed/2026-01/traj_1rp3rges5811.md +0 -31
- package/.trajectories/completed/2026-01/traj_22bhyulruouw.json +0 -113
- package/.trajectories/completed/2026-01/traj_22bhyulruouw.md +0 -57
- package/.trajectories/completed/2026-01/traj_2dao7ddgnta0.json +0 -53
- package/.trajectories/completed/2026-01/traj_2dao7ddgnta0.md +0 -32
- package/.trajectories/completed/2026-01/traj_33iuy72sezbk.json +0 -49
- package/.trajectories/completed/2026-01/traj_33iuy72sezbk.md +0 -31
- package/.trajectories/completed/2026-01/traj_3t0440mjeunc.json +0 -26
- package/.trajectories/completed/2026-01/traj_3t0440mjeunc.md +0 -6
- package/.trajectories/completed/2026-01/traj_45x9494d9xnr.json +0 -47
- package/.trajectories/completed/2026-01/traj_45x9494d9xnr.md +0 -32
- package/.trajectories/completed/2026-01/traj_4aa0bb77s4nh.json +0 -53
- package/.trajectories/completed/2026-01/traj_4aa0bb77s4nh.md +0 -32
- package/.trajectories/completed/2026-01/traj_4qwd4zmhfwp4.json +0 -49
- package/.trajectories/completed/2026-01/traj_4qwd4zmhfwp4.md +0 -31
- package/.trajectories/completed/2026-01/traj_5ammh5qtvklq.json +0 -77
- package/.trajectories/completed/2026-01/traj_5ammh5qtvklq.md +0 -42
- package/.trajectories/completed/2026-01/traj_5lhmzq8rxpqv.json +0 -59
- package/.trajectories/completed/2026-01/traj_5lhmzq8rxpqv.md +0 -33
- package/.trajectories/completed/2026-01/traj_5vr4e9erb1fs.json +0 -53
- package/.trajectories/completed/2026-01/traj_5vr4e9erb1fs.md +0 -32
- package/.trajectories/completed/2026-01/traj_6fgiwdoklvym.json +0 -48
- package/.trajectories/completed/2026-01/traj_6fgiwdoklvym.md +0 -24
- package/.trajectories/completed/2026-01/traj_6mieijqyvaag.json +0 -77
- package/.trajectories/completed/2026-01/traj_6mieijqyvaag.md +0 -42
- package/.trajectories/completed/2026-01/traj_6unwwmgyj5sq.json +0 -109
- package/.trajectories/completed/2026-01/traj_78ffm31jn3uk.json +0 -77
- package/.trajectories/completed/2026-01/traj_78ffm31jn3uk.md +0 -42
- package/.trajectories/completed/2026-01/traj_7ludwvz45veh.json +0 -209
- package/.trajectories/completed/2026-01/traj_7ludwvz45veh.md +0 -97
- package/.trajectories/completed/2026-01/traj_94gnp3k30goq.json +0 -66
- package/.trajectories/completed/2026-01/traj_94gnp3k30goq.md +0 -36
- package/.trajectories/completed/2026-01/traj_9921cuhel0pj.json +0 -48
- package/.trajectories/completed/2026-01/traj_9921cuhel0pj.md +0 -24
- package/.trajectories/completed/2026-01/traj_a0tqx8biw9c4.json +0 -49
- package/.trajectories/completed/2026-01/traj_a0tqx8biw9c4.md +0 -31
- package/.trajectories/completed/2026-01/traj_ajs7zqfux4wc.json +0 -49
- package/.trajectories/completed/2026-01/traj_ajs7zqfux4wc.md +0 -23
- package/.trajectories/completed/2026-01/traj_avqeghu6pz5a.json +0 -40
- package/.trajectories/completed/2026-01/traj_avqeghu6pz5a.md +0 -22
- package/.trajectories/completed/2026-01/traj_ax8uungxz2qh.json +0 -66
- package/.trajectories/completed/2026-01/traj_ax8uungxz2qh.md +0 -36
- package/.trajectories/completed/2026-01/traj_c9izbh2snpzf.json +0 -49
- package/.trajectories/completed/2026-01/traj_c9izbh2snpzf.md +0 -31
- package/.trajectories/completed/2026-01/traj_cpn70dw066nt.json +0 -65
- package/.trajectories/completed/2026-01/traj_cpn70dw066nt.md +0 -37
- package/.trajectories/completed/2026-01/traj_cvtqhlwcq9s0.json +0 -53
- package/.trajectories/completed/2026-01/traj_cvtqhlwcq9s0.md +0 -32
- package/.trajectories/completed/2026-01/traj_cxofprm2m2en.json +0 -49
- package/.trajectories/completed/2026-01/traj_cxofprm2m2en.md +0 -31
- package/.trajectories/completed/2026-01/traj_d2hhz3k0vrhn.json +0 -26
- package/.trajectories/completed/2026-01/traj_d2hhz3k0vrhn.md +0 -6
- package/.trajectories/completed/2026-01/traj_dcsp9s8y01ra.json +0 -121
- package/.trajectories/completed/2026-01/traj_dcsp9s8y01ra.md +0 -29
- package/.trajectories/completed/2026-01/traj_dfuvww9pege5.json +0 -59
- package/.trajectories/completed/2026-01/traj_dfuvww9pege5.md +0 -37
- package/.trajectories/completed/2026-01/traj_erglv2f8t9eh.json +0 -36
- package/.trajectories/completed/2026-01/traj_erglv2f8t9eh.md +0 -21
- package/.trajectories/completed/2026-01/traj_fhx9irlckht6.json +0 -53
- package/.trajectories/completed/2026-01/traj_fhx9irlckht6.md +0 -32
- package/.trajectories/completed/2026-01/traj_fqduidx3xbtp.json +0 -101
- package/.trajectories/completed/2026-01/traj_fqduidx3xbtp.md +0 -52
- package/.trajectories/completed/2026-01/traj_g0fisy9h51mf.json +0 -77
- package/.trajectories/completed/2026-01/traj_g0fisy9h51mf.md +0 -42
- package/.trajectories/completed/2026-01/traj_gjdre5voouod.json +0 -53
- package/.trajectories/completed/2026-01/traj_gjdre5voouod.md +0 -32
- package/.trajectories/completed/2026-01/traj_gtlyqtta3x8l.json +0 -25
- package/.trajectories/completed/2026-01/traj_gtlyqtta3x8l.md +0 -15
- package/.trajectories/completed/2026-01/traj_h4xijiuip3w4.json +0 -101
- package/.trajectories/completed/2026-01/traj_h4xijiuip3w4.md +0 -44
- package/.trajectories/completed/2026-01/traj_he75f24d1xfm.json +0 -101
- package/.trajectories/completed/2026-01/traj_he75f24d1xfm.md +0 -52
- package/.trajectories/completed/2026-01/traj_hf81ey93uz6t.json +0 -49
- package/.trajectories/completed/2026-01/traj_hf81ey93uz6t.md +0 -31
- package/.trajectories/completed/2026-01/traj_hfmki2jr9d4r.json +0 -65
- package/.trajectories/completed/2026-01/traj_hfmki2jr9d4r.md +0 -37
- package/.trajectories/completed/2026-01/traj_hhxte7w4gjjx.json +0 -22
- package/.trajectories/completed/2026-01/traj_hhxte7w4gjjx.md +0 -5
- package/.trajectories/completed/2026-01/traj_hpungyhoj6v5.json +0 -53
- package/.trajectories/completed/2026-01/traj_hpungyhoj6v5.md +0 -32
- package/.trajectories/completed/2026-01/traj_lgtodco7dp1n.json +0 -61
- package/.trajectories/completed/2026-01/traj_lgtodco7dp1n.md +0 -36
- package/.trajectories/completed/2026-01/traj_lq450ly148uw.json +0 -49
- package/.trajectories/completed/2026-01/traj_lq450ly148uw.md +0 -31
- package/.trajectories/completed/2026-01/traj_m2xkjv0w2sq7.json +0 -25
- package/.trajectories/completed/2026-01/traj_m2xkjv0w2sq7.md +0 -15
- package/.trajectories/completed/2026-01/traj_multi_server_arch.md +0 -101
- package/.trajectories/completed/2026-01/traj_noq5zbvnrdvz.json +0 -53
- package/.trajectories/completed/2026-01/traj_noq5zbvnrdvz.md +0 -32
- package/.trajectories/completed/2026-01/traj_ntbs6ppopf46.json +0 -53
- package/.trajectories/completed/2026-01/traj_ntbs6ppopf46.md +0 -32
- package/.trajectories/completed/2026-01/traj_oszg9flv74pk.json +0 -73
- package/.trajectories/completed/2026-01/traj_oszg9flv74pk.md +0 -41
- package/.trajectories/completed/2026-01/traj_ozd98si6a7ns.json +0 -48
- package/.trajectories/completed/2026-01/traj_ozd98si6a7ns.md +0 -24
- package/.trajectories/completed/2026-01/traj_prdza7a5cxp5.json +0 -53
- package/.trajectories/completed/2026-01/traj_prdza7a5cxp5.md +0 -32
- package/.trajectories/completed/2026-01/traj_psd9ob0j2ru3.json +0 -27
- package/.trajectories/completed/2026-01/traj_psd9ob0j2ru3.md +0 -14
- package/.trajectories/completed/2026-01/traj_pulomd3y8cvj.json +0 -77
- package/.trajectories/completed/2026-01/traj_pulomd3y8cvj.md +0 -42
- package/.trajectories/completed/2026-01/traj_qb3twvvywfwi.json +0 -77
- package/.trajectories/completed/2026-01/traj_qb3twvvywfwi.md +0 -42
- package/.trajectories/completed/2026-01/traj_qft54mi7nfor.json +0 -53
- package/.trajectories/completed/2026-01/traj_qft54mi7nfor.md +0 -32
- package/.trajectories/completed/2026-01/traj_qx9uhf8whhxo.json +0 -83
- package/.trajectories/completed/2026-01/traj_qx9uhf8whhxo.md +0 -47
- package/.trajectories/completed/2026-01/traj_rd9toccj18a0.json +0 -59
- package/.trajectories/completed/2026-01/traj_rd9toccj18a0.md +0 -37
- package/.trajectories/completed/2026-01/traj_rsavt0jipi3c.json +0 -109
- package/.trajectories/completed/2026-01/traj_rsavt0jipi3c.md +0 -56
- package/.trajectories/completed/2026-01/traj_rt4fiw3ecp50.json +0 -48
- package/.trajectories/completed/2026-01/traj_rt4fiw3ecp50.md +0 -16
- package/.trajectories/completed/2026-01/traj_st8j35b0hrlc.json +0 -59
- package/.trajectories/completed/2026-01/traj_st8j35b0hrlc.md +0 -37
- package/.trajectories/completed/2026-01/traj_t1yy8m7hbuxp.json +0 -53
- package/.trajectories/completed/2026-01/traj_t1yy8m7hbuxp.md +0 -32
- package/.trajectories/completed/2026-01/traj_tmux_orchestrator_analysis.json +0 -84
- package/.trajectories/completed/2026-01/traj_tmux_orchestrator_analysis.md +0 -109
- package/.trajectories/completed/2026-01/traj_u9n9eqasw16k.json +0 -53
- package/.trajectories/completed/2026-01/traj_u9n9eqasw16k.md +0 -32
- package/.trajectories/completed/2026-01/traj_ub8csuv3lcv4.json +0 -53
- package/.trajectories/completed/2026-01/traj_ub8csuv3lcv4.md +0 -32
- package/.trajectories/completed/2026-01/traj_uc29tlso8i9s.json +0 -186
- package/.trajectories/completed/2026-01/traj_uc29tlso8i9s.md +0 -86
- package/.trajectories/completed/2026-01/traj_ui9b4tqxoa7j.json +0 -77
- package/.trajectories/completed/2026-01/traj_ui9b4tqxoa7j.md +0 -42
- package/.trajectories/completed/2026-01/traj_v87hypnongqx.json +0 -71
- package/.trajectories/completed/2026-01/traj_v87hypnongqx.md +0 -42
- package/.trajectories/completed/2026-01/traj_v9dkdoxylyid.json +0 -89
- package/.trajectories/completed/2026-01/traj_v9dkdoxylyid.md +0 -47
- package/.trajectories/completed/2026-01/traj_wkp2fgzdyinb.json +0 -53
- package/.trajectories/completed/2026-01/traj_wkp2fgzdyinb.md +0 -32
- package/.trajectories/completed/2026-01/traj_x14t8w8rn7xg.json +0 -20
- package/.trajectories/completed/2026-01/traj_x14t8w8rn7xg.md +0 -6
- package/.trajectories/completed/2026-01/traj_x721m1j9rzup.json +0 -113
- package/.trajectories/completed/2026-01/traj_x721m1j9rzup.md +0 -57
- package/.trajectories/completed/2026-01/traj_xjqvmep5ed3h.json +0 -61
- package/.trajectories/completed/2026-01/traj_xjqvmep5ed3h.md +0 -36
- package/.trajectories/completed/2026-01/traj_xnwbznkvv8ua.json +0 -175
- package/.trajectories/completed/2026-01/traj_xnwbznkvv8ua.md +0 -82
- package/.trajectories/completed/2026-01/traj_xy9vifpqet80.json +0 -65
- package/.trajectories/completed/2026-01/traj_xy9vifpqet80.md +0 -37
- package/.trajectories/completed/2026-01/traj_y7aiwijyfmmv.json +0 -49
- package/.trajectories/completed/2026-01/traj_y7aiwijyfmmv.md +0 -31
- package/.trajectories/completed/2026-01/traj_y7n6hfbf7dmg.json +0 -49
- package/.trajectories/completed/2026-01/traj_y7n6hfbf7dmg.md +0 -31
- package/.trajectories/completed/2026-01/traj_ysjc8zaeqtd3.json +0 -47
- package/.trajectories/completed/2026-01/traj_ysjc8zaeqtd3.md +0 -32
- package/.trajectories/completed/2026-01/traj_yvdadtvdgnz3.json +0 -59
- package/.trajectories/completed/2026-01/traj_yvdadtvdgnz3.md +0 -37
- package/.trajectories/completed/2026-01/traj_yvfkwnkdiso2.json +0 -49
- package/.trajectories/completed/2026-01/traj_yvfkwnkdiso2.md +0 -31
- package/.trajectories/completed/2026-01/traj_z0vcw1wrzide.json +0 -53
- package/.trajectories/completed/2026-01/traj_z0vcw1wrzide.md +0 -32
- package/.trajectories/consolidate-settings-panel.md +0 -24
- package/.trajectories/gh-cli-user-token.md +0 -26
- package/.trajectories/index.json +0 -607
package/dist/wrapper/shared.d.ts
CHANGED
|
@@ -53,7 +53,7 @@ export declare const INJECTION_CONSTANTS: {
|
|
|
53
53
|
/** Timeout for injection verification (ms) */
|
|
54
54
|
readonly VERIFICATION_TIMEOUT_MS: 2000;
|
|
55
55
|
/** Delay between message and Enter key (ms) */
|
|
56
|
-
readonly ENTER_DELAY_MS:
|
|
56
|
+
readonly ENTER_DELAY_MS: 100;
|
|
57
57
|
/** Backoff multiplier for retries (ms per attempt) */
|
|
58
58
|
readonly RETRY_BACKOFF_MS: 300;
|
|
59
59
|
/** Delay between processing queued messages (ms) */
|
package/dist/wrapper/shared.js
CHANGED
|
@@ -19,7 +19,7 @@ export const INJECTION_CONSTANTS = {
|
|
|
19
19
|
/** Timeout for injection verification (ms) */
|
|
20
20
|
VERIFICATION_TIMEOUT_MS: 2000,
|
|
21
21
|
/** Delay between message and Enter key (ms) */
|
|
22
|
-
ENTER_DELAY_MS:
|
|
22
|
+
ENTER_DELAY_MS: 100,
|
|
23
23
|
/** Backoff multiplier for retries (ms per attempt) */
|
|
24
24
|
RETRY_BACKOFF_MS: 300,
|
|
25
25
|
/** Delay between processing queued messages (ms) */
|
|
@@ -58,6 +58,11 @@ export function sleep(ms) {
|
|
|
58
58
|
*/
|
|
59
59
|
export function buildInjectionString(msg) {
|
|
60
60
|
const shortId = msg.messageId.substring(0, 8);
|
|
61
|
+
// Use senderName from data if available (for dashboard messages sent via _DashboardUI)
|
|
62
|
+
// This allows showing the actual GitHub username instead of the system client name
|
|
63
|
+
const displayFrom = (msg.from === '_DashboardUI' && typeof msg.data?.senderName === 'string')
|
|
64
|
+
? msg.data.senderName
|
|
65
|
+
: msg.from;
|
|
61
66
|
// Strip ANSI and normalize whitespace
|
|
62
67
|
const sanitizedBody = stripAnsi(msg.body).replace(/[\r\n]+/g, ' ').trim();
|
|
63
68
|
// Thread hint
|
|
@@ -68,8 +73,13 @@ export function buildInjectionString(msg) {
|
|
|
68
73
|
: msg.importance !== undefined && msg.importance > 50
|
|
69
74
|
? ' [!]'
|
|
70
75
|
: '';
|
|
71
|
-
// Channel indicator for broadcasts
|
|
72
|
-
|
|
76
|
+
// Channel indicator for channel messages and broadcasts
|
|
77
|
+
// originalTo will be '*' for broadcasts or the channel name (e.g., '#general') for channel messages
|
|
78
|
+
const channelHint = msg.originalTo === '*'
|
|
79
|
+
? ' [#general]'
|
|
80
|
+
: msg.originalTo?.startsWith('#')
|
|
81
|
+
? ` [${msg.originalTo}]`
|
|
82
|
+
: '';
|
|
73
83
|
// Extract attachment file paths if present
|
|
74
84
|
let attachmentHint = '';
|
|
75
85
|
if (msg.data?.attachments && Array.isArray(msg.data.attachments)) {
|
|
@@ -80,7 +90,7 @@ export function buildInjectionString(msg) {
|
|
|
80
90
|
attachmentHint = ` [Attachments: ${filePaths.join(', ')}]`;
|
|
81
91
|
}
|
|
82
92
|
}
|
|
83
|
-
return `Relay message from ${
|
|
93
|
+
return `Relay message from ${displayFrom} [${shortId}]${threadHint}${importanceHint}${channelHint}${attachmentHint}: ${sanitizedBody}`;
|
|
84
94
|
}
|
|
85
95
|
/**
|
|
86
96
|
* Calculate injection success rate from metrics
|
|
@@ -232,9 +232,16 @@ export declare class TmuxWrapper extends BaseWrapper {
|
|
|
232
232
|
*/
|
|
233
233
|
private parseSessionEndAndClose;
|
|
234
234
|
/**
|
|
235
|
-
* Execute spawn via API (if dashboardPort set) or callback
|
|
235
|
+
* Execute spawn via API (if dashboardPort set) or callback.
|
|
236
|
+
* After spawning, waits for the agent to come online and sends the task via relay.
|
|
236
237
|
*/
|
|
237
238
|
protected executeSpawn(name: string, cli: string, task: string): Promise<void>;
|
|
239
|
+
/**
|
|
240
|
+
* Wait for a spawned agent to come online, then send the task via relay.
|
|
241
|
+
* Uses the wrapper's own relay client so the message comes "from" this agent,
|
|
242
|
+
* not from the dashboard's relay client.
|
|
243
|
+
*/
|
|
244
|
+
private waitAndSendTask;
|
|
238
245
|
/**
|
|
239
246
|
* Execute release via API (if dashboardPort set) or callback
|
|
240
247
|
*/
|
|
@@ -255,6 +262,11 @@ export declare class TmuxWrapper extends BaseWrapper {
|
|
|
255
262
|
* Agents should reply to originalTo to maintain channel routing (e.g., respond to #general, not DM).
|
|
256
263
|
*/
|
|
257
264
|
protected handleIncomingMessage(from: string, payload: SendPayload, messageId: string, meta?: SendMeta, originalTo?: string): void;
|
|
265
|
+
/**
|
|
266
|
+
* Handle incoming channel message from relay.
|
|
267
|
+
* Channel messages include a channel indicator so the agent knows to reply to the channel.
|
|
268
|
+
*/
|
|
269
|
+
protected handleIncomingChannelMessage(from: string, channel: string, body: string, envelope: import('../protocol/types.js').Envelope<import('../protocol/channels.js').ChannelMessagePayload>): void;
|
|
258
270
|
/**
|
|
259
271
|
* Check if we should inject a message.
|
|
260
272
|
* Uses UniversalIdleDetector (from BaseWrapper) for robust cross-CLI idle detection.
|
|
@@ -218,11 +218,18 @@ export class TmuxWrapper extends BaseWrapper {
|
|
|
218
218
|
if (!this.config.args || this.config.args.length === 0) {
|
|
219
219
|
return this.config.command;
|
|
220
220
|
}
|
|
221
|
-
// Quote any argument that contains spaces, quotes, or special chars
|
|
221
|
+
// Quote any argument that contains spaces, quotes, or shell special chars
|
|
222
|
+
// Must handle: spaces, quotes, $, <, >, |, &, ;, (, ), `, etc.
|
|
222
223
|
const quotedArgs = this.config.args.map(arg => {
|
|
223
|
-
if (
|
|
224
|
-
// Use double quotes and escape internal quotes
|
|
225
|
-
|
|
224
|
+
if (/[\s"'$<>|&;()`,!\\]/.test(arg)) {
|
|
225
|
+
// Use double quotes and escape internal quotes and special chars
|
|
226
|
+
const escaped = arg
|
|
227
|
+
.replace(/\\/g, '\\\\')
|
|
228
|
+
.replace(/"/g, '\\"')
|
|
229
|
+
.replace(/\$/g, '\\$')
|
|
230
|
+
.replace(/`/g, '\\`')
|
|
231
|
+
.replace(/!/g, '\\!');
|
|
232
|
+
return `"${escaped}"`;
|
|
226
233
|
}
|
|
227
234
|
return arg;
|
|
228
235
|
});
|
|
@@ -251,9 +258,14 @@ export class TmuxWrapper extends BaseWrapper {
|
|
|
251
258
|
this.inbox.init();
|
|
252
259
|
}
|
|
253
260
|
// Connect to relay daemon (in background, don't block)
|
|
254
|
-
this.client.connect()
|
|
261
|
+
this.client.connect()
|
|
262
|
+
.then(() => {
|
|
263
|
+
this.logStderr(`Relay connected (state: ${this.client.state})`, true);
|
|
264
|
+
})
|
|
265
|
+
.catch((err) => {
|
|
255
266
|
// Connection failures will retry via client backoff; surface once to stderr.
|
|
256
267
|
this.logStderr(`Relay connect failed: ${err.message}. Will retry if enabled.`, true);
|
|
268
|
+
this.logStderr(`Relay client state: ${this.client.state}`, true);
|
|
257
269
|
});
|
|
258
270
|
// Kill any existing session with this name
|
|
259
271
|
try {
|
|
@@ -330,9 +342,13 @@ export class TmuxWrapper extends BaseWrapper {
|
|
|
330
342
|
// Wait for shell to be ready (look for prompt)
|
|
331
343
|
await this.waitForShellReady();
|
|
332
344
|
// Send the command to run
|
|
345
|
+
this.logStderr('Sending command to tmux...');
|
|
333
346
|
await this.sendKeysLiteral(fullCommand);
|
|
334
|
-
await sleep(
|
|
347
|
+
await sleep(300); // Give shell time to process the command literal
|
|
348
|
+
this.logStderr('Sending Enter...');
|
|
335
349
|
await this.sendKeys('Enter');
|
|
350
|
+
await sleep(500); // Ensure Enter is processed and command starts before we continue
|
|
351
|
+
this.logStderr('Command sent');
|
|
336
352
|
}
|
|
337
353
|
catch (err) {
|
|
338
354
|
throw new Error(`Failed to create tmux session: ${err.message}`);
|
|
@@ -452,6 +468,8 @@ export class TmuxWrapper extends BaseWrapper {
|
|
|
452
468
|
async injectInstructions() {
|
|
453
469
|
if (!this.running)
|
|
454
470
|
return;
|
|
471
|
+
if (this.config.skipInstructions)
|
|
472
|
+
return;
|
|
455
473
|
// Use escaped prefix (\->relay:) in examples to prevent parser from treating them as real commands
|
|
456
474
|
const escapedPrefix = '\\' + this.relayPrefix;
|
|
457
475
|
// Build instructions including relay and trail
|
|
@@ -991,20 +1009,23 @@ export class TmuxWrapper extends BaseWrapper {
|
|
|
991
1009
|
});
|
|
992
1010
|
}
|
|
993
1011
|
/**
|
|
994
|
-
* Execute spawn via API (if dashboardPort set) or callback
|
|
1012
|
+
* Execute spawn via API (if dashboardPort set) or callback.
|
|
1013
|
+
* After spawning, waits for the agent to come online and sends the task via relay.
|
|
995
1014
|
*/
|
|
996
1015
|
async executeSpawn(name, cli, task) {
|
|
1016
|
+
let spawned = false;
|
|
997
1017
|
if (this.config.dashboardPort) {
|
|
998
1018
|
// Use dashboard API for spawning (works from any context, no terminal required)
|
|
999
1019
|
try {
|
|
1000
1020
|
const response = await fetch(`http://localhost:${this.config.dashboardPort}/api/spawn`, {
|
|
1001
1021
|
method: 'POST',
|
|
1002
1022
|
headers: { 'Content-Type': 'application/json' },
|
|
1003
|
-
body: JSON.stringify({ name, cli, task
|
|
1023
|
+
body: JSON.stringify({ name, cli }), // No task - we send it after agent is online
|
|
1004
1024
|
});
|
|
1005
1025
|
const result = await response.json();
|
|
1006
1026
|
if (result.success) {
|
|
1007
1027
|
this.logStderr(`Spawned ${name} via API`);
|
|
1028
|
+
spawned = true;
|
|
1008
1029
|
}
|
|
1009
1030
|
else {
|
|
1010
1031
|
this.logStderr(`Spawn failed: ${result.error}`, true);
|
|
@@ -1018,11 +1039,57 @@ export class TmuxWrapper extends BaseWrapper {
|
|
|
1018
1039
|
// Fall back to callback
|
|
1019
1040
|
try {
|
|
1020
1041
|
await this.config.onSpawn(name, cli, task);
|
|
1042
|
+
spawned = true;
|
|
1021
1043
|
}
|
|
1022
1044
|
catch (err) {
|
|
1023
1045
|
this.logStderr(`Spawn failed: ${err.message}`, true);
|
|
1024
1046
|
}
|
|
1025
1047
|
}
|
|
1048
|
+
// If spawn succeeded and we have a task, wait for agent to come online and send it
|
|
1049
|
+
if (spawned && task && task.trim() && this.config.dashboardPort) {
|
|
1050
|
+
await this.waitAndSendTask(name, task);
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
/**
|
|
1054
|
+
* Wait for a spawned agent to come online, then send the task via relay.
|
|
1055
|
+
* Uses the wrapper's own relay client so the message comes "from" this agent,
|
|
1056
|
+
* not from the dashboard's relay client.
|
|
1057
|
+
*/
|
|
1058
|
+
async waitAndSendTask(agentName, task) {
|
|
1059
|
+
const maxWaitMs = 30000;
|
|
1060
|
+
const pollIntervalMs = 500;
|
|
1061
|
+
const startTime = Date.now();
|
|
1062
|
+
this.logStderr(`Waiting for ${agentName} to come online...`);
|
|
1063
|
+
// Poll for agent to be online using dedicated status endpoint
|
|
1064
|
+
while (Date.now() - startTime < maxWaitMs) {
|
|
1065
|
+
try {
|
|
1066
|
+
const response = await fetch(`http://localhost:${this.config.dashboardPort}/api/agents/${encodeURIComponent(agentName)}/online`);
|
|
1067
|
+
const data = await response.json();
|
|
1068
|
+
if (data.online) {
|
|
1069
|
+
this.logStderr(`${agentName} is online, sending task...`);
|
|
1070
|
+
// Send task directly via our relay client (not dashboard API)
|
|
1071
|
+
// This ensures the message comes "from" this agent, not from _DashboardUI
|
|
1072
|
+
if (this.client.state === 'READY') {
|
|
1073
|
+
const sent = this.client.sendMessage(agentName, task, 'message');
|
|
1074
|
+
if (sent) {
|
|
1075
|
+
this.logStderr(`Task sent to ${agentName}`);
|
|
1076
|
+
}
|
|
1077
|
+
else {
|
|
1078
|
+
this.logStderr(`Failed to send task to ${agentName}: sendMessage returned false`, true);
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
else {
|
|
1082
|
+
this.logStderr(`Failed to send task to ${agentName}: relay client not ready (state: ${this.client.state})`, true);
|
|
1083
|
+
}
|
|
1084
|
+
return;
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
catch (err) {
|
|
1088
|
+
// Ignore poll errors, keep trying
|
|
1089
|
+
}
|
|
1090
|
+
await sleep(pollIntervalMs);
|
|
1091
|
+
}
|
|
1092
|
+
this.logStderr(`Timeout waiting for ${agentName} to come online`, true);
|
|
1026
1093
|
}
|
|
1027
1094
|
/**
|
|
1028
1095
|
* Execute release via API (if dashboardPort set) or callback
|
|
@@ -1069,6 +1136,10 @@ export class TmuxWrapper extends BaseWrapper {
|
|
|
1069
1136
|
// Only process if we have API or callbacks configured
|
|
1070
1137
|
const canSpawn = this.config.dashboardPort || this.config.onSpawn;
|
|
1071
1138
|
const canRelease = this.config.dashboardPort || this.config.onRelease;
|
|
1139
|
+
// Debug: Log spawn capability status
|
|
1140
|
+
if (content.includes('->relay:spawn')) {
|
|
1141
|
+
this.logStderr(`[spawn-debug] canSpawn=${!!canSpawn} dashboardPort=${this.config.dashboardPort} hasOnSpawn=${!!this.config.onSpawn}`);
|
|
1142
|
+
}
|
|
1072
1143
|
if (!canSpawn && !canRelease)
|
|
1073
1144
|
return;
|
|
1074
1145
|
const lines = content.split('\n');
|
|
@@ -1079,6 +1150,12 @@ export class TmuxWrapper extends BaseWrapper {
|
|
|
1079
1150
|
let trimmed = line.trim();
|
|
1080
1151
|
// Strip common line prefixes (bullets, prompts) before checking for commands
|
|
1081
1152
|
trimmed = trimmed.replace(linePrefixPattern, '');
|
|
1153
|
+
// Fix for over-stripping: the linePrefixPattern includes - and > characters,
|
|
1154
|
+
// which can accidentally strip the -> from ->relay:spawn, leaving just relay:spawn.
|
|
1155
|
+
// If we detect this happened, restore the -> prefix.
|
|
1156
|
+
if (/^(relay|thinking|continuity):/.test(trimmed)) {
|
|
1157
|
+
trimmed = '->' + trimmed;
|
|
1158
|
+
}
|
|
1082
1159
|
// If we're in fenced spawn mode, accumulate lines until we see >>>
|
|
1083
1160
|
if (this.pendingFencedSpawn) {
|
|
1084
1161
|
// Check for fence close (>>> at end of line or on its own line)
|
|
@@ -1217,6 +1294,40 @@ export class TmuxWrapper extends BaseWrapper {
|
|
|
1217
1294
|
// Try to inject
|
|
1218
1295
|
this.checkForInjectionOpportunity();
|
|
1219
1296
|
}
|
|
1297
|
+
/**
|
|
1298
|
+
* Handle incoming channel message from relay.
|
|
1299
|
+
* Channel messages include a channel indicator so the agent knows to reply to the channel.
|
|
1300
|
+
*/
|
|
1301
|
+
handleIncomingChannelMessage(from, channel, body, envelope) {
|
|
1302
|
+
const messageId = envelope.id;
|
|
1303
|
+
if (this.hasSeenIncoming(messageId)) {
|
|
1304
|
+
this.logStderr(`← ${from} [${channel}]: duplicate delivery (${messageId.substring(0, 8)})`);
|
|
1305
|
+
return;
|
|
1306
|
+
}
|
|
1307
|
+
const truncatedBody = body.substring(0, Math.min(DEBUG_LOG_TRUNCATE_LENGTH, body.length));
|
|
1308
|
+
this.logStderr(`← ${from} [${channel}]: ${truncatedBody}...`);
|
|
1309
|
+
// Record in trajectory via trail
|
|
1310
|
+
this.trajectory?.message('received', from, this.config.name, body);
|
|
1311
|
+
// Queue for injection - include channel as originalTo so we can inform the agent how to route responses
|
|
1312
|
+
this.messageQueue.push({
|
|
1313
|
+
from,
|
|
1314
|
+
body,
|
|
1315
|
+
messageId,
|
|
1316
|
+
thread: envelope.payload.thread,
|
|
1317
|
+
data: {
|
|
1318
|
+
_isChannelMessage: true,
|
|
1319
|
+
_channel: channel,
|
|
1320
|
+
_mentions: envelope.payload.mentions,
|
|
1321
|
+
},
|
|
1322
|
+
originalTo: channel, // Set channel as the reply target
|
|
1323
|
+
});
|
|
1324
|
+
// Write to inbox if enabled
|
|
1325
|
+
if (this.inbox) {
|
|
1326
|
+
this.inbox.addMessage(from, body);
|
|
1327
|
+
}
|
|
1328
|
+
// Try to inject
|
|
1329
|
+
this.checkForInjectionOpportunity();
|
|
1330
|
+
}
|
|
1220
1331
|
/**
|
|
1221
1332
|
* Check if we should inject a message.
|
|
1222
1333
|
* Uses UniversalIdleDetector (from BaseWrapper) for robust cross-CLI idle detection.
|
|
@@ -1236,11 +1347,6 @@ export class TmuxWrapper extends BaseWrapper {
|
|
|
1236
1347
|
setTimeout(() => this.checkForInjectionOpportunity(), retryMs);
|
|
1237
1348
|
return;
|
|
1238
1349
|
}
|
|
1239
|
-
// Log detection method in debug mode
|
|
1240
|
-
if (this.config.debug && idleResult.signals.length > 0) {
|
|
1241
|
-
const signalInfo = idleResult.signals.map(s => `${s.source}:${(s.confidence * 100).toFixed(0)}%`).join(', ');
|
|
1242
|
-
this.logStderr(`Idle detected (${signalInfo})`);
|
|
1243
|
-
}
|
|
1244
1350
|
this.injectNextMessage();
|
|
1245
1351
|
}
|
|
1246
1352
|
/**
|
|
@@ -1252,19 +1358,16 @@ export class TmuxWrapper extends BaseWrapper {
|
|
|
1252
1358
|
if (!msg)
|
|
1253
1359
|
return;
|
|
1254
1360
|
this.isInjecting = true;
|
|
1255
|
-
this.logStderr(`Injecting message from ${msg.from} (cli: ${this.cliType})`);
|
|
1256
1361
|
try {
|
|
1257
1362
|
const shortId = msg.messageId.substring(0, 8);
|
|
1258
1363
|
// Wait for input to be clear before injecting
|
|
1259
1364
|
// If input is not clear (human typing), re-queue and try later - never clear forcefully!
|
|
1260
|
-
// Fix for agent-relay-j9z: forceful clearing destroys human input in progress
|
|
1261
1365
|
const waitTimeoutMs = this.config.inputWaitTimeoutMs ?? 5000;
|
|
1262
1366
|
const waitPollMs = this.config.inputWaitPollMs ?? 200;
|
|
1263
1367
|
const inputClear = await this.waitForClearInput(waitTimeoutMs, waitPollMs);
|
|
1264
1368
|
if (!inputClear) {
|
|
1265
1369
|
// Input still has text after timeout - DON'T clear forcefully, re-queue instead
|
|
1266
|
-
|
|
1267
|
-
this.logStderr('Input not clear after waiting, re-queuing injection to preserve human input');
|
|
1370
|
+
this.logStderr('Input not clear, re-queuing injection');
|
|
1268
1371
|
this.messageQueue.unshift(msg);
|
|
1269
1372
|
this.isInjecting = false;
|
|
1270
1373
|
setTimeout(() => this.checkForInjectionOpportunity(), this.config.injectRetryMs ?? 1000);
|
|
@@ -1316,7 +1419,9 @@ export class TmuxWrapper extends BaseWrapper {
|
|
|
1316
1419
|
}
|
|
1317
1420
|
},
|
|
1318
1421
|
performInjection: async (inj) => {
|
|
1319
|
-
|
|
1422
|
+
// Use send-keys -l (literal) instead of paste-buffer
|
|
1423
|
+
// paste-buffer causes issues where Claude shows "[Pasted text]" but content doesn't appear
|
|
1424
|
+
await this.sendKeysLiteral(inj);
|
|
1320
1425
|
await sleep(INJECTION_CONSTANTS.ENTER_DELAY_MS);
|
|
1321
1426
|
await this.sendKeys('Enter');
|
|
1322
1427
|
},
|
|
@@ -1367,7 +1472,15 @@ export class TmuxWrapper extends BaseWrapper {
|
|
|
1367
1472
|
* Send special keys to tmux
|
|
1368
1473
|
*/
|
|
1369
1474
|
async sendKeys(keys) {
|
|
1370
|
-
|
|
1475
|
+
const cmd = `"${this.tmuxPath}" send-keys -t ${this.sessionName} ${keys}`;
|
|
1476
|
+
try {
|
|
1477
|
+
await execAsync(cmd);
|
|
1478
|
+
this.logStderr(`[sendKeys] Sent: ${keys}`);
|
|
1479
|
+
}
|
|
1480
|
+
catch (err) {
|
|
1481
|
+
this.logStderr(`[sendKeys] Failed to send ${keys}: ${err.message}`, true);
|
|
1482
|
+
throw err;
|
|
1483
|
+
}
|
|
1371
1484
|
}
|
|
1372
1485
|
/**
|
|
1373
1486
|
* Send literal text to tmux
|
|
@@ -1382,7 +1495,14 @@ export class TmuxWrapper extends BaseWrapper {
|
|
|
1382
1495
|
.replace(/\$/g, '\\$')
|
|
1383
1496
|
.replace(/`/g, '\\`')
|
|
1384
1497
|
.replace(/!/g, '\\!');
|
|
1385
|
-
|
|
1498
|
+
try {
|
|
1499
|
+
await execAsync(`"${this.tmuxPath}" send-keys -t ${this.sessionName} -l "${escaped}"`);
|
|
1500
|
+
this.logStderr(`[sendKeysLiteral] Sent ${text.length} chars`);
|
|
1501
|
+
}
|
|
1502
|
+
catch (err) {
|
|
1503
|
+
this.logStderr(`[sendKeysLiteral] Failed: ${err.message}`, true);
|
|
1504
|
+
throw err;
|
|
1505
|
+
}
|
|
1386
1506
|
}
|
|
1387
1507
|
/**
|
|
1388
1508
|
* Paste text using tmux buffer with optional bracketed paste to avoid interleaving with ongoing output.
|
|
@@ -1398,15 +1518,9 @@ export class TmuxWrapper extends BaseWrapper {
|
|
|
1398
1518
|
.replace(/`/g, '\\`')
|
|
1399
1519
|
.replace(/!/g, '\\!');
|
|
1400
1520
|
// Set tmux buffer then paste
|
|
1401
|
-
|
|
1402
|
-
await execAsync(
|
|
1403
|
-
|
|
1404
|
-
if (useBracketedPaste) {
|
|
1405
|
-
await execAsync(`"${this.tmuxPath}" paste-buffer -t ${this.sessionName} -p`);
|
|
1406
|
-
}
|
|
1407
|
-
else {
|
|
1408
|
-
await execAsync(`"${this.tmuxPath}" paste-buffer -t ${this.sessionName}`);
|
|
1409
|
-
}
|
|
1521
|
+
const setBufferCmd = `"${this.tmuxPath}" set-buffer -- "${escaped}"`;
|
|
1522
|
+
await execAsync(setBufferCmd);
|
|
1523
|
+
await execAsync(`"${this.tmuxPath}" paste-buffer -t ${this.sessionName}`);
|
|
1410
1524
|
}
|
|
1411
1525
|
/**
|
|
1412
1526
|
* Reset session-specific state for wrapper reuse.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-relay",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Real-time agent-to-agent communication system",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -13,8 +13,9 @@
|
|
|
13
13
|
},
|
|
14
14
|
"scripts": {
|
|
15
15
|
"postinstall": "npm rebuild better-sqlite3 && node scripts/postinstall.js",
|
|
16
|
-
"build": "npm run clean && tsc",
|
|
17
|
-
"
|
|
16
|
+
"build": "npm run clean && tsc && npm run build:dashboard",
|
|
17
|
+
"build:dashboard": "cd src/dashboard && npm run build",
|
|
18
|
+
"postbuild": "chmod +x dist/cli/index.js && mkdir -p dist/dashboard && cp -r src/dashboard/out dist/dashboard/",
|
|
18
19
|
"dev:watch": "tsc -w",
|
|
19
20
|
"predev": "npm run clean && tsc && chmod +x dist/cli/index.js",
|
|
20
21
|
"dev": "concurrently -n daemon,next -c blue,magenta \"npm run dev:daemon\" \"npm run dev:next\"",
|
|
@@ -26,6 +27,7 @@
|
|
|
26
27
|
"dev:rebuild": "npm run build && echo '✓ Rebuilt (linked version updated)'",
|
|
27
28
|
"start": "node dist/cli/index.js",
|
|
28
29
|
"daemon": "node dist/daemon/server.js",
|
|
30
|
+
"dashboard": "node dist/dashboard-server/start.js",
|
|
29
31
|
"pretest": "npm run build",
|
|
30
32
|
"test": "vitest run",
|
|
31
33
|
"test:integration": "vitest run test/cloud/*.integration.test.ts",
|
|
@@ -97,6 +99,9 @@
|
|
|
97
99
|
"ws": "^8.18.3"
|
|
98
100
|
},
|
|
99
101
|
"devDependencies": {
|
|
102
|
+
"@testing-library/dom": "^10.4.1",
|
|
103
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
104
|
+
"@testing-library/react": "^14.3.1",
|
|
100
105
|
"@types/better-sqlite3": "^7.6.13",
|
|
101
106
|
"@types/cors": "^2.8.19",
|
|
102
107
|
"@types/express": "^5.0.6",
|
|
@@ -116,7 +121,7 @@
|
|
|
116
121
|
"eslint": "^8.57.1",
|
|
117
122
|
"jsdom": "^25.0.1",
|
|
118
123
|
"typescript": "^5.9.3",
|
|
119
|
-
"vitest": "^2.1.
|
|
124
|
+
"vitest": "^2.1.9"
|
|
120
125
|
},
|
|
121
126
|
"engines": {
|
|
122
127
|
"node": ">=18.0.0"
|
package/scripts/postinstall.js
CHANGED
|
@@ -3,14 +3,16 @@
|
|
|
3
3
|
* Postinstall Script for agent-relay
|
|
4
4
|
*
|
|
5
5
|
* This script runs after npm install to:
|
|
6
|
-
* 1. Install
|
|
7
|
-
* 2.
|
|
8
|
-
* 3.
|
|
6
|
+
* 1. Install relay-pty binary for current platform
|
|
7
|
+
* 2. Install dashboard dependencies
|
|
8
|
+
* 3. Patch agent-trajectories CLI
|
|
9
|
+
* 4. Check for tmux availability (fallback)
|
|
9
10
|
*/
|
|
10
11
|
|
|
11
12
|
import { execSync } from 'node:child_process';
|
|
12
13
|
import path from 'node:path';
|
|
13
14
|
import fs from 'node:fs';
|
|
15
|
+
import os from 'node:os';
|
|
14
16
|
import { fileURLToPath } from 'node:url';
|
|
15
17
|
|
|
16
18
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -41,6 +43,86 @@ function warn(msg) {
|
|
|
41
43
|
console.log(`${colors.yellow}[warn]${colors.reset} ${msg}`);
|
|
42
44
|
}
|
|
43
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Get the platform-specific binary name for relay-pty
|
|
48
|
+
* Returns null if platform is not supported
|
|
49
|
+
*/
|
|
50
|
+
function getRelayPtyBinaryName() {
|
|
51
|
+
const platform = os.platform();
|
|
52
|
+
const arch = os.arch();
|
|
53
|
+
|
|
54
|
+
// Map Node.js arch to Rust target arch
|
|
55
|
+
const archMap = {
|
|
56
|
+
'arm64': 'arm64',
|
|
57
|
+
'x64': 'x64',
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
// Map Node.js platform to Rust target platform
|
|
61
|
+
const platformMap = {
|
|
62
|
+
'darwin': 'darwin',
|
|
63
|
+
'linux': 'linux',
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const targetPlatform = platformMap[platform];
|
|
67
|
+
const targetArch = archMap[arch];
|
|
68
|
+
|
|
69
|
+
if (!targetPlatform || !targetArch) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return `relay-pty-${targetPlatform}-${targetArch}`;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Install the relay-pty binary for the current platform
|
|
78
|
+
*/
|
|
79
|
+
function installRelayPtyBinary() {
|
|
80
|
+
const pkgRoot = getPackageRoot();
|
|
81
|
+
const binaryName = getRelayPtyBinaryName();
|
|
82
|
+
|
|
83
|
+
if (!binaryName) {
|
|
84
|
+
warn(`Unsupported platform: ${os.platform()}-${os.arch()}`);
|
|
85
|
+
warn('relay-pty binary not available, will fall back to tmux mode');
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const sourcePath = path.join(pkgRoot, 'bin', binaryName);
|
|
90
|
+
const targetPath = path.join(pkgRoot, 'bin', 'relay-pty');
|
|
91
|
+
|
|
92
|
+
// Check if platform-specific binary exists
|
|
93
|
+
if (!fs.existsSync(sourcePath)) {
|
|
94
|
+
warn(`relay-pty binary not found for ${os.platform()}-${os.arch()}`);
|
|
95
|
+
warn('Will fall back to tmux mode');
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Check if already installed (and is a symlink or copy of correct binary)
|
|
100
|
+
if (fs.existsSync(targetPath)) {
|
|
101
|
+
try {
|
|
102
|
+
// Check if it's already the right binary by comparing size
|
|
103
|
+
const sourceStats = fs.statSync(sourcePath);
|
|
104
|
+
const targetStats = fs.statSync(targetPath);
|
|
105
|
+
if (sourceStats.size === targetStats.size) {
|
|
106
|
+
info('relay-pty binary already installed');
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
} catch {
|
|
110
|
+
// Continue to reinstall
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Copy the binary (symlinks don't work well across npm install)
|
|
115
|
+
try {
|
|
116
|
+
fs.copyFileSync(sourcePath, targetPath);
|
|
117
|
+
fs.chmodSync(targetPath, 0o755);
|
|
118
|
+
success(`Installed relay-pty binary for ${os.platform()}-${os.arch()}`);
|
|
119
|
+
return true;
|
|
120
|
+
} catch (err) {
|
|
121
|
+
warn(`Failed to install relay-pty binary: ${err.message}`);
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
44
126
|
/**
|
|
45
127
|
* Check if tmux is available on the system
|
|
46
128
|
*/
|
|
@@ -140,6 +222,9 @@ function patchAgentTrajectories() {
|
|
|
140
222
|
* Main postinstall routine
|
|
141
223
|
*/
|
|
142
224
|
async function main() {
|
|
225
|
+
// Install relay-pty binary for current platform (primary mode)
|
|
226
|
+
const hasRelayPty = installRelayPtyBinary();
|
|
227
|
+
|
|
143
228
|
// Ensure trail CLI captures agent info on start
|
|
144
229
|
patchAgentTrajectories();
|
|
145
230
|
|
|
@@ -151,18 +236,23 @@ async function main() {
|
|
|
151
236
|
return;
|
|
152
237
|
}
|
|
153
238
|
|
|
154
|
-
//
|
|
239
|
+
// If relay-pty is installed, we're good
|
|
240
|
+
if (hasRelayPty) {
|
|
241
|
+
info('Using relay-pty for agent communication (fast mode)');
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Fall back to tmux check
|
|
155
246
|
if (hasSystemTmux()) {
|
|
156
|
-
info('System tmux found');
|
|
247
|
+
info('System tmux found (fallback mode)');
|
|
157
248
|
return;
|
|
158
249
|
}
|
|
159
250
|
|
|
160
|
-
//
|
|
161
|
-
warn('
|
|
162
|
-
info('
|
|
163
|
-
info('
|
|
164
|
-
info('
|
|
165
|
-
info(' Or use PTY mode via the dashboard (no tmux required)');
|
|
251
|
+
// Neither relay-pty nor tmux available
|
|
252
|
+
warn('Neither relay-pty nor tmux available');
|
|
253
|
+
info('Agent spawning will not work without one of:');
|
|
254
|
+
info(' 1. relay-pty binary (included for darwin-arm64, darwin-x64, linux-x64)');
|
|
255
|
+
info(' 2. tmux: brew install tmux (macOS) or apt install tmux (Linux)');
|
|
166
256
|
}
|
|
167
257
|
|
|
168
258
|
main().catch((err) => {
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"id": "traj_3yx9dy148mge",
|
|
3
|
-
"version": 1,
|
|
4
|
-
"task": {
|
|
5
|
-
"title": "Investigate agent-relay codex-auth tunnel failure"
|
|
6
|
-
},
|
|
7
|
-
"status": "active",
|
|
8
|
-
"startedAt": "2026-01-10T04:02:25.981Z",
|
|
9
|
-
"agents": [
|
|
10
|
-
{
|
|
11
|
-
"name": "khaliqgant",
|
|
12
|
-
"role": "lead",
|
|
13
|
-
"joinedAt": "2026-01-10T04:02:25.985Z"
|
|
14
|
-
}
|
|
15
|
-
],
|
|
16
|
-
"chapters": [
|
|
17
|
-
{
|
|
18
|
-
"id": "chap_18hrx02drpjk",
|
|
19
|
-
"title": "Work",
|
|
20
|
-
"agentName": "default",
|
|
21
|
-
"startedAt": "2026-01-10T04:20:27.656Z",
|
|
22
|
-
"events": [
|
|
23
|
-
{
|
|
24
|
-
"ts": 1768018827657,
|
|
25
|
-
"type": "decision",
|
|
26
|
-
"content": "Switched workspace SSH tunnel port to 3022: Switched workspace SSH tunnel port to 3022",
|
|
27
|
-
"raw": {
|
|
28
|
-
"question": "Switched workspace SSH tunnel port to 3022",
|
|
29
|
-
"chosen": "Switched workspace SSH tunnel port to 3022",
|
|
30
|
-
"alternatives": [],
|
|
31
|
-
"reasoning": "sshd failed to bind 2222 in workspace; moving default tunneling port avoids conflicts"
|
|
32
|
-
},
|
|
33
|
-
"significance": "high"
|
|
34
|
-
}
|
|
35
|
-
]
|
|
36
|
-
}
|
|
37
|
-
],
|
|
38
|
-
"commits": [],
|
|
39
|
-
"filesChanged": [],
|
|
40
|
-
"projectId": "/Users/khaliqgant/Projects/agent-workforce/relay",
|
|
41
|
-
"tags": []
|
|
42
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
# Trajectory: Fix agent-relay-322 and agent-relay-324
|
|
2
|
-
|
|
3
|
-
> **Status:** 🔄 Active
|
|
4
|
-
> **Task:** agent-relay-322,agent-relay-324
|
|
5
|
-
> **Started:** January 6, 2026 at 01:36 PM
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Chapters
|
|
10
|
-
|
|
11
|
-
### 1. Initial work
|
|
12
|
-
*Agent: Fullstack*
|
|
13
|
-
|
|
14
|
-
- Added buildClaudeArgs call to spawner.ts spawn() method to apply model and --agent flags from agent profiles: Added buildClaudeArgs call to spawner.ts spawn() method to apply model and --agent flags from agent profiles
|
|
15
|
-
- Created PR #80 for agent-relay-322. Now working on agent-relay-324 - replacing ps command with /proc parsing: Created PR #80 for agent-relay-322. Now working on agent-relay-324 - replacing ps command with /proc parsing
|
|
16
|
-
- Replaced ps command with /proc/[pid]/status parsing. VmRSS line provides resident set size in kB. CPU% left at 0 since it requires time-based sampling.: Replaced ps command with /proc/[pid]/status parsing. VmRSS line provides resident set size in kB. CPU% left at 0 since it requires time-based sampling.
|
|
17
|
-
|