@axlsdk/studio 0.9.1 → 0.10.1

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/dist/cli.cjs CHANGED
@@ -24,13 +24,15 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
24
24
  ));
25
25
 
26
26
  // src/cli.ts
27
- var import_node_path2 = require("path");
28
- var import_node_fs2 = require("fs");
27
+ var import_node_path3 = require("path");
28
+ var import_node_fs3 = require("fs");
29
29
  var import_node_url = require("url");
30
30
  var import_node_server = require("@hono/node-server");
31
31
  var import_node_ws = require("@hono/node-ws");
32
32
 
33
33
  // src/server/index.ts
34
+ var import_node_fs = require("fs");
35
+ var import_node_path = require("path");
34
36
  var import_hono12 = require("hono");
35
37
  var import_cors = require("hono/cors");
36
38
  var import_serve_static = require("@hono/node-server/serve-static");
@@ -67,8 +69,13 @@ var ConnectionManager = class {
67
69
  channels = /* @__PURE__ */ new Map();
68
70
  /** ws -> set of subscribed channels (for cleanup) */
69
71
  connections = /* @__PURE__ */ new Map();
72
+ maxConnections = 100;
70
73
  /** Register a new WS connection. */
71
74
  add(ws) {
75
+ if (this.connections.size >= this.maxConnections) {
76
+ ws.close?.();
77
+ return;
78
+ }
72
79
  this.connections.set(ws, /* @__PURE__ */ new Set());
73
80
  }
74
81
  /** Remove a WS connection and all its subscriptions. */
@@ -84,15 +91,16 @@ var ConnectionManager = class {
84
91
  }
85
92
  this.connections.delete(ws);
86
93
  }
87
- /** Subscribe a connection to a channel. */
94
+ /** Subscribe a connection to a channel. No-op if the connection was not added. */
88
95
  subscribe(ws, channel) {
96
+ if (!this.connections.has(ws)) return;
89
97
  let subs = this.channels.get(channel);
90
98
  if (!subs) {
91
99
  subs = /* @__PURE__ */ new Set();
92
100
  this.channels.set(channel, subs);
93
101
  }
94
102
  subs.add(ws);
95
- this.connections.get(ws)?.add(channel);
103
+ this.connections.get(ws).add(channel);
96
104
  }
97
105
  /** Unsubscribe a connection from a channel. */
98
106
  unsubscribe(ws, channel) {
@@ -133,6 +141,14 @@ var ConnectionManager = class {
133
141
  }
134
142
  }
135
143
  }
144
+ /** Close all connections and clear all state. Used during shutdown. */
145
+ closeAll() {
146
+ for (const ws of this.connections.keys()) {
147
+ ws.close?.();
148
+ }
149
+ this.connections.clear();
150
+ this.channels.clear();
151
+ }
136
152
  /** Get the number of active connections. */
137
153
  get connectionCount() {
138
154
  return this.connections.size;
@@ -143,6 +159,52 @@ var ConnectionManager = class {
143
159
  }
144
160
  };
145
161
 
162
+ // src/server/ws/protocol.ts
163
+ var VALID_CHANNEL_PREFIXES = ["execution:", "trace:"];
164
+ var VALID_EXACT_CHANNELS = ["costs", "decisions"];
165
+ var MAX_CHANNEL_LENGTH = 256;
166
+ function handleWsMessage(raw, socket, connMgr) {
167
+ if (raw.length > 65536) {
168
+ return JSON.stringify({ type: "error", message: "Message too large" });
169
+ }
170
+ let msg;
171
+ try {
172
+ msg = JSON.parse(raw);
173
+ } catch {
174
+ return JSON.stringify({ type: "error", message: "Invalid JSON" });
175
+ }
176
+ switch (msg.type) {
177
+ case "subscribe": {
178
+ const error = validateChannel(msg.channel);
179
+ if (error) return JSON.stringify({ type: "error", message: error });
180
+ connMgr.subscribe(socket, msg.channel);
181
+ return JSON.stringify({ type: "subscribed", channel: msg.channel });
182
+ }
183
+ case "unsubscribe": {
184
+ const error = validateChannel(msg.channel);
185
+ if (error) return JSON.stringify({ type: "error", message: error });
186
+ connMgr.unsubscribe(socket, msg.channel);
187
+ return JSON.stringify({ type: "unsubscribed", channel: msg.channel });
188
+ }
189
+ case "ping":
190
+ return JSON.stringify({ type: "pong" });
191
+ default:
192
+ return JSON.stringify({ type: "error", message: "Unknown message type" });
193
+ }
194
+ }
195
+ function validateChannel(channel) {
196
+ if (typeof channel !== "string" || !channel) {
197
+ return "Missing or invalid channel";
198
+ }
199
+ if (channel.length > MAX_CHANNEL_LENGTH) {
200
+ return `Channel name exceeds ${MAX_CHANNEL_LENGTH} characters`;
201
+ }
202
+ if (!VALID_EXACT_CHANNELS.includes(channel) && !VALID_CHANNEL_PREFIXES.some((p) => channel.startsWith(p))) {
203
+ return `Invalid channel: ${channel}`;
204
+ }
205
+ return null;
206
+ }
207
+
146
208
  // src/server/ws/handler.ts
147
209
  function createWsHandlers(connMgr) {
148
210
  return {
@@ -150,37 +212,8 @@ function createWsHandlers(connMgr) {
150
212
  connMgr.add(ws);
151
213
  },
152
214
  onMessage(event, ws) {
153
- let msg;
154
- try {
155
- msg = JSON.parse(String(event.data));
156
- } catch {
157
- const err = { type: "error", message: "Invalid JSON" };
158
- ws.send(JSON.stringify(err));
159
- return;
160
- }
161
- switch (msg.type) {
162
- case "subscribe": {
163
- connMgr.subscribe(ws, msg.channel);
164
- const reply = { type: "subscribed", channel: msg.channel };
165
- ws.send(JSON.stringify(reply));
166
- break;
167
- }
168
- case "unsubscribe": {
169
- connMgr.unsubscribe(ws, msg.channel);
170
- const reply = { type: "unsubscribed", channel: msg.channel };
171
- ws.send(JSON.stringify(reply));
172
- break;
173
- }
174
- case "ping": {
175
- const reply = { type: "pong" };
176
- ws.send(JSON.stringify(reply));
177
- break;
178
- }
179
- default: {
180
- const err = { type: "error", message: `Unknown message type` };
181
- ws.send(JSON.stringify(err));
182
- }
183
- }
215
+ const reply = handleWsMessage(String(event.data), ws, connMgr);
216
+ if (reply) ws.send(reply);
184
217
  },
185
218
  onClose(_event, ws) {
186
219
  connMgr.remove(ws);
@@ -275,8 +308,8 @@ var health_default = app;
275
308
  var import_hono2 = require("hono");
276
309
  var import_axl = require("@axlsdk/axl");
277
310
  function createWorkflowRoutes(connMgr) {
278
- const app8 = new import_hono2.Hono();
279
- app8.get("/workflows", (c) => {
311
+ const app7 = new import_hono2.Hono();
312
+ app7.get("/workflows", (c) => {
280
313
  const runtime = c.get("runtime");
281
314
  const workflows = runtime.getWorkflows().map((w) => ({
282
315
  name: w.name,
@@ -285,7 +318,7 @@ function createWorkflowRoutes(connMgr) {
285
318
  }));
286
319
  return c.json({ ok: true, data: workflows });
287
320
  });
288
- app8.get("/workflows/:name", (c) => {
321
+ app7.get("/workflows/:name", (c) => {
289
322
  const runtime = c.get("runtime");
290
323
  const name = c.req.param("name");
291
324
  const workflow = runtime.getWorkflow(name);
@@ -304,7 +337,7 @@ function createWorkflowRoutes(connMgr) {
304
337
  }
305
338
  });
306
339
  });
307
- app8.post("/workflows/:name/execute", async (c) => {
340
+ app7.post("/workflows/:name/execute", async (c) => {
308
341
  const runtime = c.get("runtime");
309
342
  const name = c.req.param("name");
310
343
  const workflow = runtime.getWorkflow(name);
@@ -335,7 +368,7 @@ function createWorkflowRoutes(connMgr) {
335
368
  const result = await runtime.execute(name, body.input ?? {}, { metadata: body.metadata });
336
369
  return c.json({ ok: true, data: { result } });
337
370
  });
338
- return app8;
371
+ return app7;
339
372
  }
340
373
 
341
374
  // src/server/routes/executions.ts
@@ -369,8 +402,8 @@ var executions_default = app2;
369
402
  // src/server/routes/sessions.ts
370
403
  var import_hono4 = require("hono");
371
404
  function createSessionRoutes(connMgr) {
372
- const app8 = new import_hono4.Hono();
373
- app8.get("/sessions", async (c) => {
405
+ const app7 = new import_hono4.Hono();
406
+ app7.get("/sessions", async (c) => {
374
407
  const runtime = c.get("runtime");
375
408
  const store = runtime.getStateStore();
376
409
  if (!store.listSessions) {
@@ -384,7 +417,7 @@ function createSessionRoutes(connMgr) {
384
417
  }
385
418
  return c.json({ ok: true, data: sessions });
386
419
  });
387
- app8.get("/sessions/:id", async (c) => {
420
+ app7.get("/sessions/:id", async (c) => {
388
421
  const runtime = c.get("runtime");
389
422
  const store = runtime.getStateStore();
390
423
  const id = c.req.param("id");
@@ -392,7 +425,7 @@ function createSessionRoutes(connMgr) {
392
425
  const handoffHistory = await store.getSessionMeta(id, "handoffHistory");
393
426
  return c.json({ ok: true, data: { id, history, handoffHistory: handoffHistory ?? [] } });
394
427
  });
395
- app8.post("/sessions/:id/send", async (c) => {
428
+ app7.post("/sessions/:id/send", async (c) => {
396
429
  const runtime = c.get("runtime");
397
430
  const id = c.req.param("id");
398
431
  const body = await c.req.json();
@@ -400,7 +433,7 @@ function createSessionRoutes(connMgr) {
400
433
  const result = await session.send(body.workflow, body.message);
401
434
  return c.json({ ok: true, data: { result } });
402
435
  });
403
- app8.post("/sessions/:id/stream", async (c) => {
436
+ app7.post("/sessions/:id/stream", async (c) => {
404
437
  const runtime = c.get("runtime");
405
438
  const id = c.req.param("id");
406
439
  const body = await c.req.json();
@@ -421,14 +454,14 @@ function createSessionRoutes(connMgr) {
421
454
  })();
422
455
  return c.json({ ok: true, data: { executionId, streaming: true } });
423
456
  });
424
- app8.delete("/sessions/:id", async (c) => {
457
+ app7.delete("/sessions/:id", async (c) => {
425
458
  const runtime = c.get("runtime");
426
459
  const store = runtime.getStateStore();
427
460
  const id = c.req.param("id");
428
461
  await store.deleteSession(id);
429
462
  return c.json({ ok: true, data: { deleted: true } });
430
463
  });
431
- return app8;
464
+ return app7;
432
465
  }
433
466
 
434
467
  // src/server/routes/agents.ts
@@ -661,61 +694,65 @@ var decisions_default = app6;
661
694
  // src/server/routes/costs.ts
662
695
  var import_hono9 = require("hono");
663
696
  function createCostRoutes(costAggregator) {
664
- const app8 = new import_hono9.Hono();
665
- app8.get("/costs", (c) => {
697
+ const app7 = new import_hono9.Hono();
698
+ app7.get("/costs", (c) => {
666
699
  return c.json({ ok: true, data: costAggregator.getData() });
667
700
  });
668
- app8.post("/costs/reset", (c) => {
701
+ app7.post("/costs/reset", (c) => {
669
702
  costAggregator.reset();
670
703
  return c.json({ ok: true, data: { reset: true } });
671
704
  });
672
- return app8;
705
+ return app7;
673
706
  }
674
707
 
675
708
  // src/server/routes/evals.ts
676
709
  var import_hono10 = require("hono");
677
- var app7 = new import_hono10.Hono();
678
- app7.get("/evals", async (c) => {
679
- const runtime = c.get("runtime");
680
- const evals = runtime.getRegisteredEvals();
681
- return c.json({ ok: true, data: evals });
682
- });
683
- app7.post("/evals/:name/run", async (c) => {
684
- const runtime = c.get("runtime");
685
- const name = c.req.param("name");
686
- const entry = runtime.getRegisteredEval(name);
687
- if (!entry) {
688
- return c.json(
689
- { ok: false, error: { code: "NOT_FOUND", message: `Eval "${name}" not found` } },
690
- 404
691
- );
692
- }
693
- try {
694
- const result = await runtime.runRegisteredEval(name);
695
- return c.json({ ok: true, data: result });
696
- } catch (err) {
697
- const message = err instanceof Error ? err.message : String(err);
698
- return c.json({ ok: false, error: { code: "EVAL_ERROR", message } }, 400);
699
- }
700
- });
701
- app7.post("/evals/compare", async (c) => {
702
- const runtime = c.get("runtime");
703
- const body = await c.req.json();
704
- try {
705
- const result = await runtime.evalCompare(body.baseline, body.candidate);
706
- return c.json({ ok: true, data: result });
707
- } catch (err) {
708
- const message = err instanceof Error ? err.message : String(err);
709
- return c.json({ ok: false, error: { code: "EVAL_ERROR", message } }, 400);
710
- }
711
- });
712
- var evals_default = app7;
710
+ function createEvalRoutes(evalLoader) {
711
+ const app7 = new import_hono10.Hono();
712
+ app7.get("/evals", async (c) => {
713
+ if (evalLoader) await evalLoader();
714
+ const runtime = c.get("runtime");
715
+ const evals = runtime.getRegisteredEvals();
716
+ return c.json({ ok: true, data: evals });
717
+ });
718
+ app7.post("/evals/:name/run", async (c) => {
719
+ if (evalLoader) await evalLoader();
720
+ const runtime = c.get("runtime");
721
+ const name = c.req.param("name");
722
+ const entry = runtime.getRegisteredEval(name);
723
+ if (!entry) {
724
+ return c.json(
725
+ { ok: false, error: { code: "NOT_FOUND", message: `Eval "${name}" not found` } },
726
+ 404
727
+ );
728
+ }
729
+ try {
730
+ const result = await runtime.runRegisteredEval(name);
731
+ return c.json({ ok: true, data: result });
732
+ } catch (err) {
733
+ const message = err instanceof Error ? err.message : String(err);
734
+ return c.json({ ok: false, error: { code: "EVAL_ERROR", message } }, 400);
735
+ }
736
+ });
737
+ app7.post("/evals/compare", async (c) => {
738
+ const runtime = c.get("runtime");
739
+ const body = await c.req.json();
740
+ try {
741
+ const result = await runtime.evalCompare(body.baseline, body.candidate);
742
+ return c.json({ ok: true, data: result });
743
+ } catch (err) {
744
+ const message = err instanceof Error ? err.message : String(err);
745
+ return c.json({ ok: false, error: { code: "EVAL_ERROR", message } }, 400);
746
+ }
747
+ });
748
+ return app7;
749
+ }
713
750
 
714
751
  // src/server/routes/playground.ts
715
752
  var import_hono11 = require("hono");
716
753
  function createPlaygroundRoutes(connMgr) {
717
- const app8 = new import_hono11.Hono();
718
- app8.post("/playground/chat", async (c) => {
754
+ const app7 = new import_hono11.Hono();
755
+ app7.post("/playground/chat", async (c) => {
719
756
  const runtime = c.get("runtime");
720
757
  const body = await c.req.json();
721
758
  const workflowName = body.workflow ?? runtime.getWorkflowNames()[0];
@@ -746,21 +783,53 @@ function createPlaygroundRoutes(connMgr) {
746
783
  data: { sessionId, executionId, streaming: true }
747
784
  });
748
785
  });
749
- return app8;
786
+ return app7;
750
787
  }
751
788
 
752
789
  // src/server/index.ts
753
790
  function createServer(options) {
754
- const { runtime, staticRoot } = options;
755
- const app8 = new import_hono12.Hono();
791
+ const { runtime, staticRoot, basePath = "", readOnly = false } = options;
792
+ const app7 = new import_hono12.Hono();
756
793
  const connMgr = new ConnectionManager();
757
794
  const costAggregator = new CostAggregator(connMgr);
758
- app8.use("*", (0, import_cors.cors)());
759
- app8.use("*", errorHandler);
760
- app8.use("*", async (c, next) => {
795
+ if (options.cors !== false) {
796
+ app7.use("*", (0, import_cors.cors)());
797
+ }
798
+ app7.use("*", errorHandler);
799
+ app7.use("*", async (c, next) => {
761
800
  c.set("runtime", runtime);
762
801
  await next();
763
802
  });
803
+ if (readOnly) {
804
+ const blocked = [
805
+ "POST /api/workflows",
806
+ "POST /api/executions",
807
+ "POST /api/sessions",
808
+ "DELETE /api/sessions",
809
+ "PUT /api/memory",
810
+ "DELETE /api/memory",
811
+ "POST /api/decisions",
812
+ "POST /api/costs",
813
+ "POST /api/tools",
814
+ "POST /api/evals",
815
+ "POST /api/playground"
816
+ ];
817
+ app7.use("/api/*", async (c, next) => {
818
+ const apiIdx = c.req.path.indexOf("/api/");
819
+ const apiPath = apiIdx >= 0 ? c.req.path.slice(apiIdx) : c.req.path;
820
+ const key = `${c.req.method} ${apiPath}`;
821
+ if (blocked.some((b) => key.startsWith(b))) {
822
+ return c.json(
823
+ {
824
+ ok: false,
825
+ error: { code: "READ_ONLY", message: "Studio is mounted in read-only mode" }
826
+ },
827
+ 405
828
+ );
829
+ }
830
+ await next();
831
+ });
832
+ }
764
833
  const api = new import_hono12.Hono();
765
834
  api.route("/", health_default);
766
835
  api.route("/", createWorkflowRoutes(connMgr));
@@ -771,10 +840,10 @@ function createServer(options) {
771
840
  api.route("/", memory_default);
772
841
  api.route("/", decisions_default);
773
842
  api.route("/", createCostRoutes(costAggregator));
774
- api.route("/", evals_default);
843
+ api.route("/", createEvalRoutes(options.evalLoader));
775
844
  api.route("/", createPlaygroundRoutes(connMgr));
776
- app8.route("/api", api);
777
- runtime.on("trace", (event) => {
845
+ app7.route("/api", api);
846
+ const traceListener = (event) => {
778
847
  const traceEvent = event;
779
848
  if (traceEvent.executionId) {
780
849
  connMgr.broadcastWithWildcard(`trace:${traceEvent.executionId}`, traceEvent);
@@ -783,12 +852,47 @@ function createServer(options) {
783
852
  if (traceEvent.type === "await_human") {
784
853
  connMgr.broadcast("decisions", traceEvent);
785
854
  }
786
- });
855
+ };
856
+ runtime.on("trace", traceListener);
787
857
  if (staticRoot) {
788
- app8.use("/*", (0, import_serve_static.serveStatic)({ root: staticRoot }));
789
- app8.get("*", (0, import_serve_static.serveStatic)({ root: staticRoot, path: "/index.html" }));
858
+ app7.use(
859
+ "/*",
860
+ (0, import_serve_static.serveStatic)({
861
+ root: staticRoot,
862
+ rewriteRequestPath: basePath ? (path) => path.startsWith(basePath) ? path.slice(basePath.length) || "/" : path : void 0
863
+ })
864
+ );
865
+ if (basePath) {
866
+ const indexPath = (0, import_node_path.resolve)(staticRoot, "index.html");
867
+ if (!(0, import_node_fs.existsSync)(indexPath)) {
868
+ console.warn(`[axl-studio] index.html not found at ${indexPath}`);
869
+ } else {
870
+ const indexHtml = (0, import_node_fs.readFileSync)(indexPath, "utf-8");
871
+ const safeBasePath = JSON.stringify(basePath).replace(/</g, "\\u003c");
872
+ const injectedHtml = indexHtml.replace(
873
+ "</head>",
874
+ `<base href="${basePath}/">
875
+ <script>window.__AXL_STUDIO_BASE__=${safeBasePath}</script>
876
+ </head>`
877
+ );
878
+ if (injectedHtml === indexHtml) {
879
+ console.warn(
880
+ "[axl-studio] Could not inject basePath into index.html \u2014 </head> tag not found. The SPA may not route correctly."
881
+ );
882
+ }
883
+ app7.get("*", (c) => c.html(injectedHtml));
884
+ }
885
+ } else {
886
+ app7.get("*", (0, import_serve_static.serveStatic)({ root: staticRoot, path: "/index.html" }));
887
+ }
790
888
  }
791
- return { app: app8, connMgr, costAggregator, createWsHandlers: () => createWsHandlers(connMgr) };
889
+ return {
890
+ app: app7,
891
+ connMgr,
892
+ costAggregator,
893
+ createWsHandlers: () => createWsHandlers(connMgr),
894
+ traceListener
895
+ };
792
896
  }
793
897
 
794
898
  // src/resolve-runtime.ts
@@ -798,8 +902,8 @@ function resolveRuntime(mod) {
798
902
  }
799
903
 
800
904
  // src/cli-utils.ts
801
- var import_node_path = require("path");
802
- var import_node_fs = require("fs");
905
+ var import_node_path2 = require("path");
906
+ var import_node_fs2 = require("fs");
803
907
  var CONFIG_CANDIDATES = [
804
908
  "axl.config.mts",
805
909
  "axl.config.ts",
@@ -808,8 +912,8 @@ var CONFIG_CANDIDATES = [
808
912
  ];
809
913
  function findConfig(cwd) {
810
914
  for (const name of CONFIG_CANDIDATES) {
811
- const p = (0, import_node_path.resolve)(cwd, name);
812
- if ((0, import_node_fs.existsSync)(p)) return p;
915
+ const p = (0, import_node_path2.resolve)(cwd, name);
916
+ if ((0, import_node_fs2.existsSync)(p)) return p;
813
917
  }
814
918
  return void 0;
815
919
  }
@@ -843,7 +947,7 @@ function parseArgs(argv) {
843
947
  return result;
844
948
  }
845
949
  function needsEsmForcing(configPath) {
846
- const ext = (0, import_node_path.extname)(configPath);
950
+ const ext = (0, import_node_path2.extname)(configPath);
847
951
  return ext === ".ts" || ext === ".tsx";
848
952
  }
849
953
  function needsTsxLoader(configPath) {
@@ -881,8 +985,8 @@ Tip: Use .mts for configs with top-level await or in projects without "type": "m
881
985
  }
882
986
  let configPath;
883
987
  if (args.config) {
884
- configPath = (0, import_node_path2.resolve)(process.cwd(), args.config);
885
- if (!(0, import_node_fs2.existsSync)(configPath)) {
988
+ configPath = (0, import_node_path3.resolve)(process.cwd(), args.config);
989
+ if (!(0, import_node_fs3.existsSync)(configPath)) {
886
990
  console.error(`Config file not found: ${configPath}`);
887
991
  process.exit(1);
888
992
  }
@@ -950,7 +1054,7 @@ Tip: Use .mts for configs with top-level await or in projects without "type": "m
950
1054
  }
951
1055
  console.log(`[axl-studio] Loading config from ${configPath}`);
952
1056
  let runtime;
953
- const ext = (0, import_node_path2.extname)(configPath);
1057
+ const ext = (0, import_node_path3.extname)(configPath);
954
1058
  try {
955
1059
  const mod = await import((0, import_node_url.pathToFileURL)(configPath).href);
956
1060
  runtime = resolveRuntime(mod);
@@ -987,21 +1091,21 @@ Tip: Use .mts for configs with top-level await or in projects without "type": "m
987
1091
  console.error(`Failed to load config:`, err);
988
1092
  process.exit(1);
989
1093
  }
990
- const staticRoot = (0, import_node_path2.resolve)(import_meta.dirname ?? __dirname, "client");
991
- const hasStaticAssets = (0, import_node_fs2.existsSync)((0, import_node_path2.resolve)(staticRoot, "index.html"));
992
- const { app: app8, createWsHandlers: createWsHandlers2 } = createServer({
1094
+ const staticRoot = (0, import_node_path3.resolve)(import_meta.dirname ?? __dirname, "client");
1095
+ const hasStaticAssets = (0, import_node_fs3.existsSync)((0, import_node_path3.resolve)(staticRoot, "index.html"));
1096
+ const { app: app7, createWsHandlers: createWsHandlers2 } = createServer({
993
1097
  runtime,
994
1098
  staticRoot: hasStaticAssets ? staticRoot : void 0
995
1099
  });
996
- const { injectWebSocket, upgradeWebSocket } = (0, import_node_ws.createNodeWebSocket)({ app: app8 });
1100
+ const { injectWebSocket, upgradeWebSocket } = (0, import_node_ws.createNodeWebSocket)({ app: app7 });
997
1101
  const wsHandlers = createWsHandlers2();
998
- app8.get(
1102
+ app7.get(
999
1103
  "/ws",
1000
1104
  upgradeWebSocket(() => wsHandlers)
1001
1105
  );
1002
1106
  const server = (0, import_node_server.serve)(
1003
1107
  {
1004
- fetch: app8.fetch,
1108
+ fetch: app7.fetch,
1005
1109
  port: args.port
1006
1110
  },
1007
1111
  (info) => {