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/client.js
CHANGED
|
@@ -82,6 +82,14 @@ export class RelayClient {
|
|
|
82
82
|
* @param originalTo - Original 'to' field from sender (e.g., '*' for broadcasts)
|
|
83
83
|
*/
|
|
84
84
|
onMessage;
|
|
85
|
+
/**
|
|
86
|
+
* Callback for channel messages.
|
|
87
|
+
* @param from - Sender name
|
|
88
|
+
* @param channel - Channel name
|
|
89
|
+
* @param body - Message content
|
|
90
|
+
* @param envelope - Full envelope for additional data
|
|
91
|
+
*/
|
|
92
|
+
onChannelMessage;
|
|
85
93
|
onStateChange;
|
|
86
94
|
onError;
|
|
87
95
|
constructor(config = {}) {
|
|
@@ -217,6 +225,120 @@ export class RelayClient {
|
|
|
217
225
|
broadcast(body, kind = 'message', data) {
|
|
218
226
|
return this.sendMessage('*', body, kind, data);
|
|
219
227
|
}
|
|
228
|
+
// =============================================================================
|
|
229
|
+
// Channel Operations
|
|
230
|
+
// =============================================================================
|
|
231
|
+
/**
|
|
232
|
+
* Join a channel.
|
|
233
|
+
* @param channel - Channel name (e.g., '#general', 'dm:alice:bob')
|
|
234
|
+
* @param displayName - Optional display name for this member
|
|
235
|
+
*/
|
|
236
|
+
joinChannel(channel, displayName) {
|
|
237
|
+
if (this._state !== 'READY') {
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
const envelope = {
|
|
241
|
+
v: PROTOCOL_VERSION,
|
|
242
|
+
type: 'CHANNEL_JOIN',
|
|
243
|
+
id: generateId(),
|
|
244
|
+
ts: Date.now(),
|
|
245
|
+
payload: {
|
|
246
|
+
channel,
|
|
247
|
+
displayName,
|
|
248
|
+
},
|
|
249
|
+
};
|
|
250
|
+
return this.send(envelope);
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Admin join: Add any member to a channel (does not require member to be connected).
|
|
254
|
+
* Used by dashboard to sync channel memberships for agents.
|
|
255
|
+
* @param channel - Channel name (e.g., '#general')
|
|
256
|
+
* @param member - Name of the member to add
|
|
257
|
+
*/
|
|
258
|
+
adminJoinChannel(channel, member) {
|
|
259
|
+
if (this._state !== 'READY') {
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
const envelope = {
|
|
263
|
+
v: PROTOCOL_VERSION,
|
|
264
|
+
type: 'CHANNEL_JOIN',
|
|
265
|
+
id: generateId(),
|
|
266
|
+
ts: Date.now(),
|
|
267
|
+
payload: {
|
|
268
|
+
channel,
|
|
269
|
+
member, // Admin mode: specify member to add
|
|
270
|
+
},
|
|
271
|
+
};
|
|
272
|
+
return this.send(envelope);
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Leave a channel.
|
|
276
|
+
* @param channel - Channel name to leave
|
|
277
|
+
* @param reason - Optional reason for leaving
|
|
278
|
+
*/
|
|
279
|
+
leaveChannel(channel, reason) {
|
|
280
|
+
if (this._state !== 'READY')
|
|
281
|
+
return false;
|
|
282
|
+
const envelope = {
|
|
283
|
+
v: PROTOCOL_VERSION,
|
|
284
|
+
type: 'CHANNEL_LEAVE',
|
|
285
|
+
id: generateId(),
|
|
286
|
+
ts: Date.now(),
|
|
287
|
+
payload: {
|
|
288
|
+
channel,
|
|
289
|
+
reason,
|
|
290
|
+
},
|
|
291
|
+
};
|
|
292
|
+
return this.send(envelope);
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Admin remove: Remove any member from a channel (does not require member to be connected).
|
|
296
|
+
* Used by dashboard to remove channel members.
|
|
297
|
+
* @param channel - Channel name (e.g., '#general')
|
|
298
|
+
* @param member - Name of the member to remove
|
|
299
|
+
*/
|
|
300
|
+
adminRemoveMember(channel, member) {
|
|
301
|
+
if (this._state !== 'READY') {
|
|
302
|
+
return false;
|
|
303
|
+
}
|
|
304
|
+
const envelope = {
|
|
305
|
+
v: PROTOCOL_VERSION,
|
|
306
|
+
type: 'CHANNEL_LEAVE',
|
|
307
|
+
id: generateId(),
|
|
308
|
+
ts: Date.now(),
|
|
309
|
+
payload: {
|
|
310
|
+
channel,
|
|
311
|
+
member, // Admin mode: specify member to remove
|
|
312
|
+
},
|
|
313
|
+
};
|
|
314
|
+
return this.send(envelope);
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Send a message to a channel.
|
|
318
|
+
* @param channel - Channel name
|
|
319
|
+
* @param body - Message content
|
|
320
|
+
* @param options - Optional thread, mentions, attachments
|
|
321
|
+
*/
|
|
322
|
+
sendChannelMessage(channel, body, options) {
|
|
323
|
+
if (this._state !== 'READY') {
|
|
324
|
+
return false;
|
|
325
|
+
}
|
|
326
|
+
const envelope = {
|
|
327
|
+
v: PROTOCOL_VERSION,
|
|
328
|
+
type: 'CHANNEL_MESSAGE',
|
|
329
|
+
id: generateId(),
|
|
330
|
+
ts: Date.now(),
|
|
331
|
+
payload: {
|
|
332
|
+
channel,
|
|
333
|
+
body,
|
|
334
|
+
thread: options?.thread,
|
|
335
|
+
mentions: options?.mentions,
|
|
336
|
+
attachments: options?.attachments,
|
|
337
|
+
data: options?.data,
|
|
338
|
+
},
|
|
339
|
+
};
|
|
340
|
+
return this.send(envelope);
|
|
341
|
+
}
|
|
220
342
|
/**
|
|
221
343
|
* Subscribe to a topic.
|
|
222
344
|
*/
|
|
@@ -395,6 +517,9 @@ export class RelayClient {
|
|
|
395
517
|
case 'DELIVER':
|
|
396
518
|
this.handleDeliver(envelope);
|
|
397
519
|
break;
|
|
520
|
+
case 'CHANNEL_MESSAGE':
|
|
521
|
+
this.handleChannelMessage(envelope);
|
|
522
|
+
break;
|
|
398
523
|
case 'PING':
|
|
399
524
|
this.handlePing(envelope);
|
|
400
525
|
break;
|
|
@@ -417,6 +542,7 @@ export class RelayClient {
|
|
|
417
542
|
}
|
|
418
543
|
}
|
|
419
544
|
handleDeliver(envelope) {
|
|
545
|
+
console.log(`[relay-client:${this.config.agentName}] Received DELIVER from ${envelope.from}: "${envelope.payload.body?.substring(0, 40)}..."`);
|
|
420
546
|
// Send ACK
|
|
421
547
|
this.send({
|
|
422
548
|
v: PROTOCOL_VERSION,
|
|
@@ -430,6 +556,7 @@ export class RelayClient {
|
|
|
430
556
|
});
|
|
431
557
|
const duplicate = this.markDelivered(envelope.id);
|
|
432
558
|
if (duplicate) {
|
|
559
|
+
console.log(`[relay-client:${this.config.agentName}] Duplicate delivery, skipping`);
|
|
433
560
|
return;
|
|
434
561
|
}
|
|
435
562
|
// Notify handler
|
|
@@ -437,6 +564,46 @@ export class RelayClient {
|
|
|
437
564
|
if (this.onMessage && envelope.from) {
|
|
438
565
|
this.onMessage(envelope.from, envelope.payload, envelope.id, envelope.payload_meta, envelope.delivery.originalTo);
|
|
439
566
|
}
|
|
567
|
+
else {
|
|
568
|
+
console.log(`[relay-client:${this.config.agentName}] No onMessage handler or no from field`);
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
handleChannelMessage(envelope) {
|
|
572
|
+
if (!this.config.quiet) {
|
|
573
|
+
console.log(`[client] handleChannelMessage: from=${envelope.from}, channel=${envelope.payload.channel}`);
|
|
574
|
+
}
|
|
575
|
+
const duplicate = this.markDelivered(envelope.id);
|
|
576
|
+
if (duplicate) {
|
|
577
|
+
if (!this.config.quiet) {
|
|
578
|
+
console.log(`[client] handleChannelMessage: duplicate message ${envelope.id}, skipping`);
|
|
579
|
+
}
|
|
580
|
+
return;
|
|
581
|
+
}
|
|
582
|
+
// Notify channel message handler
|
|
583
|
+
if (this.onChannelMessage && envelope.from) {
|
|
584
|
+
if (!this.config.quiet) {
|
|
585
|
+
console.log(`[client] Calling onChannelMessage callback`);
|
|
586
|
+
}
|
|
587
|
+
this.onChannelMessage(envelope.from, envelope.payload.channel, envelope.payload.body, envelope);
|
|
588
|
+
}
|
|
589
|
+
else if (!this.config.quiet) {
|
|
590
|
+
console.log(`[client] No onChannelMessage handler set (handler=${!!this.onChannelMessage}, from=${envelope.from})`);
|
|
591
|
+
}
|
|
592
|
+
// Also call onMessage for backwards compatibility
|
|
593
|
+
// Convert to SendPayload format (channel is passed as 5th argument, not in payload)
|
|
594
|
+
if (this.onMessage && envelope.from) {
|
|
595
|
+
const sendPayload = {
|
|
596
|
+
kind: 'message',
|
|
597
|
+
body: envelope.payload.body,
|
|
598
|
+
data: {
|
|
599
|
+
_isChannelMessage: true,
|
|
600
|
+
_channel: envelope.payload.channel,
|
|
601
|
+
_mentions: envelope.payload.mentions,
|
|
602
|
+
},
|
|
603
|
+
thread: envelope.payload.thread,
|
|
604
|
+
};
|
|
605
|
+
this.onMessage(envelope.from, sendPayload, envelope.id, undefined, envelope.payload.channel);
|
|
606
|
+
}
|
|
440
607
|
}
|
|
441
608
|
handlePing(envelope) {
|
|
442
609
|
this.send({
|
package/dist/wrapper/parser.d.ts
CHANGED
|
@@ -137,10 +137,6 @@ export declare class OutputParser {
|
|
|
137
137
|
*/
|
|
138
138
|
reset(): void;
|
|
139
139
|
}
|
|
140
|
-
/**
|
|
141
|
-
* Format a relay command for injection into agent input.
|
|
142
|
-
*/
|
|
143
|
-
export declare function formatIncomingMessage(from: string, body: string, kind?: PayloadKind): string;
|
|
144
140
|
/**
|
|
145
141
|
* Parsed message metadata block from agent output.
|
|
146
142
|
*/
|
package/dist/wrapper/parser.js
CHANGED
|
@@ -49,6 +49,9 @@ const MAX_INLINE_CONTINUATION_LINES = 30;
|
|
|
49
49
|
// They are handled separately by the wrappers (pty-wrapper.ts, tmux-wrapper.ts)
|
|
50
50
|
const SPAWN_COMMAND_PATTERN = /->relay:spawn\s+\S+/i;
|
|
51
51
|
const RELEASE_COMMAND_PATTERN = /->relay:release\s+\S+/i;
|
|
52
|
+
// JSON relay format: ->relay.json:{...}
|
|
53
|
+
// Simple single-line format that's resilient and won't interfere with normal conversation
|
|
54
|
+
const JSON_RELAY_PATTERN = /->relay\.json:(\{[^\n]+\})/;
|
|
52
55
|
/**
|
|
53
56
|
* Check if a line is a spawn or release command that should be handled
|
|
54
57
|
* by the wrapper's spawn subsystem, not parsed as a relay message.
|
|
@@ -653,9 +656,41 @@ export class OutputParser {
|
|
|
653
656
|
const thinkingBase = this.options.thinkingPrefix.replace(/:$/, '');
|
|
654
657
|
const hasRelayPattern = line.includes(relayBase) || line.includes(thinkingBase);
|
|
655
658
|
const hasBlockPattern = line.includes('[[') || line.includes('```');
|
|
656
|
-
|
|
659
|
+
const hasJsonRelay = line.includes('->relay.json:');
|
|
660
|
+
if (!hasRelayPattern && !hasBlockPattern && !hasJsonRelay) {
|
|
657
661
|
return { command: null, output: line };
|
|
658
662
|
}
|
|
663
|
+
// Check for JSON relay format first (preferred): ->relay.json:{...}
|
|
664
|
+
if (hasJsonRelay) {
|
|
665
|
+
const stripped = stripAnsi(line);
|
|
666
|
+
const jsonMatch = stripped.match(JSON_RELAY_PATTERN);
|
|
667
|
+
if (jsonMatch) {
|
|
668
|
+
try {
|
|
669
|
+
const parsed = JSON.parse(jsonMatch[1]);
|
|
670
|
+
const kind = parsed.kind || 'message';
|
|
671
|
+
// Handle different command kinds
|
|
672
|
+
if (kind === 'message' && parsed.to) {
|
|
673
|
+
return {
|
|
674
|
+
command: {
|
|
675
|
+
to: parsed.to,
|
|
676
|
+
kind: 'message',
|
|
677
|
+
body: parsed.body || '',
|
|
678
|
+
thread: parsed.thread,
|
|
679
|
+
raw: jsonMatch[0],
|
|
680
|
+
},
|
|
681
|
+
output: null,
|
|
682
|
+
};
|
|
683
|
+
}
|
|
684
|
+
// spawn/release are handled by the wrapper, not here
|
|
685
|
+
// But we still strip the line from output
|
|
686
|
+
return { command: null, output: null };
|
|
687
|
+
}
|
|
688
|
+
catch {
|
|
689
|
+
// Invalid JSON, pass through
|
|
690
|
+
console.error('[parser] Invalid JSON in ->relay.json:', jsonMatch[1]);
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
}
|
|
659
694
|
// Strip ANSI codes for pattern matching (only when potentially needed)
|
|
660
695
|
const stripped = stripAnsi(line);
|
|
661
696
|
// Handle code fences
|
|
@@ -811,12 +846,12 @@ export class OutputParser {
|
|
|
811
846
|
shouldFilterFencedInline(target, body) {
|
|
812
847
|
// Check for placeholder target names
|
|
813
848
|
if (isPlaceholderTarget(target)) {
|
|
814
|
-
|
|
849
|
+
// Silently filter placeholder targets (common in documentation)
|
|
815
850
|
return true;
|
|
816
851
|
}
|
|
817
852
|
// Check for instructional body content
|
|
818
853
|
if (isInstructionalText(body)) {
|
|
819
|
-
|
|
854
|
+
// Silently filter instructional text (common in system prompts)
|
|
820
855
|
return true;
|
|
821
856
|
}
|
|
822
857
|
return false;
|
|
@@ -1049,13 +1084,6 @@ export class OutputParser {
|
|
|
1049
1084
|
this.fencedInlineKind = 'message';
|
|
1050
1085
|
}
|
|
1051
1086
|
}
|
|
1052
|
-
/**
|
|
1053
|
-
* Format a relay command for injection into agent input.
|
|
1054
|
-
*/
|
|
1055
|
-
export function formatIncomingMessage(from, body, kind = 'message') {
|
|
1056
|
-
const prefix = kind === 'thinking' ? '[THINKING]' : '[MSG]';
|
|
1057
|
-
return `\n${prefix} from ${from}: ${body}\n`;
|
|
1058
|
-
}
|
|
1059
1087
|
/**
|
|
1060
1088
|
* Parse [[RELAY_METADATA]]...[[/RELAY_METADATA]] blocks from agent output.
|
|
1061
1089
|
* Agents can output metadata to enhance messages.
|
|
@@ -230,9 +230,15 @@ export declare class PtyWrapper extends BaseWrapper {
|
|
|
230
230
|
protected parseSpawnReleaseCommands(content: string): void;
|
|
231
231
|
/**
|
|
232
232
|
* Execute spawn via API or callback.
|
|
233
|
-
*
|
|
233
|
+
* After spawning, waits for the agent to come online and sends the task via relay.
|
|
234
234
|
*/
|
|
235
235
|
protected executeSpawn(name: string, cli: string, task: string): Promise<void>;
|
|
236
|
+
/**
|
|
237
|
+
* Wait for a spawned agent to come online, then send the task via relay.
|
|
238
|
+
* Uses the wrapper's own relay client so the message comes "from" this agent,
|
|
239
|
+
* not from the dashboard's relay client.
|
|
240
|
+
*/
|
|
241
|
+
private waitAndSendTask;
|
|
236
242
|
/**
|
|
237
243
|
* Execute release via API or callback.
|
|
238
244
|
* Overrides BaseWrapper to add PTY-specific logging and API path.
|
|
@@ -243,6 +249,11 @@ export declare class PtyWrapper extends BaseWrapper {
|
|
|
243
249
|
* Extends BaseWrapper to add PTY-specific behavior.
|
|
244
250
|
*/
|
|
245
251
|
protected handleIncomingMessage(from: string, payload: SendPayload, messageId: string, meta?: SendMeta, originalTo?: string): void;
|
|
252
|
+
/**
|
|
253
|
+
* Handle incoming channel message from relay.
|
|
254
|
+
* Extends BaseWrapper to add PTY-specific queue processing.
|
|
255
|
+
*/
|
|
256
|
+
protected handleIncomingChannelMessage(from: string, channel: string, body: string, envelope: import('../protocol/types.js').Envelope<import('../protocol/channels.js').ChannelMessagePayload>): void;
|
|
246
257
|
/**
|
|
247
258
|
* Wait for output to stabilize before injection.
|
|
248
259
|
* Uses UniversalIdleDetector (from BaseWrapper) for robust cross-CLI idle detection.
|
|
@@ -134,8 +134,11 @@ export class PtyWrapper extends BaseWrapper {
|
|
|
134
134
|
}
|
|
135
135
|
}
|
|
136
136
|
// Connect to relay daemon
|
|
137
|
+
const socketPath = this.config.socketPath ?? 'DEFAULT';
|
|
138
|
+
console.log(`[pty:${this.config.name}] Connecting to relay daemon at: ${socketPath}`);
|
|
137
139
|
try {
|
|
138
140
|
await this.client.connect();
|
|
141
|
+
console.log(`[pty:${this.config.name}] Relay connected (state: ${this.client.state})`);
|
|
139
142
|
// If this is a shadow agent, bind to the primary after connecting
|
|
140
143
|
if (this.config.shadowOf) {
|
|
141
144
|
const speakOn = this.config.shadowSpeakOn ?? ['EXPLICIT_ASK'];
|
|
@@ -150,6 +153,7 @@ export class PtyWrapper extends BaseWrapper {
|
|
|
150
153
|
}
|
|
151
154
|
catch (err) {
|
|
152
155
|
console.error(`[pty:${this.config.name}] Relay connect failed: ${err.message}`);
|
|
156
|
+
console.error(`[pty:${this.config.name}] Relay client state: ${this.client.state}`);
|
|
153
157
|
}
|
|
154
158
|
// Build command args
|
|
155
159
|
const args = this.config.args ?? [];
|
|
@@ -220,6 +224,7 @@ export class PtyWrapper extends BaseWrapper {
|
|
|
220
224
|
this.injectInstructions();
|
|
221
225
|
}
|
|
222
226
|
this.readyForMessages = true;
|
|
227
|
+
console.log(`[pty:${this.config.name}] Agent ready for messages (queueLen=${this.messageQueue.length}, interactive=${this.config.interactive})`);
|
|
223
228
|
// Process any messages that arrived while waiting (skip in interactive mode)
|
|
224
229
|
if (!this.config.interactive) {
|
|
225
230
|
this.processMessageQueue();
|
|
@@ -228,6 +233,7 @@ export class PtyWrapper extends BaseWrapper {
|
|
|
228
233
|
console.error(`[pty:${this.config.name}] Failed to wait for agent ready:`, err);
|
|
229
234
|
// Fall back to marking ready anyway to avoid blocking forever
|
|
230
235
|
this.readyForMessages = true;
|
|
236
|
+
console.log(`[pty:${this.config.name}] Agent ready for messages (fallback, queueLen=${this.messageQueue.length})`);
|
|
231
237
|
});
|
|
232
238
|
}
|
|
233
239
|
/**
|
|
@@ -608,6 +614,14 @@ export class PtyWrapper extends BaseWrapper {
|
|
|
608
614
|
// 500 chars is enough to capture most relay message headers
|
|
609
615
|
const lookbackStart = Math.max(0, this.lastParsedLength - 500);
|
|
610
616
|
const contentToParse = cleanContent.substring(lookbackStart);
|
|
617
|
+
// Debug: Check if content contains relay pattern
|
|
618
|
+
if (contentToParse.includes('->relay:')) {
|
|
619
|
+
const relayLines = contentToParse.split('\n').filter(l => l.includes('->relay:'));
|
|
620
|
+
console.log(`[pty:${this.config.name}] [RELAY-DEBUG] Found ${relayLines.length} lines with ->relay: pattern`);
|
|
621
|
+
relayLines.slice(0, 3).forEach((line, i) => {
|
|
622
|
+
console.log(`[pty:${this.config.name}] [RELAY-DEBUG] Line ${i}: "${line.substring(0, 80)}..."`);
|
|
623
|
+
});
|
|
624
|
+
}
|
|
611
625
|
// First, try to find fenced multi-line messages: ->relay:Target <<<\n...\n>>>
|
|
612
626
|
this.parseFencedMessages(contentToParse);
|
|
613
627
|
// Then parse single-line messages
|
|
@@ -625,9 +639,14 @@ export class PtyWrapper extends BaseWrapper {
|
|
|
625
639
|
// Thread is optional, can be [thread:id] or [thread:project:id] for cross-project
|
|
626
640
|
const escapedPrefix = this.relayPrefix.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
627
641
|
const fenceStartPattern = new RegExp(`${escapedPrefix}(\\S+)(?:\\s+\\[thread:(?:([\\w-]+):)?([\\w-]+)\\])?\\s*<<<`, 'g');
|
|
642
|
+
// Debug: Log if content contains relay prefix with fenced syntax
|
|
643
|
+
if (content.includes(this.relayPrefix) && content.includes('<<<')) {
|
|
644
|
+
console.error(`[pty:${this.config.name}] parseFencedMessages: Found relay+<<< in content`);
|
|
645
|
+
}
|
|
628
646
|
let match;
|
|
629
647
|
while ((match = fenceStartPattern.exec(content)) !== null) {
|
|
630
648
|
const target = match[1];
|
|
649
|
+
console.error(`[pty:${this.config.name}] parseFencedMessages: MATCHED target=${target}`);
|
|
631
650
|
const threadProject = match[2]; // Optional: project part of thread
|
|
632
651
|
const threadId = match[3]; // Thread ID
|
|
633
652
|
const startIdx = match.index + match[0].length;
|
|
@@ -985,22 +1004,24 @@ export class PtyWrapper extends BaseWrapper {
|
|
|
985
1004
|
}
|
|
986
1005
|
/**
|
|
987
1006
|
* Execute spawn via API or callback.
|
|
988
|
-
*
|
|
1007
|
+
* After spawning, waits for the agent to come online and sends the task via relay.
|
|
989
1008
|
*/
|
|
990
1009
|
async executeSpawn(name, cli, task) {
|
|
991
1010
|
console.log(`[pty:${this.config.name}] [SPAWN-DEBUG] executeSpawn called: name=${name}, cli=${cli}, task="${task.substring(0, 50)}..."`);
|
|
992
1011
|
console.log(`[pty:${this.config.name}] [SPAWN-DEBUG] dashboardPort=${this.config.dashboardPort}, hasOnSpawn=${!!this.config.onSpawn}`);
|
|
1012
|
+
let spawned = false;
|
|
993
1013
|
if (this.config.dashboardPort) {
|
|
994
1014
|
// Use dashboard API for spawning (works from spawned agents)
|
|
995
1015
|
try {
|
|
996
1016
|
const response = await fetch(`http://localhost:${this.config.dashboardPort}/api/spawn`, {
|
|
997
1017
|
method: 'POST',
|
|
998
1018
|
headers: { 'Content-Type': 'application/json' },
|
|
999
|
-
body: JSON.stringify({ name, cli, task
|
|
1019
|
+
body: JSON.stringify({ name, cli }), // No task - we send it after agent is online
|
|
1000
1020
|
});
|
|
1001
1021
|
const result = await response.json();
|
|
1002
1022
|
if (result.success) {
|
|
1003
1023
|
console.log(`[pty:${this.config.name}] Spawned ${name} via API`);
|
|
1024
|
+
spawned = true;
|
|
1004
1025
|
}
|
|
1005
1026
|
else {
|
|
1006
1027
|
console.error(`[pty:${this.config.name}] Spawn failed: ${result.error}`);
|
|
@@ -1014,11 +1035,57 @@ export class PtyWrapper extends BaseWrapper {
|
|
|
1014
1035
|
// Fall back to callback
|
|
1015
1036
|
try {
|
|
1016
1037
|
await this.config.onSpawn(name, cli, task);
|
|
1038
|
+
spawned = true;
|
|
1017
1039
|
}
|
|
1018
1040
|
catch (err) {
|
|
1019
1041
|
console.error(`[pty:${this.config.name}] Spawn failed: ${err.message}`);
|
|
1020
1042
|
}
|
|
1021
1043
|
}
|
|
1044
|
+
// If spawn succeeded and we have a task, wait for agent to come online and send it
|
|
1045
|
+
if (spawned && task && task.trim() && this.config.dashboardPort) {
|
|
1046
|
+
await this.waitAndSendTask(name, task);
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
/**
|
|
1050
|
+
* Wait for a spawned agent to come online, then send the task via relay.
|
|
1051
|
+
* Uses the wrapper's own relay client so the message comes "from" this agent,
|
|
1052
|
+
* not from the dashboard's relay client.
|
|
1053
|
+
*/
|
|
1054
|
+
async waitAndSendTask(agentName, task) {
|
|
1055
|
+
const maxWaitMs = 30000;
|
|
1056
|
+
const pollIntervalMs = 500;
|
|
1057
|
+
const startTime = Date.now();
|
|
1058
|
+
console.log(`[pty:${this.config.name}] Waiting for ${agentName} to come online...`);
|
|
1059
|
+
// Poll for agent to be online using dedicated status endpoint
|
|
1060
|
+
while (Date.now() - startTime < maxWaitMs) {
|
|
1061
|
+
try {
|
|
1062
|
+
const response = await fetch(`http://localhost:${this.config.dashboardPort}/api/agents/${encodeURIComponent(agentName)}/online`);
|
|
1063
|
+
const data = await response.json();
|
|
1064
|
+
if (data.online) {
|
|
1065
|
+
console.log(`[pty:${this.config.name}] ${agentName} is online, sending task...`);
|
|
1066
|
+
// Send task directly via our relay client (not dashboard API)
|
|
1067
|
+
// This ensures the message comes "from" this agent, not from _DashboardUI
|
|
1068
|
+
if (this.client.state === 'READY') {
|
|
1069
|
+
const sent = this.client.sendMessage(agentName, task, 'message');
|
|
1070
|
+
if (sent) {
|
|
1071
|
+
console.log(`[pty:${this.config.name}] Task sent to ${agentName}`);
|
|
1072
|
+
}
|
|
1073
|
+
else {
|
|
1074
|
+
console.error(`[pty:${this.config.name}] Failed to send task to ${agentName}: sendMessage returned false`);
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
else {
|
|
1078
|
+
console.error(`[pty:${this.config.name}] Failed to send task to ${agentName}: relay client not ready (state: ${this.client.state})`);
|
|
1079
|
+
}
|
|
1080
|
+
return;
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
catch (err) {
|
|
1084
|
+
// Ignore poll errors, keep trying
|
|
1085
|
+
}
|
|
1086
|
+
await sleep(pollIntervalMs);
|
|
1087
|
+
}
|
|
1088
|
+
console.error(`[pty:${this.config.name}] Timeout waiting for ${agentName} to come online`);
|
|
1022
1089
|
}
|
|
1023
1090
|
/**
|
|
1024
1091
|
* Execute release via API or callback.
|
|
@@ -1058,6 +1125,8 @@ export class PtyWrapper extends BaseWrapper {
|
|
|
1058
1125
|
* Extends BaseWrapper to add PTY-specific behavior.
|
|
1059
1126
|
*/
|
|
1060
1127
|
handleIncomingMessage(from, payload, messageId, meta, originalTo) {
|
|
1128
|
+
const bodyPreview = payload.body.substring(0, 50).replace(/\n/g, '\\n');
|
|
1129
|
+
console.log(`[pty:${this.config.name}] Message received from ${from}: "${bodyPreview}..." (readyForMessages=${this.readyForMessages}, queueLen=${this.messageQueue.length})`);
|
|
1061
1130
|
// Call base class to handle deduplication and queuing
|
|
1062
1131
|
super.handleIncomingMessage(from, payload, messageId, meta, originalTo);
|
|
1063
1132
|
// PTY-specific: Process the message queue immediately
|
|
@@ -1067,6 +1136,20 @@ export class PtyWrapper extends BaseWrapper {
|
|
|
1067
1136
|
console.error(`[pty:${this.config.name}] Message received hook error:`, err);
|
|
1068
1137
|
});
|
|
1069
1138
|
}
|
|
1139
|
+
/**
|
|
1140
|
+
* Handle incoming channel message from relay.
|
|
1141
|
+
* Extends BaseWrapper to add PTY-specific queue processing.
|
|
1142
|
+
*/
|
|
1143
|
+
handleIncomingChannelMessage(from, channel, body, envelope) {
|
|
1144
|
+
// Call base class to handle deduplication and queuing
|
|
1145
|
+
super.handleIncomingChannelMessage(from, channel, body, envelope);
|
|
1146
|
+
// PTY-specific: Process the message queue immediately
|
|
1147
|
+
this.processMessageQueue();
|
|
1148
|
+
// PTY-specific: Dispatch message received hook with channel info
|
|
1149
|
+
this.hookRegistry.dispatchMessageReceived(from, body, envelope.id).catch(err => {
|
|
1150
|
+
console.error(`[pty:${this.config.name}] Channel message received hook error:`, err);
|
|
1151
|
+
});
|
|
1152
|
+
}
|
|
1070
1153
|
/**
|
|
1071
1154
|
* Wait for output to stabilize before injection.
|
|
1072
1155
|
* Uses UniversalIdleDetector (from BaseWrapper) for robust cross-CLI idle detection.
|
|
@@ -1114,6 +1197,8 @@ export class PtyWrapper extends BaseWrapper {
|
|
|
1114
1197
|
this.isInjecting = false;
|
|
1115
1198
|
return;
|
|
1116
1199
|
}
|
|
1200
|
+
const bodyPreview = msg.body.substring(0, 50).replace(/\n/g, '\\n');
|
|
1201
|
+
console.log(`[pty:${this.config.name}] Processing message from ${msg.from}: "${bodyPreview}..." (remaining=${this.messageQueue.length})`);
|
|
1117
1202
|
try {
|
|
1118
1203
|
// Wait for output to stabilize before injecting
|
|
1119
1204
|
await this.waitForOutputStable();
|
|
@@ -1152,9 +1237,21 @@ export class PtyWrapper extends BaseWrapper {
|
|
|
1152
1237
|
if (!this.ptyProcess || !this.running) {
|
|
1153
1238
|
throw new Error('PTY process not running');
|
|
1154
1239
|
}
|
|
1155
|
-
//
|
|
1156
|
-
|
|
1157
|
-
|
|
1240
|
+
// Use bracketed paste mode for CLIs that support it (claude, codex, gemini)
|
|
1241
|
+
// This prevents interleaving with CLI output and ensures clean input
|
|
1242
|
+
const useBracketedPaste = this.cliType === 'claude' || this.cliType === 'codex' || this.cliType === 'gemini';
|
|
1243
|
+
if (useBracketedPaste) {
|
|
1244
|
+
// Bracketed paste: \x1b[200~ starts paste, \x1b[201~ ends paste
|
|
1245
|
+
this.ptyProcess.write('\x1b[200~' + inj + '\x1b[201~');
|
|
1246
|
+
}
|
|
1247
|
+
else {
|
|
1248
|
+
this.ptyProcess.write(inj);
|
|
1249
|
+
}
|
|
1250
|
+
// Wait longer for CLI to process the pasted content before sending Enter.
|
|
1251
|
+
// The standard 50ms delay is too short for CLIs like Claude that need time
|
|
1252
|
+
// to process bracketed paste content before accepting Enter.
|
|
1253
|
+
await sleep(200);
|
|
1254
|
+
// Send Enter key - use \r for PTY (carriage return)
|
|
1158
1255
|
this.ptyProcess.write('\r');
|
|
1159
1256
|
},
|
|
1160
1257
|
log: (message) => console.log(`[pty:${this.config.name}] ${message}`),
|
|
@@ -1199,6 +1296,8 @@ export class PtyWrapper extends BaseWrapper {
|
|
|
1199
1296
|
injectInstructions() {
|
|
1200
1297
|
if (!this.running)
|
|
1201
1298
|
return;
|
|
1299
|
+
if (this.config.skipInstructions)
|
|
1300
|
+
return;
|
|
1202
1301
|
// Guard: Only inject once per session
|
|
1203
1302
|
if (this.instructionsInjected) {
|
|
1204
1303
|
console.log(`[pty:${this.config.name}] Init instructions already injected, skipping`);
|