@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/README.md +225 -7
- package/dist/{chunk-EG74VI3M.js → chunk-GKIPF45K.js} +206 -101
- package/dist/chunk-GKIPF45K.js.map +1 -0
- package/dist/cli.cjs +220 -116
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/client/assets/{index-DDlRZgfC.js → index-jeUeToM_.js} +13 -13
- package/dist/client/index.html +2 -2
- package/dist/connection-manager-DbOgO_gK.d.cts +75 -0
- package/dist/connection-manager-DbOgO_gK.d.ts +75 -0
- package/dist/middleware.cjs +1243 -0
- package/dist/middleware.cjs.map +1 -0
- package/dist/middleware.d.cts +131 -0
- package/dist/middleware.d.ts +131 -0
- package/dist/middleware.js +346 -0
- package/dist/middleware.js.map +1 -0
- package/dist/server/index.cjs +204 -100
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +12 -62
- package/dist/server/index.d.ts +12 -62
- package/dist/server/index.js +1 -1
- package/package.json +16 -4
- package/dist/chunk-EG74VI3M.js.map +0 -1
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
|
|
28
|
-
var
|
|
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)
|
|
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
|
-
|
|
154
|
-
|
|
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
|
|
279
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
373
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
665
|
-
|
|
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
|
-
|
|
701
|
+
app7.post("/costs/reset", (c) => {
|
|
669
702
|
costAggregator.reset();
|
|
670
703
|
return c.json({ ok: true, data: { reset: true } });
|
|
671
704
|
});
|
|
672
|
-
return
|
|
705
|
+
return app7;
|
|
673
706
|
}
|
|
674
707
|
|
|
675
708
|
// src/server/routes/evals.ts
|
|
676
709
|
var import_hono10 = require("hono");
|
|
677
|
-
|
|
678
|
-
app7
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
const
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
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
|
|
718
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
759
|
-
|
|
760
|
-
|
|
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("/",
|
|
843
|
+
api.route("/", createEvalRoutes(options.evalLoader));
|
|
775
844
|
api.route("/", createPlaygroundRoutes(connMgr));
|
|
776
|
-
|
|
777
|
-
|
|
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
|
-
|
|
789
|
-
|
|
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 {
|
|
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
|
|
802
|
-
var
|
|
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,
|
|
812
|
-
if ((0,
|
|
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,
|
|
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,
|
|
885
|
-
if (!(0,
|
|
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,
|
|
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,
|
|
991
|
-
const hasStaticAssets = (0,
|
|
992
|
-
const { app:
|
|
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:
|
|
1100
|
+
const { injectWebSocket, upgradeWebSocket } = (0, import_node_ws.createNodeWebSocket)({ app: app7 });
|
|
997
1101
|
const wsHandlers = createWsHandlers2();
|
|
998
|
-
|
|
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:
|
|
1108
|
+
fetch: app7.fetch,
|
|
1005
1109
|
port: args.port
|
|
1006
1110
|
},
|
|
1007
1111
|
(info) => {
|