neural-loom 0.2.16 → 0.2.18
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/.next/BUILD_ID +1 -1
- package/.next/build-manifest.json +3 -3
- package/.next/cache/.previewinfo +1 -1
- package/.next/cache/.rscinfo +1 -1
- package/.next/cache/.tsbuildinfo +1 -1
- package/.next/diagnostics/route-bundle-stats.json +2 -2
- package/.next/fallback-build-manifest.json +3 -3
- package/.next/prerender-manifest.json +3 -3
- package/.next/server/app/_global-error.html +1 -1
- package/.next/server/app/_global-error.rsc +1 -1
- package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/_not-found.html +1 -1
- package/.next/server/app/_not-found.rsc +1 -1
- package/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/index.html +1 -1
- package/.next/server/app/index.rsc +2 -2
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/index.segments/_full.segment.rsc +2 -2
- package/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/page/react-loadable-manifest.json +3 -3
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__0d0pykb._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__0d0pykb._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__0iqaxhx._.js +5 -5
- package/.next/server/chunks/[root-of-the-server]__0iqaxhx._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__0qyrt6_._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__0qyrt6_._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__0qz~w0~._.js +6 -6
- package/.next/server/chunks/[root-of-the-server]__0qz~w0~._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__0ty8hwz._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__0ty8hwz._.js.map +1 -1
- package/.next/server/chunks/ssr/_0t7oqy6._.js +1 -1
- package/.next/server/chunks/ssr/_0t7oqy6._.js.map +1 -1
- package/.next/server/middleware-build-manifest.js +3 -3
- package/.next/server/pages/404.html +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.js +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/chunks/0ek0280331wie.js +1 -0
- package/.next/static/chunks/0whfmx9l_25d4.js +1 -0
- package/.next/static/chunks/{06z14vx5drwj0.js → 0x__nd4avi0fg.js} +2 -2
- package/.next/trace +1 -1
- package/.next/trace-build +1 -1
- package/package.json +1 -1
- package/src/app/api/sessions/launch/route.ts +4 -1
- package/src/app/api/sessions/route.ts +7 -1
- package/src/app/components/IdeLayout.tsx +4 -3
- package/src/app/components/TerminalConsole.tsx +5 -4
- package/src/app/page.tsx +101 -14
- package/src/lib/agents/WebSocketServer.ts +115 -90
- package/src/lib/recents.ts +19 -2
- package/.next/static/chunks/0cv9~vnm0atn4.js +0 -1
- package/.next/static/chunks/0t~533m2dl-bb.js +0 -1
- /package/.next/static/{Sqg0WwYlho2e4abhJPPMw → OOK46QJncZAPJTv2oCT-X}/_buildManifest.js +0 -0
- /package/.next/static/{Sqg0WwYlho2e4abhJPPMw → OOK46QJncZAPJTv2oCT-X}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{Sqg0WwYlho2e4abhJPPMw → OOK46QJncZAPJTv2oCT-X}/_ssgManifest.js +0 -0
package/.next/trace
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
[{"name":"generate-buildid","duration":282,"timestamp":118007911269,"id":4,"parentId":1,"tags":{},"startTime":1781338743682,"traceId":"9cb8826ecd92b75b"},{"name":"load-custom-routes","duration":343,"timestamp":118007911664,"id":5,"parentId":1,"tags":{},"startTime":1781338743682,"traceId":"9cb8826ecd92b75b"},{"name":"create-dist-dir","duration":1906,"timestamp":118007912037,"id":6,"parentId":1,"tags":{},"startTime":1781338743683,"traceId":"9cb8826ecd92b75b"},{"name":"clean","duration":508,"timestamp":118007914735,"id":7,"parentId":1,"tags":{},"startTime":1781338743685,"traceId":"9cb8826ecd92b75b"},{"name":"discover-routes","duration":7369,"timestamp":118007936353,"id":8,"parentId":1,"tags":{},"startTime":1781338743707,"traceId":"9cb8826ecd92b75b"},{"name":"create-root-mapping","duration":59,"timestamp":118007943770,"id":9,"parentId":1,"tags":{},"startTime":1781338743714,"traceId":"9cb8826ecd92b75b"},{"name":"generate-route-types","duration":17441,"timestamp":118007945233,"id":10,"parentId":1,"tags":{},"startTime":1781338743716,"traceId":"9cb8826ecd92b75b"},{"name":"public-dir-conflict-check","duration":84,"timestamp":118007962798,"id":11,"parentId":1,"tags":{},"startTime":1781338743733,"traceId":"9cb8826ecd92b75b"},{"name":"generate-routes-manifest","duration":2186,"timestamp":118007962977,"id":12,"parentId":1,"tags":{},"startTime":1781338743734,"traceId":"9cb8826ecd92b75b"},{"name":"run-turbopack","duration":2289163,"timestamp":118007971439,"id":14,"parentId":1,"tags":{},"startTime":1781338743742,"traceId":"9cb8826ecd92b75b"},{"name":"turbopack-build-events","duration":64,"timestamp":118008264417,"id":15,"parentId":1,"tags":{},"startTime":1781338744035,"traceId":"9cb8826ecd92b75b"},{"name":"run-typescript","duration":3434329,"timestamp":118010272734,"id":16,"parentId":1,"tags":{},"startTime":1781338746043,"traceId":"9cb8826ecd92b75b"},{"name":"generate-required-server-files","duration":1351,"timestamp":118013707902,"id":18,"parentId":1,"tags":{},"startTime":1781338749478,"traceId":"9cb8826ecd92b75b"},{"name":"check-static-error-page","duration":7348,"timestamp":118013829609,"id":20,"parentId":19,"tags":{},"startTime":1781338749600,"traceId":"9cb8826ecd92b75b"},{"name":"is-page-static","duration":515970,"timestamp":118013841895,"id":41,"parentId":22,"tags":{},"startTime":1781338749612,"traceId":"9cb8826ecd92b75b"},{"name":"check-page","duration":525707,"timestamp":118013832279,"id":22,"parentId":19,"tags":{"page":"/_global-error"},"startTime":1781338749603,"traceId":"9cb8826ecd92b75b"},{"name":"is-page-static","duration":639263,"timestamp":118013842115,"id":43,"parentId":24,"tags":{},"startTime":1781338749613,"traceId":"9cb8826ecd92b75b"},{"name":"check-page","duration":648585,"timestamp":118013832862,"id":24,"parentId":19,"tags":{"page":"/api/context/claude"},"startTime":1781338749603,"traceId":"9cb8826ecd92b75b"},{"name":"is-page-static","duration":648704,"timestamp":118013842021,"id":42,"parentId":23,"tags":{},"startTime":1781338749613,"traceId":"9cb8826ecd92b75b"},{"name":"check-page","duration":658186,"timestamp":118013832592,"id":23,"parentId":19,"tags":{"page":"/api/context/aider"},"startTime":1781338749603,"traceId":"9cb8826ecd92b75b"},{"name":"is-page-static","duration":649657,"timestamp":118013842303,"id":45,"parentId":26,"tags":{},"startTime":1781338749613,"traceId":"9cb8826ecd92b75b"},{"name":"check-page","duration":658525,"timestamp":118013833481,"id":26,"parentId":19,"tags":{"page":"/api/context/ssh"},"startTime":1781338749604,"traceId":"9cb8826ecd92b75b"},{"name":"is-page-static","duration":654791,"timestamp":118013842209,"id":44,"parentId":25,"tags":{},"startTime":1781338749613,"traceId":"9cb8826ecd92b75b"},{"name":"check-page","duration":663932,"timestamp":118013833114,"id":25,"parentId":19,"tags":{"page":"/api/context"},"startTime":1781338749604,"traceId":"9cb8826ecd92b75b"},{"name":"is-page-static","duration":655914,"timestamp":118013842808,"id":47,"parentId":28,"tags":{},"startTime":1781338749613,"traceId":"9cb8826ecd92b75b"},{"name":"check-page","duration":664750,"timestamp":118013834019,"id":28,"parentId":19,"tags":{"page":"/api/git"},"startTime":1781338749605,"traceId":"9cb8826ecd92b75b"},{"name":"is-page-static","duration":658504,"timestamp":118013842927,"id":48,"parentId":29,"tags":{},"startTime":1781338749613,"traceId":"9cb8826ecd92b75b"},{"name":"check-page","duration":667255,"timestamp":118013834231,"id":29,"parentId":19,"tags":{"page":"/api/recents"},"startTime":1781338749605,"traceId":"9cb8826ecd92b75b"},{"name":"is-page-static","duration":662542,"timestamp":118013843513,"id":52,"parentId":33,"tags":{},"startTime":1781338749614,"traceId":"9cb8826ecd92b75b"},{"name":"check-page","duration":671071,"timestamp":118013835036,"id":33,"parentId":19,"tags":{"page":"/api/sessions"},"startTime":1781338749606,"traceId":"9cb8826ecd92b75b"},{"name":"is-page-static","duration":663896,"timestamp":118013847267,"id":58,"parentId":39,"tags":{},"startTime":1781338749618,"traceId":"9cb8826ecd92b75b"},{"name":"check-page","duration":674545,"timestamp":118013836663,"id":39,"parentId":19,"tags":{"page":"/"},"startTime":1781338749607,"traceId":"9cb8826ecd92b75b"},{"name":"is-page-static","duration":671435,"timestamp":118013843760,"id":56,"parentId":37,"tags":{},"startTime":1781338749614,"traceId":"9cb8826ecd92b75b"},{"name":"check-page","duration":679130,"timestamp":118013836117,"id":37,"parentId":19,"tags":{"page":"/api/sessions/stop"},"startTime":1781338749607,"traceId":"9cb8826ecd92b75b"},{"name":"is-page-static","duration":674171,"timestamp":118013841449,"id":40,"parentId":21,"tags":{},"startTime":1781338749612,"traceId":"9cb8826ecd92b75b"},{"name":"check-page","duration":684474,"timestamp":118013831188,"id":21,"parentId":19,"tags":{"page":"/_not-found"},"startTime":1781338749602,"traceId":"9cb8826ecd92b75b"},{"name":"is-page-static","duration":673413,"timestamp":118013844141,"id":57,"parentId":38,"tags":{},"startTime":1781338749615,"traceId":"9cb8826ecd92b75b"},{"name":"check-page","duration":681313,"timestamp":118013836300,"id":38,"parentId":19,"tags":{"page":"/favicon.ico"},"startTime":1781338749607,"traceId":"9cb8826ecd92b75b"},{"name":"is-page-static","duration":678441,"timestamp":118013843713,"id":55,"parentId":36,"tags":{},"startTime":1781338749614,"traceId":"9cb8826ecd92b75b"},{"name":"check-page","duration":686315,"timestamp":118013835895,"id":36,"parentId":19,"tags":{"page":"/api/sessions/stats"},"startTime":1781338749606,"traceId":"9cb8826ecd92b75b"},{"name":"is-page-static","duration":679345,"timestamp":118013843148,"id":49,"parentId":30,"tags":{},"startTime":1781338749614,"traceId":"9cb8826ecd92b75b"},{"name":"check-page","duration":688097,"timestamp":118013834431,"id":30,"parentId":19,"tags":{"page":"/api/sessions/inject"},"startTime":1781338749605,"traceId":"9cb8826ecd92b75b"},{"name":"is-page-static","duration":680072,"timestamp":118013842550,"id":46,"parentId":27,"tags":{},"startTime":1781338749613,"traceId":"9cb8826ecd92b75b"},{"name":"check-page","duration":688908,"timestamp":118013833738,"id":27,"parentId":19,"tags":{"page":"/api/files"},"startTime":1781338749604,"traceId":"9cb8826ecd92b75b"},{"name":"is-page-static","duration":681725,"timestamp":118013843663,"id":54,"parentId":35,"tags":{},"startTime":1781338749614,"traceId":"9cb8826ecd92b75b"},{"name":"check-page","duration":689938,"timestamp":118013835495,"id":35,"parentId":19,"tags":{"page":"/api/sessions/start"},"startTime":1781338749606,"traceId":"9cb8826ecd92b75b"},{"name":"is-page-static","duration":685057,"timestamp":118013843601,"id":53,"parentId":34,"tags":{},"startTime":1781338749614,"traceId":"9cb8826ecd92b75b"},{"name":"check-page","duration":693485,"timestamp":118013835212,"id":34,"parentId":19,"tags":{"page":"/api/sessions/scope"},"startTime":1781338749606,"traceId":"9cb8826ecd92b75b"},{"name":"is-page-static","duration":685674,"timestamp":118013843363,"id":51,"parentId":32,"tags":{},"startTime":1781338749614,"traceId":"9cb8826ecd92b75b"},{"name":"check-page","duration":694198,"timestamp":118013834859,"id":32,"parentId":19,"tags":{"page":"/api/sessions/launch"},"startTime":1781338749605,"traceId":"9cb8826ecd92b75b"},{"name":"is-page-static","duration":687810,"timestamp":118013843286,"id":50,"parentId":31,"tags":{},"startTime":1781338749614,"traceId":"9cb8826ecd92b75b"},{"name":"check-page","duration":696471,"timestamp":118013834656,"id":31,"parentId":19,"tags":{"page":"/api/sessions/input"},"startTime":1781338749605,"traceId":"9cb8826ecd92b75b"},{"name":"static-check","duration":702012,"timestamp":118013829142,"id":19,"parentId":1,"tags":{},"startTime":1781338749600,"traceId":"9cb8826ecd92b75b"},{"name":"write-routes-manifest","duration":825,"timestamp":118014532169,"id":60,"parentId":1,"tags":{},"startTime":1781338750303,"traceId":"9cb8826ecd92b75b"},{"name":"load-dotenv","duration":37,"timestamp":118014549398,"id":63,"parentId":62,"tags":{},"startTime":1781338750320,"traceId":"9cb8826ecd92b75b"},{"name":"run-export-path-map","duration":511,"timestamp":118014554631,"id":64,"parentId":62,"tags":{},"startTime":1781338750325,"traceId":"9cb8826ecd92b75b"},{"name":"next-export","duration":662660,"timestamp":118014548449,"id":62,"parentId":1,"tags":{},"startTime":1781338750319,"traceId":"9cb8826ecd92b75b"},{"name":"move-exported-app-not-found-","duration":2015,"timestamp":118015212509,"id":65,"parentId":61,"tags":{},"startTime":1781338750983,"traceId":"9cb8826ecd92b75b"},{"name":"move-exported-app-global-error-","duration":1369,"timestamp":118015214626,"id":66,"parentId":61,"tags":{},"startTime":1781338750985,"traceId":"9cb8826ecd92b75b"},{"name":"static-generation","duration":681180,"timestamp":118014537878,"id":61,"parentId":1,"tags":{},"startTime":1781338750308,"traceId":"9cb8826ecd92b75b"},{"name":"write-routes-manifest","duration":791,"timestamp":118015219174,"id":67,"parentId":1,"tags":{},"startTime":1781338750990,"traceId":"9cb8826ecd92b75b"},{"name":"print-tree-view","duration":2954,"timestamp":118015229447,"id":68,"parentId":1,"tags":{},"startTime":1781338751000,"traceId":"9cb8826ecd92b75b"},{"name":"write-route-bundle-stats","duration":16441,"timestamp":118015232437,"id":69,"parentId":1,"tags":{},"startTime":1781338751003,"traceId":"9cb8826ecd92b75b"},{"name":"telemetry-flush","duration":169841,"timestamp":118015248909,"id":70,"parentId":1,"tags":{},"startTime":1781338751019,"traceId":"9cb8826ecd92b75b"},{"name":"next-build","duration":7554364,"timestamp":118007864407,"id":1,"tags":{"buildMode":"default","version":"16.2.6","bundler":"turbopack","has-custom-webpack-config":"false","use-build-worker":"true"},"startTime":1781338743635,"traceId":"9cb8826ecd92b75b"}]
|
|
1
|
+
[{"name":"generate-buildid","duration":233,"timestamp":122936787499,"id":4,"parentId":1,"tags":{},"startTime":1781343672559,"traceId":"6671a738675edec6"},{"name":"load-custom-routes","duration":416,"timestamp":122936787853,"id":5,"parentId":1,"tags":{},"startTime":1781343672559,"traceId":"6671a738675edec6"},{"name":"create-dist-dir","duration":655,"timestamp":122936788306,"id":6,"parentId":1,"tags":{},"startTime":1781343672560,"traceId":"6671a738675edec6"},{"name":"clean","duration":505,"timestamp":122936789824,"id":7,"parentId":1,"tags":{},"startTime":1781343672561,"traceId":"6671a738675edec6"},{"name":"discover-routes","duration":7895,"timestamp":122936814021,"id":8,"parentId":1,"tags":{},"startTime":1781343672585,"traceId":"6671a738675edec6"},{"name":"create-root-mapping","duration":65,"timestamp":122936821969,"id":9,"parentId":1,"tags":{},"startTime":1781343672593,"traceId":"6671a738675edec6"},{"name":"generate-route-types","duration":18916,"timestamp":122936823530,"id":10,"parentId":1,"tags":{},"startTime":1781343672595,"traceId":"6671a738675edec6"},{"name":"public-dir-conflict-check","duration":112,"timestamp":122936842618,"id":11,"parentId":1,"tags":{},"startTime":1781343672614,"traceId":"6671a738675edec6"},{"name":"generate-routes-manifest","duration":2601,"timestamp":122936842847,"id":12,"parentId":1,"tags":{},"startTime":1781343672614,"traceId":"6671a738675edec6"},{"name":"run-turbopack","duration":2481070,"timestamp":122936852892,"id":14,"parentId":1,"tags":{},"startTime":1781343672624,"traceId":"6671a738675edec6"},{"name":"turbopack-build-events","duration":73,"timestamp":122937178078,"id":15,"parentId":1,"tags":{},"startTime":1781343672949,"traceId":"6671a738675edec6"},{"name":"run-typescript","duration":4017829,"timestamp":122939341501,"id":16,"parentId":1,"tags":{},"startTime":1781343675113,"traceId":"6671a738675edec6"},{"name":"generate-required-server-files","duration":1447,"timestamp":122943360185,"id":18,"parentId":1,"tags":{},"startTime":1781343679132,"traceId":"6671a738675edec6"},{"name":"check-static-error-page","duration":8108,"timestamp":122943512253,"id":20,"parentId":19,"tags":{},"startTime":1781343679284,"traceId":"6671a738675edec6"},{"name":"is-page-static","duration":585753,"timestamp":122943525922,"id":41,"parentId":22,"tags":{},"startTime":1781343679297,"traceId":"6671a738675edec6"},{"name":"check-page","duration":596750,"timestamp":122943515212,"id":22,"parentId":19,"tags":{"page":"/_global-error"},"startTime":1781343679287,"traceId":"6671a738675edec6"},{"name":"is-page-static","duration":766859,"timestamp":122943526780,"id":48,"parentId":29,"tags":{},"startTime":1781343679298,"traceId":"6671a738675edec6"},{"name":"check-page","duration":776640,"timestamp":122943517064,"id":29,"parentId":19,"tags":{"page":"/api/recents"},"startTime":1781343679288,"traceId":"6671a738675edec6"},{"name":"is-page-static","duration":781361,"timestamp":122943527001,"id":49,"parentId":30,"tags":{},"startTime":1781343679298,"traceId":"6671a738675edec6"},{"name":"check-page","duration":791109,"timestamp":122943517307,"id":30,"parentId":19,"tags":{"page":"/api/sessions/inject"},"startTime":1781343679289,"traceId":"6671a738675edec6"},{"name":"is-page-static","duration":783998,"timestamp":122943526248,"id":44,"parentId":25,"tags":{},"startTime":1781343679298,"traceId":"6671a738675edec6"},{"name":"check-page","duration":794120,"timestamp":122943516181,"id":25,"parentId":19,"tags":{"page":"/api/context"},"startTime":1781343679288,"traceId":"6671a738675edec6"},{"name":"is-page-static","duration":787189,"timestamp":122943526318,"id":45,"parentId":26,"tags":{},"startTime":1781343679298,"traceId":"6671a738675edec6"},{"name":"check-page","duration":797177,"timestamp":122943516382,"id":26,"parentId":19,"tags":{"page":"/api/context/ssh"},"startTime":1781343679288,"traceId":"6671a738675edec6"},{"name":"is-page-static","duration":787503,"timestamp":122943526675,"id":47,"parentId":28,"tags":{},"startTime":1781343679298,"traceId":"6671a738675edec6"},{"name":"check-page","duration":797395,"timestamp":122943516838,"id":28,"parentId":19,"tags":{"page":"/api/git"},"startTime":1781343679288,"traceId":"6671a738675edec6"},{"name":"is-page-static","duration":802754,"timestamp":122943525584,"id":40,"parentId":21,"tags":{},"startTime":1781343679297,"traceId":"6671a738675edec6"},{"name":"check-page","duration":814472,"timestamp":122943513913,"id":21,"parentId":19,"tags":{"page":"/_not-found"},"startTime":1781343679285,"traceId":"6671a738675edec6"},{"name":"is-page-static","duration":811742,"timestamp":122943526060,"id":42,"parentId":23,"tags":{},"startTime":1781343679297,"traceId":"6671a738675edec6"},{"name":"check-page","duration":822208,"timestamp":122943515644,"id":23,"parentId":19,"tags":{"page":"/api/context/aider"},"startTime":1781343679287,"traceId":"6671a738675edec6"},{"name":"is-page-static","duration":812137,"timestamp":122943527223,"id":51,"parentId":32,"tags":{},"startTime":1781343679299,"traceId":"6671a738675edec6"},{"name":"check-page","duration":821595,"timestamp":122943517818,"id":32,"parentId":19,"tags":{"page":"/api/sessions/launch"},"startTime":1781343679289,"traceId":"6671a738675edec6"},{"name":"is-page-static","duration":814442,"timestamp":122943527291,"id":52,"parentId":33,"tags":{},"startTime":1781343679299,"traceId":"6671a738675edec6"},{"name":"check-page","duration":823715,"timestamp":122943518063,"id":33,"parentId":19,"tags":{"page":"/api/sessions"},"startTime":1781343679289,"traceId":"6671a738675edec6"},{"name":"is-page-static","duration":815509,"timestamp":122943527411,"id":54,"parentId":35,"tags":{},"startTime":1781343679299,"traceId":"6671a738675edec6"},{"name":"check-page","duration":824290,"timestamp":122943518666,"id":35,"parentId":19,"tags":{"page":"/api/sessions/start"},"startTime":1781343679290,"traceId":"6671a738675edec6"},{"name":"is-page-static","duration":816612,"timestamp":122943527642,"id":57,"parentId":38,"tags":{},"startTime":1781343679299,"traceId":"6671a738675edec6"},{"name":"check-page","duration":824697,"timestamp":122943519593,"id":38,"parentId":19,"tags":{"page":"/favicon.ico"},"startTime":1781343679291,"traceId":"6671a738675edec6"},{"name":"is-page-static","duration":817880,"timestamp":122943526555,"id":46,"parentId":27,"tags":{},"startTime":1781343679298,"traceId":"6671a738675edec6"},{"name":"check-page","duration":827861,"timestamp":122943516594,"id":27,"parentId":19,"tags":{"page":"/api/files"},"startTime":1781343679288,"traceId":"6671a738675edec6"},{"name":"is-page-static","duration":818726,"timestamp":122943526160,"id":43,"parentId":24,"tags":{},"startTime":1781343679297,"traceId":"6671a738675edec6"},{"name":"check-page","duration":828955,"timestamp":122943515955,"id":24,"parentId":19,"tags":{"page":"/api/context/claude"},"startTime":1781343679287,"traceId":"6671a738675edec6"},{"name":"is-page-static","duration":819367,"timestamp":122943527444,"id":55,"parentId":36,"tags":{},"startTime":1781343679299,"traceId":"6671a738675edec6"},{"name":"check-page","duration":827716,"timestamp":122943519127,"id":36,"parentId":19,"tags":{"page":"/api/sessions/stats"},"startTime":1781343679290,"traceId":"6671a738675edec6"},{"name":"is-page-static","duration":822135,"timestamp":122943527144,"id":50,"parentId":31,"tags":{},"startTime":1781343679298,"traceId":"6671a738675edec6"},{"name":"check-page","duration":831733,"timestamp":122943517584,"id":31,"parentId":19,"tags":{"page":"/api/sessions/input"},"startTime":1781343679289,"traceId":"6671a738675edec6"},{"name":"is-page-static","duration":822223,"timestamp":122943527362,"id":53,"parentId":34,"tags":{},"startTime":1781343679299,"traceId":"6671a738675edec6"},{"name":"check-page","duration":831331,"timestamp":122943518290,"id":34,"parentId":19,"tags":{"page":"/api/sessions/scope"},"startTime":1781343679290,"traceId":"6671a738675edec6"},{"name":"is-page-static","duration":822073,"timestamp":122943531435,"id":58,"parentId":39,"tags":{},"startTime":1781343679303,"traceId":"6671a738675edec6"},{"name":"check-page","duration":833537,"timestamp":122943520002,"id":39,"parentId":19,"tags":{"page":"/"},"startTime":1781343679291,"traceId":"6671a738675edec6"},{"name":"is-page-static","duration":831907,"timestamp":122943527480,"id":56,"parentId":37,"tags":{},"startTime":1781343679299,"traceId":"6671a738675edec6"},{"name":"check-page","duration":840023,"timestamp":122943519404,"id":37,"parentId":19,"tags":{"page":"/api/sessions/stop"},"startTime":1781343679291,"traceId":"6671a738675edec6"},{"name":"static-check","duration":847689,"timestamp":122943511766,"id":19,"parentId":1,"tags":{},"startTime":1781343679283,"traceId":"6671a738675edec6"},{"name":"write-routes-manifest","duration":822,"timestamp":122944360519,"id":60,"parentId":1,"tags":{},"startTime":1781343680132,"traceId":"6671a738675edec6"},{"name":"load-dotenv","duration":34,"timestamp":122944376710,"id":63,"parentId":62,"tags":{},"startTime":1781343680148,"traceId":"6671a738675edec6"},{"name":"run-export-path-map","duration":483,"timestamp":122944381824,"id":64,"parentId":62,"tags":{},"startTime":1781343680153,"traceId":"6671a738675edec6"},{"name":"next-export","duration":699880,"timestamp":122944375844,"id":62,"parentId":1,"tags":{},"startTime":1781343680147,"traceId":"6671a738675edec6"},{"name":"move-exported-app-not-found-","duration":2207,"timestamp":122945077590,"id":65,"parentId":61,"tags":{},"startTime":1781343680849,"traceId":"6671a738675edec6"},{"name":"move-exported-app-global-error-","duration":1556,"timestamp":122945079921,"id":66,"parentId":61,"tags":{},"startTime":1781343680851,"traceId":"6671a738675edec6"},{"name":"static-generation","duration":718716,"timestamp":122944366415,"id":61,"parentId":1,"tags":{},"startTime":1781343680138,"traceId":"6671a738675edec6"},{"name":"write-routes-manifest","duration":795,"timestamp":122945085252,"id":67,"parentId":1,"tags":{},"startTime":1781343680857,"traceId":"6671a738675edec6"},{"name":"print-tree-view","duration":3065,"timestamp":122945096735,"id":68,"parentId":1,"tags":{},"startTime":1781343680868,"traceId":"6671a738675edec6"},{"name":"write-route-bundle-stats","duration":14376,"timestamp":122945099835,"id":69,"parentId":1,"tags":{},"startTime":1781343680871,"traceId":"6671a738675edec6"},{"name":"telemetry-flush","duration":174402,"timestamp":122945114263,"id":70,"parentId":1,"tags":{},"startTime":1781343680886,"traceId":"6671a738675edec6"},{"name":"next-build","duration":8551307,"timestamp":122936737382,"id":1,"tags":{"buildMode":"default","version":"16.2.6","bundler":"turbopack","has-custom-webpack-config":"false","use-build-worker":"true"},"startTime":1781343672509,"traceId":"6671a738675edec6"}]
|
package/.next/trace-build
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
[{"name":"run-turbopack","duration":
|
|
1
|
+
[{"name":"run-turbopack","duration":2481070,"timestamp":122936852892,"id":14,"parentId":1,"tags":{},"startTime":1781343672624,"traceId":"6671a738675edec6"},{"name":"turbopack-build-events","duration":73,"timestamp":122937178078,"id":15,"parentId":1,"tags":{},"startTime":1781343672949,"traceId":"6671a738675edec6"},{"name":"run-typescript","duration":4017829,"timestamp":122939341501,"id":16,"parentId":1,"tags":{},"startTime":1781343675113,"traceId":"6671a738675edec6"},{"name":"static-check","duration":847689,"timestamp":122943511766,"id":19,"parentId":1,"tags":{},"startTime":1781343679283,"traceId":"6671a738675edec6"},{"name":"static-generation","duration":718716,"timestamp":122944366415,"id":61,"parentId":1,"tags":{},"startTime":1781343680138,"traceId":"6671a738675edec6"},{"name":"telemetry-flush","duration":174402,"timestamp":122945114263,"id":70,"parentId":1,"tags":{},"startTime":1781343680886,"traceId":"6671a738675edec6"},{"name":"next-build","duration":8551307,"timestamp":122936737382,"id":1,"tags":{"buildMode":"default","version":"16.2.6","bundler":"turbopack","has-custom-webpack-config":"false","use-build-worker":"true"},"startTime":1781343672509,"traceId":"6671a738675edec6"}]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { NextResponse } from "next/server";
|
|
2
2
|
import { SessionManager } from "@/lib/agents/SessionManager";
|
|
3
|
-
import { addRecent } from "@/lib/recents";
|
|
3
|
+
import { addRecent, saveLastSession } from "@/lib/recents";
|
|
4
4
|
|
|
5
5
|
export async function POST(request: Request) {
|
|
6
6
|
try {
|
|
@@ -15,6 +15,9 @@ export async function POST(request: Request) {
|
|
|
15
15
|
const manager = SessionManager.getInstance();
|
|
16
16
|
const session = await manager.createSession(type, name, workspaceRoot, scopedDirs);
|
|
17
17
|
|
|
18
|
+
// Save session config to recents
|
|
19
|
+
saveLastSession({ type, name, workspaceRoot, scopedDirs });
|
|
20
|
+
|
|
18
21
|
// Save workspace root to recents list
|
|
19
22
|
if (workspaceRoot) {
|
|
20
23
|
addRecent("workspace", workspaceRoot);
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { NextResponse } from "next/server";
|
|
2
2
|
import { SessionManager } from "@/lib/agents/SessionManager";
|
|
3
3
|
|
|
4
|
+
declare global {
|
|
5
|
+
var wsPort: number | undefined;
|
|
6
|
+
}
|
|
7
|
+
|
|
4
8
|
export async function GET(request: Request) {
|
|
5
9
|
try {
|
|
6
10
|
const { searchParams } = new URL(request.url);
|
|
@@ -15,12 +19,14 @@ export async function GET(request: Request) {
|
|
|
15
19
|
return NextResponse.json({
|
|
16
20
|
...session.getStatus(),
|
|
17
21
|
logs: session.logs,
|
|
22
|
+
wsPort: global.wsPort || 3001,
|
|
18
23
|
});
|
|
19
24
|
}
|
|
20
25
|
|
|
21
26
|
const sessions = manager.listSessions();
|
|
22
27
|
const originalCwd = process.env.ORIGINAL_CWD || process.cwd();
|
|
23
|
-
|
|
28
|
+
const wsPort = global.wsPort || 3001;
|
|
29
|
+
return NextResponse.json({ sessions, originalCwd, wsPort });
|
|
24
30
|
} catch (error) {
|
|
25
31
|
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
26
32
|
return NextResponse.json({ error: errorMessage }, { status: 500 });
|
|
@@ -73,6 +73,7 @@ interface IdeLayoutProps {
|
|
|
73
73
|
sessions: RunnerStatus[];
|
|
74
74
|
onSwitchSession: (id: string) => void;
|
|
75
75
|
onRefreshSessions?: () => void;
|
|
76
|
+
wsPort?: number;
|
|
76
77
|
}
|
|
77
78
|
|
|
78
79
|
interface OpenFile {
|
|
@@ -82,7 +83,7 @@ interface OpenFile {
|
|
|
82
83
|
isModified: boolean;
|
|
83
84
|
}
|
|
84
85
|
|
|
85
|
-
export default function IdeLayout({ sessionId, workspaceRoot, scopedDirs, onClose, sessions, onSwitchSession, onRefreshSessions }: IdeLayoutProps) {
|
|
86
|
+
export default function IdeLayout({ sessionId, workspaceRoot, scopedDirs, onClose, sessions, onSwitchSession, onRefreshSessions, wsPort = 3001 }: IdeLayoutProps) {
|
|
86
87
|
const scopedDirsStr = JSON.stringify(scopedDirs);
|
|
87
88
|
const activeSession = sessions.find(s => s.id === sessionId);
|
|
88
89
|
const [workspace, setWorkspace] = useState<WorkspaceData | null>(null);
|
|
@@ -1411,7 +1412,7 @@ export default function IdeLayout({ sessionId, workspaceRoot, scopedDirs, onClos
|
|
|
1411
1412
|
|
|
1412
1413
|
<div style={{ ...terminalConsoleWrapperStyle, display: "flex", width: "100%", height: "100%" }}>
|
|
1413
1414
|
<div style={{ flex: 1, height: "100%", borderRight: splitSessionId ? "1px solid var(--border)" : "none", overflow: "hidden" }}>
|
|
1414
|
-
<TerminalConsole sessionId={sessionId} height="100%" />
|
|
1415
|
+
<TerminalConsole sessionId={sessionId} height="100%" wsPort={wsPort} />
|
|
1415
1416
|
</div>
|
|
1416
1417
|
{splitSessionId && (
|
|
1417
1418
|
<div style={{ flex: 1, height: "100%", overflow: "hidden", display: "flex", flexDirection: "column" }}>
|
|
@@ -1426,7 +1427,7 @@ export default function IdeLayout({ sessionId, workspaceRoot, scopedDirs, onClos
|
|
|
1426
1427
|
</button>
|
|
1427
1428
|
</div>
|
|
1428
1429
|
<div style={{ flex: 1, overflow: "hidden" }}>
|
|
1429
|
-
<TerminalConsole sessionId={splitSessionId} height="100%" />
|
|
1430
|
+
<TerminalConsole sessionId={splitSessionId} height="100%" wsPort={wsPort} />
|
|
1430
1431
|
</div>
|
|
1431
1432
|
</div>
|
|
1432
1433
|
)}
|
|
@@ -9,9 +9,10 @@ import "xterm/css/xterm.css";
|
|
|
9
9
|
interface TerminalConsoleProps {
|
|
10
10
|
sessionId: string;
|
|
11
11
|
height?: string | number;
|
|
12
|
+
wsPort?: number;
|
|
12
13
|
}
|
|
13
14
|
|
|
14
|
-
export default function TerminalConsole({ sessionId, height = "400px" }: TerminalConsoleProps) {
|
|
15
|
+
export default function TerminalConsole({ sessionId, height = "400px", wsPort = 3001 }: TerminalConsoleProps) {
|
|
15
16
|
const terminalRef = useRef<HTMLDivElement>(null);
|
|
16
17
|
const xtermRef = useRef<Terminal | null>(null);
|
|
17
18
|
const wsRef = useRef<WebSocket | null>(null);
|
|
@@ -130,9 +131,9 @@ export default function TerminalConsole({ sessionId, height = "400px" }: Termina
|
|
|
130
131
|
|
|
131
132
|
xtermRef.current = term;
|
|
132
133
|
|
|
133
|
-
// Connect WebSocket client to gateway server on port
|
|
134
|
+
// Connect WebSocket client to gateway server on dynamic port
|
|
134
135
|
const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
|
|
135
|
-
const wsUrl = `${protocol}//${window.location.hostname}
|
|
136
|
+
const wsUrl = `${protocol}//${window.location.hostname}:${wsPort}`;
|
|
136
137
|
const ws = new WebSocket(wsUrl);
|
|
137
138
|
wsRef.current = ws;
|
|
138
139
|
|
|
@@ -216,7 +217,7 @@ export default function TerminalConsole({ sessionId, height = "400px" }: Termina
|
|
|
216
217
|
console.warn("Error disposing terminal:", e);
|
|
217
218
|
}
|
|
218
219
|
};
|
|
219
|
-
}, [sessionId]);
|
|
220
|
+
}, [sessionId, wsPort]);
|
|
220
221
|
|
|
221
222
|
return (
|
|
222
223
|
<div
|
package/src/app/page.tsx
CHANGED
|
@@ -88,6 +88,13 @@ export default function Home() {
|
|
|
88
88
|
const [isClaudeWizardOpen, setIsClaudeWizardOpen] = useState<boolean>(false);
|
|
89
89
|
const [isClaudeDockerLaunch, setIsClaudeDockerLaunch] = useState<boolean>(false);
|
|
90
90
|
const [serverCwd, setServerCwd] = useState<string>("");
|
|
91
|
+
const [wsPort, setWsPort] = useState<number>(3001);
|
|
92
|
+
const [lastSessionConfig, setLastSessionConfig] = useState<{
|
|
93
|
+
type: 'mock' | 'claude' | 'claude-docker' | 'claude-ssh' | 'aider' | 'aider-docker';
|
|
94
|
+
name?: string;
|
|
95
|
+
workspaceRoot?: string;
|
|
96
|
+
scopedDirs?: string[];
|
|
97
|
+
} | null>(null);
|
|
91
98
|
|
|
92
99
|
const activeSession = sessions.find(s => s.id === activeSessionId);
|
|
93
100
|
const isDockerActive = sessions.some(s => (s.type === 'claude-docker' || s.type === 'aider-docker') && s.status === 'running');
|
|
@@ -101,6 +108,9 @@ export default function Home() {
|
|
|
101
108
|
if (data.sessions) {
|
|
102
109
|
setSessions(data.sessions);
|
|
103
110
|
}
|
|
111
|
+
if (data.wsPort) {
|
|
112
|
+
setWsPort(data.wsPort);
|
|
113
|
+
}
|
|
104
114
|
if (data.originalCwd) {
|
|
105
115
|
setServerCwd(data.originalCwd);
|
|
106
116
|
}
|
|
@@ -109,9 +119,24 @@ export default function Home() {
|
|
|
109
119
|
}
|
|
110
120
|
};
|
|
111
121
|
|
|
122
|
+
const fetchRecents = async () => {
|
|
123
|
+
try {
|
|
124
|
+
const res = await fetch("/api/recents");
|
|
125
|
+
if (res.ok) {
|
|
126
|
+
const data = await res.json();
|
|
127
|
+
if (data.success && data.recents && data.recents.lastSession) {
|
|
128
|
+
setLastSessionConfig(data.recents.lastSession);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
} catch (err) {
|
|
132
|
+
console.error("Failed to fetch recents:", err);
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
|
|
112
136
|
useEffect(() => {
|
|
113
137
|
const initFetch = async () => {
|
|
114
138
|
await fetchSessions();
|
|
139
|
+
await fetchRecents();
|
|
115
140
|
};
|
|
116
141
|
initFetch();
|
|
117
142
|
const interval = setInterval(fetchSessions, 4000);
|
|
@@ -173,6 +198,7 @@ export default function Home() {
|
|
|
173
198
|
if (data.success) {
|
|
174
199
|
await fetchSessions();
|
|
175
200
|
setActiveSessionId(data.session.id);
|
|
201
|
+
setLastSessionConfig({ type, name: sessionName, workspaceRoot: customWorkspaceRoot, scopedDirs: customScopedDirs });
|
|
176
202
|
}
|
|
177
203
|
} catch (err) {
|
|
178
204
|
console.error("Failed to launch session:", err);
|
|
@@ -226,6 +252,7 @@ export default function Home() {
|
|
|
226
252
|
sessions={sessions}
|
|
227
253
|
onSwitchSession={(id) => setActiveSessionId(id)}
|
|
228
254
|
onRefreshSessions={fetchSessions}
|
|
255
|
+
wsPort={wsPort}
|
|
229
256
|
/>
|
|
230
257
|
</div>
|
|
231
258
|
) : (
|
|
@@ -239,16 +266,71 @@ export default function Home() {
|
|
|
239
266
|
{sessions.length === 0 ? (
|
|
240
267
|
<div className="card" style={{ padding: "3rem 1.5rem", textAlign: "center" }}>
|
|
241
268
|
<p style={{ color: "var(--muted)", marginBottom: "1.5rem" }}>
|
|
242
|
-
No active agent sessions in this workspace. Launch a
|
|
269
|
+
No active agent sessions in this workspace. Launch a Claude or Aider agent session to begin.
|
|
243
270
|
</p>
|
|
244
|
-
<
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
271
|
+
<div style={{ display: "flex", gap: "1rem", justifyContent: "center", flexWrap: "wrap" }}>
|
|
272
|
+
{lastSessionConfig && (
|
|
273
|
+
<button
|
|
274
|
+
className={styles.quickLaunchBtn}
|
|
275
|
+
onClick={() => {
|
|
276
|
+
handleLaunchSession(
|
|
277
|
+
lastSessionConfig.type,
|
|
278
|
+
lastSessionConfig.name,
|
|
279
|
+
lastSessionConfig.workspaceRoot,
|
|
280
|
+
lastSessionConfig.scopedDirs
|
|
281
|
+
);
|
|
282
|
+
}}
|
|
283
|
+
disabled={isLoading}
|
|
284
|
+
style={{
|
|
285
|
+
background: "linear-gradient(135deg, hsl(38, 92%, 50%) 0%, hsl(0, 84%, 60%) 100%)",
|
|
286
|
+
border: "none",
|
|
287
|
+
maxWidth: "200px"
|
|
288
|
+
}}
|
|
289
|
+
title={`Re-launch: ${lastSessionConfig.name || lastSessionConfig.type}`}
|
|
290
|
+
>
|
|
291
|
+
⚡ Re-launch Last Session
|
|
292
|
+
</button>
|
|
293
|
+
)}
|
|
294
|
+
<button
|
|
295
|
+
className={styles.quickLaunchBtn}
|
|
296
|
+
onClick={() => {
|
|
297
|
+
setIsClaudeDockerLaunch(false);
|
|
298
|
+
setIsClaudeWizardOpen(true);
|
|
299
|
+
}}
|
|
300
|
+
disabled={isLoading}
|
|
301
|
+
style={{
|
|
302
|
+
background: "linear-gradient(135deg, hsl(262, 83%, 60%) 0%, hsl(195, 100%, 45%) 100%)",
|
|
303
|
+
border: "none",
|
|
304
|
+
maxWidth: "200px"
|
|
305
|
+
}}
|
|
306
|
+
>
|
|
307
|
+
Launch Claude PTY
|
|
308
|
+
</button>
|
|
309
|
+
<button
|
|
310
|
+
className={styles.quickLaunchBtn}
|
|
311
|
+
onClick={() => {
|
|
312
|
+
setIsAiderDockerLaunch(false);
|
|
313
|
+
setIsAiderWizardOpen(true);
|
|
314
|
+
}}
|
|
315
|
+
disabled={isLoading}
|
|
316
|
+
style={{
|
|
317
|
+
background: "linear-gradient(135deg, hsl(210, 80%, 45%) 0%, hsl(262, 80%, 55%) 100%)",
|
|
318
|
+
border: "none",
|
|
319
|
+
maxWidth: "200px"
|
|
320
|
+
}}
|
|
321
|
+
>
|
|
322
|
+
Launch Aider PTY
|
|
323
|
+
</button>
|
|
324
|
+
</div>
|
|
325
|
+
<div style={{ marginTop: "1.5rem", fontSize: "0.75rem", color: "var(--muted)" }}>
|
|
326
|
+
Want to verify layout features first?{" "}
|
|
327
|
+
<span
|
|
328
|
+
onClick={() => handleLaunchSession('mock')}
|
|
329
|
+
style={{ color: "var(--primary)", cursor: "pointer", textDecoration: "underline" }}
|
|
330
|
+
>
|
|
331
|
+
Start simulated sandbox session
|
|
332
|
+
</span>
|
|
333
|
+
</div>
|
|
252
334
|
</div>
|
|
253
335
|
) : (
|
|
254
336
|
<div className={styles.agentGrid}>
|
|
@@ -383,7 +465,7 @@ export default function Home() {
|
|
|
383
465
|
>Close Panel ✖</button>
|
|
384
466
|
</div>
|
|
385
467
|
</div>
|
|
386
|
-
<TerminalConsole sessionId={activeSessionId} />
|
|
468
|
+
<TerminalConsole sessionId={activeSessionId} wsPort={wsPort} />
|
|
387
469
|
</section>
|
|
388
470
|
)}
|
|
389
471
|
|
|
@@ -482,10 +564,6 @@ export default function Home() {
|
|
|
482
564
|
</section>
|
|
483
565
|
|
|
484
566
|
<section style={{ display: "flex", flexDirection: "column", gap: "0.75rem" }}>
|
|
485
|
-
<button className={styles.quickLaunchBtn} onClick={() => handleLaunchSession('mock')} disabled={isLoading}>
|
|
486
|
-
<span>⚡</span>
|
|
487
|
-
<span>Launch Mock Agent</span>
|
|
488
|
-
</button>
|
|
489
567
|
<button
|
|
490
568
|
className={styles.quickLaunchBtn}
|
|
491
569
|
onClick={() => {
|
|
@@ -576,6 +654,15 @@ export default function Home() {
|
|
|
576
654
|
<span style={{ color: "var(--primary)", cursor: "pointer" }}>→</span>
|
|
577
655
|
</li>
|
|
578
656
|
</ul>
|
|
657
|
+
<div style={{ marginTop: "1.2rem", textAlign: "center", fontSize: "0.72rem", color: "var(--muted)" }}>
|
|
658
|
+
Need to troubleshoot?{" "}
|
|
659
|
+
<span
|
|
660
|
+
onClick={() => handleLaunchSession('mock')}
|
|
661
|
+
style={{ color: "var(--primary)", cursor: "pointer", textDecoration: "underline" }}
|
|
662
|
+
>
|
|
663
|
+
Launch simulated playground sandbox
|
|
664
|
+
</span>
|
|
665
|
+
</div>
|
|
579
666
|
</section>
|
|
580
667
|
</aside>
|
|
581
668
|
|
|
@@ -3,6 +3,7 @@ import { AgentRunner } from "./AgentRunner";
|
|
|
3
3
|
|
|
4
4
|
declare global {
|
|
5
5
|
var wss: WebSocketServer | undefined;
|
|
6
|
+
var wsPort: number | undefined;
|
|
6
7
|
}
|
|
7
8
|
|
|
8
9
|
let getSessionCallback: ((id: string) => AgentRunner | undefined) | null = null;
|
|
@@ -13,120 +14,144 @@ export function initWebSocketServer(port = 3001, getSession?: (id: string) => Ag
|
|
|
13
14
|
}
|
|
14
15
|
// Prevent duplicate WebSocket servers during hot reloads in development
|
|
15
16
|
if (global.wss) {
|
|
16
|
-
console.log(
|
|
17
|
+
console.log(`[WebSocketServer] WebSocket Server already active on port ${global.wsPort || 3001} (cached).`);
|
|
17
18
|
return;
|
|
18
19
|
}
|
|
19
20
|
|
|
20
|
-
|
|
21
|
+
let currentPort = port;
|
|
22
|
+
const maxPort = port + 10;
|
|
21
23
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
wss.on("error", (err) => {
|
|
25
|
-
console.error("[WebSocketServer] WebSocket server error:", err);
|
|
26
|
-
});
|
|
27
|
-
global.wss = wss;
|
|
24
|
+
function tryBind() {
|
|
25
|
+
console.log(`[WebSocketServer] Launching NeuralLoom WebSocket Gateway on port ${currentPort}...`);
|
|
28
26
|
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
try {
|
|
28
|
+
const wss = new WebSocketServer({ port: currentPort });
|
|
31
29
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
wss.on("error", (err: unknown) => {
|
|
31
|
+
const socketErr = err as { code?: string };
|
|
32
|
+
if (socketErr.code === "EADDRINUSE" && currentPort < maxPort) {
|
|
33
|
+
console.warn(`[WebSocketServer] Port ${currentPort} in use, trying next port...`);
|
|
34
|
+
currentPort++;
|
|
35
|
+
tryBind();
|
|
36
|
+
} else {
|
|
37
|
+
console.error("[WebSocketServer] WebSocket server error:", err);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
35
40
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
41
|
+
wss.on("listening", () => {
|
|
42
|
+
global.wss = wss;
|
|
43
|
+
global.wsPort = currentPort;
|
|
44
|
+
console.log(`[WebSocketServer] WebSocket gateway successfully listening on port ${currentPort}.`);
|
|
45
|
+
});
|
|
39
46
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const { sessionId } = msg;
|
|
43
|
-
const session = getSessionCallback ? getSessionCallback(sessionId) : null;
|
|
47
|
+
wss.on("connection", (ws: WebSocket & { sessionId?: string }) => {
|
|
48
|
+
console.log("[WebSocketServer] New client connected via gateway.");
|
|
44
49
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
};
|
|
56
|
-
session
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
50
|
+
let activeSessionId: string | null = null;
|
|
51
|
+
let outputListener: ((data: string) => void) | null = null;
|
|
52
|
+
let mockBuffer = "";
|
|
53
|
+
|
|
54
|
+
ws.on("message", async (rawMsg) => {
|
|
55
|
+
try {
|
|
56
|
+
const msg = JSON.parse(rawMsg.toString());
|
|
57
|
+
|
|
58
|
+
// Client handshake to establish connection to a specific session
|
|
59
|
+
if (msg.type === "handshake") {
|
|
60
|
+
const { sessionId } = msg;
|
|
61
|
+
const session = getSessionCallback ? getSessionCallback(sessionId) : null;
|
|
62
|
+
|
|
63
|
+
if (session) {
|
|
64
|
+
activeSessionId = sessionId;
|
|
65
|
+
ws.sessionId = sessionId;
|
|
66
|
+
console.log(`[WebSocketServer] Client connected to active session: ${sessionId}`);
|
|
67
|
+
|
|
68
|
+
// Subscribe to runner output events
|
|
69
|
+
outputListener = (data: string) => {
|
|
70
|
+
if (ws.readyState === WebSocket.OPEN) {
|
|
71
|
+
ws.send(JSON.stringify({ type: "output", data }));
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
session.onOutput(outputListener);
|
|
75
|
+
|
|
76
|
+
// Send handshake acknowledgment and full historical logs
|
|
77
|
+
ws.send(
|
|
78
|
+
JSON.stringify({
|
|
79
|
+
type: "handshake-ack",
|
|
80
|
+
sessionId,
|
|
81
|
+
history: session.logs.join(""),
|
|
82
|
+
})
|
|
83
|
+
);
|
|
84
|
+
} else {
|
|
85
|
+
ws.send(JSON.stringify({ type: "error", message: "Requested session not found" }));
|
|
86
|
+
}
|
|
68
87
|
}
|
|
69
|
-
}
|
|
70
88
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
89
|
+
// User terminal input routing
|
|
90
|
+
if (msg.type === "input" && activeSessionId) {
|
|
91
|
+
const session = getSessionCallback ? getSessionCallback(activeSessionId) : null;
|
|
92
|
+
if (session && session.status === "running") {
|
|
93
|
+
if (session.type === "mock") {
|
|
94
|
+
// Buffer input for simulated command parsing in MockRunner
|
|
95
|
+
const data = msg.data;
|
|
96
|
+
if (data === "\r" || data === "\r\n") {
|
|
97
|
+
ws.send(JSON.stringify({ type: "output", data: "\r\n" }));
|
|
98
|
+
const cmd = mockBuffer;
|
|
99
|
+
mockBuffer = "";
|
|
100
|
+
await session.sendInput(cmd);
|
|
101
|
+
} else if (data === "\u007f" || data === "\b") { // Backspace
|
|
102
|
+
if (mockBuffer.length > 0) {
|
|
103
|
+
mockBuffer = mockBuffer.slice(0, -1);
|
|
104
|
+
ws.send(JSON.stringify({ type: "output", data: "\b \b" }));
|
|
105
|
+
}
|
|
106
|
+
} else {
|
|
107
|
+
mockBuffer += data;
|
|
108
|
+
ws.send(JSON.stringify({ type: "output", data })); // Local echo of key
|
|
87
109
|
}
|
|
88
110
|
} else {
|
|
89
|
-
|
|
90
|
-
|
|
111
|
+
// Pass raw keystrokes straight to Claude Code PTY
|
|
112
|
+
await session.sendInput(msg.data, true);
|
|
91
113
|
}
|
|
92
|
-
} else {
|
|
93
|
-
// Pass raw keystrokes straight to Claude Code PTY
|
|
94
|
-
await session.sendInput(msg.data, true);
|
|
95
114
|
}
|
|
96
115
|
}
|
|
116
|
+
|
|
117
|
+
// User terminal resize routing
|
|
118
|
+
if (msg.type === "resize" && activeSessionId) {
|
|
119
|
+
const { cols, rows } = msg;
|
|
120
|
+
const session = getSessionCallback ? getSessionCallback(activeSessionId) : null;
|
|
121
|
+
if (session) {
|
|
122
|
+
session.resize(cols, rows);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
} catch (err) {
|
|
126
|
+
console.error("[WebSocketServer] Error processing socket packet:", err);
|
|
97
127
|
}
|
|
128
|
+
});
|
|
98
129
|
|
|
99
|
-
|
|
100
|
-
if (
|
|
101
|
-
const { cols, rows } = msg;
|
|
130
|
+
ws.on("close", () => {
|
|
131
|
+
if (activeSessionId && outputListener) {
|
|
102
132
|
const session = getSessionCallback ? getSessionCallback(activeSessionId) : null;
|
|
103
133
|
if (session) {
|
|
104
|
-
session.
|
|
134
|
+
session.offOutput(outputListener);
|
|
105
135
|
}
|
|
106
136
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
ws.on("close", () => {
|
|
113
|
-
if (activeSessionId && outputListener) {
|
|
114
|
-
const session = getSessionCallback ? getSessionCallback(activeSessionId) : null;
|
|
115
|
-
if (session) {
|
|
116
|
-
session.offOutput(outputListener);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
console.log("[WebSocketServer] Client connection closed.");
|
|
120
|
-
});
|
|
137
|
+
console.log("[WebSocketServer] Client connection closed.");
|
|
138
|
+
});
|
|
121
139
|
|
|
122
|
-
|
|
123
|
-
|
|
140
|
+
ws.on("error", (err) => {
|
|
141
|
+
console.error("[WebSocketServer] Socket error:", err);
|
|
142
|
+
});
|
|
124
143
|
});
|
|
125
|
-
});
|
|
126
144
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
145
|
+
} catch (error) {
|
|
146
|
+
if (currentPort < maxPort) {
|
|
147
|
+
currentPort++;
|
|
148
|
+
tryBind();
|
|
149
|
+
} else {
|
|
150
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
151
|
+
console.error(`[WebSocketServer] Failed to initialize WebSocket Server: ${errorMessage}`);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
131
154
|
}
|
|
155
|
+
|
|
156
|
+
tryBind();
|
|
132
157
|
}
|