@axlsdk/studio 0.13.8 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +122 -11
- package/dist/chunk-IPDMFFTQ.js +2142 -0
- package/dist/chunk-IPDMFFTQ.js.map +1 -0
- package/dist/{chunk-6VDX5CRP.js → chunk-JGQ3MSIG.js} +5 -2
- package/dist/chunk-JGQ3MSIG.js.map +1 -0
- package/dist/cli.cjs +1336 -209
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +8 -3
- package/dist/cli.js.map +1 -1
- package/dist/client/assets/index-CLKKOaE2.css +1 -0
- package/dist/client/assets/index-rvds50cZ.js +278 -0
- package/dist/client/index.html +2 -2
- package/dist/{connection-manager-B7AWpsCD.d.cts → connection-manager-BMPahDuY.d.cts} +63 -1
- package/dist/{connection-manager-B7AWpsCD.d.ts → connection-manager-BMPahDuY.d.ts} +63 -1
- package/dist/middleware.cjs +1353 -211
- package/dist/middleware.cjs.map +1 -1
- package/dist/middleware.d.cts +52 -5
- package/dist/middleware.d.ts +52 -5
- package/dist/middleware.js +31 -8
- package/dist/middleware.js.map +1 -1
- package/dist/server/index.cjs +1325 -202
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +165 -28
- package/dist/server/index.d.ts +165 -28
- package/dist/server/index.js +7 -3
- package/package.json +11 -6
- package/dist/chunk-6VDX5CRP.js.map +0 -1
- package/dist/chunk-YWRYXT7U.js +0 -1021
- package/dist/chunk-YWRYXT7U.js.map +0 -1
- package/dist/client/assets/index-C_uwupnn.js +0 -221
- package/dist/client/assets/index-DVcH6P9w.css +0 -1
package/dist/chunk-YWRYXT7U.js
DELETED
|
@@ -1,1021 +0,0 @@
|
|
|
1
|
-
// src/server/index.ts
|
|
2
|
-
import { existsSync, readFileSync } from "fs";
|
|
3
|
-
import { resolve } from "path";
|
|
4
|
-
import { Hono as Hono12 } from "hono";
|
|
5
|
-
import { cors } from "hono/cors";
|
|
6
|
-
import { serveStatic } from "@hono/node-server/serve-static";
|
|
7
|
-
|
|
8
|
-
// src/server/middleware/error-handler.ts
|
|
9
|
-
async function errorHandler(c, next) {
|
|
10
|
-
try {
|
|
11
|
-
await next();
|
|
12
|
-
} catch (err) {
|
|
13
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
14
|
-
const code = err.code ?? "INTERNAL_ERROR";
|
|
15
|
-
let status = 500;
|
|
16
|
-
if ("status" in err) {
|
|
17
|
-
const errStatus = err.status;
|
|
18
|
-
if (typeof errStatus === "number" && errStatus >= 400 && errStatus < 600) {
|
|
19
|
-
status = errStatus;
|
|
20
|
-
}
|
|
21
|
-
} else if (code === "NOT_FOUND" || message.includes("not found") || message.includes("not registered")) {
|
|
22
|
-
status = 404;
|
|
23
|
-
} else if (code === "VALIDATION_ERROR" || message.includes("Expected") || message.includes("invalid")) {
|
|
24
|
-
status = 400;
|
|
25
|
-
}
|
|
26
|
-
const body = {
|
|
27
|
-
ok: false,
|
|
28
|
-
error: { code, message }
|
|
29
|
-
};
|
|
30
|
-
return c.json(body, status);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// src/server/ws/connection-manager.ts
|
|
35
|
-
function isBufferedChannel(channel) {
|
|
36
|
-
return channel.startsWith("execution:");
|
|
37
|
-
}
|
|
38
|
-
var BUFFER_TTL_MS = 3e4;
|
|
39
|
-
var MAX_BUFFER_EVENTS = 500;
|
|
40
|
-
var ConnectionManager = class {
|
|
41
|
-
/** channel -> set of WS connections */
|
|
42
|
-
channels = /* @__PURE__ */ new Map();
|
|
43
|
-
/** ws -> set of subscribed channels (for cleanup) */
|
|
44
|
-
connections = /* @__PURE__ */ new Map();
|
|
45
|
-
/** channel -> replay buffer for execution streams */
|
|
46
|
-
buffers = /* @__PURE__ */ new Map();
|
|
47
|
-
maxConnections = 100;
|
|
48
|
-
/** Register a new WS connection. */
|
|
49
|
-
add(ws) {
|
|
50
|
-
if (this.connections.size >= this.maxConnections) {
|
|
51
|
-
ws.close?.();
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
this.connections.set(ws, /* @__PURE__ */ new Set());
|
|
55
|
-
}
|
|
56
|
-
/** Remove a WS connection and all its subscriptions. */
|
|
57
|
-
remove(ws) {
|
|
58
|
-
const channels = this.connections.get(ws);
|
|
59
|
-
if (channels) {
|
|
60
|
-
for (const ch of channels) {
|
|
61
|
-
this.channels.get(ch)?.delete(ws);
|
|
62
|
-
if (this.channels.get(ch)?.size === 0) {
|
|
63
|
-
this.channels.delete(ch);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
this.connections.delete(ws);
|
|
68
|
-
}
|
|
69
|
-
/** Subscribe a connection to a channel. Replays buffered events for execution channels. */
|
|
70
|
-
subscribe(ws, channel) {
|
|
71
|
-
if (!this.connections.has(ws)) return;
|
|
72
|
-
let subs = this.channels.get(channel);
|
|
73
|
-
if (!subs) {
|
|
74
|
-
subs = /* @__PURE__ */ new Set();
|
|
75
|
-
this.channels.set(channel, subs);
|
|
76
|
-
}
|
|
77
|
-
subs.add(ws);
|
|
78
|
-
this.connections.get(ws).add(channel);
|
|
79
|
-
const buffer = this.buffers.get(channel);
|
|
80
|
-
if (buffer) {
|
|
81
|
-
for (const msg of buffer.events) {
|
|
82
|
-
try {
|
|
83
|
-
ws.send(msg);
|
|
84
|
-
} catch {
|
|
85
|
-
this.remove(ws);
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
/** Unsubscribe a connection from a channel. */
|
|
92
|
-
unsubscribe(ws, channel) {
|
|
93
|
-
this.channels.get(channel)?.delete(ws);
|
|
94
|
-
if (this.channels.get(channel)?.size === 0) {
|
|
95
|
-
this.channels.delete(channel);
|
|
96
|
-
}
|
|
97
|
-
this.connections.get(ws)?.delete(channel);
|
|
98
|
-
}
|
|
99
|
-
/** Broadcast data to all subscribers of a channel. Buffers events for execution channels. */
|
|
100
|
-
broadcast(channel, data) {
|
|
101
|
-
const msg = JSON.stringify({ type: "event", channel, data });
|
|
102
|
-
if (isBufferedChannel(channel)) {
|
|
103
|
-
let buffer = this.buffers.get(channel);
|
|
104
|
-
if (!buffer) {
|
|
105
|
-
buffer = { events: [], complete: false };
|
|
106
|
-
this.buffers.set(channel, buffer);
|
|
107
|
-
}
|
|
108
|
-
const event = data;
|
|
109
|
-
const isTerminal = event.type === "done" || event.type === "error";
|
|
110
|
-
if (buffer.events.length < MAX_BUFFER_EVENTS || isTerminal) {
|
|
111
|
-
buffer.events.push(msg);
|
|
112
|
-
}
|
|
113
|
-
if (isTerminal) {
|
|
114
|
-
buffer.complete = true;
|
|
115
|
-
if (buffer.timer) clearTimeout(buffer.timer);
|
|
116
|
-
buffer.timer = setTimeout(() => {
|
|
117
|
-
this.buffers.delete(channel);
|
|
118
|
-
}, BUFFER_TTL_MS);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
const subs = this.channels.get(channel);
|
|
122
|
-
if (!subs || subs.size === 0) return;
|
|
123
|
-
for (const ws of [...subs]) {
|
|
124
|
-
try {
|
|
125
|
-
ws.send(msg);
|
|
126
|
-
} catch {
|
|
127
|
-
this.remove(ws);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
/** Broadcast to channel and all wildcard subscribers (e.g., trace:* matches trace:abc). */
|
|
132
|
-
broadcastWithWildcard(channel, data) {
|
|
133
|
-
this.broadcast(channel, data);
|
|
134
|
-
const colonIdx = channel.indexOf(":");
|
|
135
|
-
if (colonIdx > 0) {
|
|
136
|
-
const wildcardChannel = channel.substring(0, colonIdx) + ":*";
|
|
137
|
-
const subs = this.channels.get(wildcardChannel);
|
|
138
|
-
if (!subs || subs.size === 0) return;
|
|
139
|
-
const msg = JSON.stringify({ type: "event", channel, data });
|
|
140
|
-
for (const ws of [...subs]) {
|
|
141
|
-
try {
|
|
142
|
-
ws.send(msg);
|
|
143
|
-
} catch {
|
|
144
|
-
this.remove(ws);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
/** Close all connections, clear all state and buffers. Used during shutdown. */
|
|
150
|
-
closeAll() {
|
|
151
|
-
for (const ws of this.connections.keys()) {
|
|
152
|
-
ws.close?.();
|
|
153
|
-
}
|
|
154
|
-
for (const buffer of this.buffers.values()) {
|
|
155
|
-
if (buffer.timer) clearTimeout(buffer.timer);
|
|
156
|
-
}
|
|
157
|
-
this.connections.clear();
|
|
158
|
-
this.channels.clear();
|
|
159
|
-
this.buffers.clear();
|
|
160
|
-
}
|
|
161
|
-
/** Get the number of active connections. */
|
|
162
|
-
get connectionCount() {
|
|
163
|
-
return this.connections.size;
|
|
164
|
-
}
|
|
165
|
-
/** Check if any connections are subscribed to a channel. */
|
|
166
|
-
hasSubscribers(channel) {
|
|
167
|
-
return (this.channels.get(channel)?.size ?? 0) > 0;
|
|
168
|
-
}
|
|
169
|
-
};
|
|
170
|
-
|
|
171
|
-
// src/server/ws/protocol.ts
|
|
172
|
-
var VALID_CHANNEL_PREFIXES = ["execution:", "trace:"];
|
|
173
|
-
var VALID_EXACT_CHANNELS = ["costs", "decisions"];
|
|
174
|
-
var MAX_CHANNEL_LENGTH = 256;
|
|
175
|
-
function handleWsMessage(raw, socket, connMgr) {
|
|
176
|
-
if (raw.length > 65536) {
|
|
177
|
-
return JSON.stringify({ type: "error", message: "Message too large" });
|
|
178
|
-
}
|
|
179
|
-
let msg;
|
|
180
|
-
try {
|
|
181
|
-
msg = JSON.parse(raw);
|
|
182
|
-
} catch {
|
|
183
|
-
return JSON.stringify({ type: "error", message: "Invalid JSON" });
|
|
184
|
-
}
|
|
185
|
-
switch (msg.type) {
|
|
186
|
-
case "subscribe": {
|
|
187
|
-
const error = validateChannel(msg.channel);
|
|
188
|
-
if (error) return JSON.stringify({ type: "error", message: error });
|
|
189
|
-
connMgr.subscribe(socket, msg.channel);
|
|
190
|
-
return JSON.stringify({ type: "subscribed", channel: msg.channel });
|
|
191
|
-
}
|
|
192
|
-
case "unsubscribe": {
|
|
193
|
-
const error = validateChannel(msg.channel);
|
|
194
|
-
if (error) return JSON.stringify({ type: "error", message: error });
|
|
195
|
-
connMgr.unsubscribe(socket, msg.channel);
|
|
196
|
-
return JSON.stringify({ type: "unsubscribed", channel: msg.channel });
|
|
197
|
-
}
|
|
198
|
-
case "ping":
|
|
199
|
-
return JSON.stringify({ type: "pong" });
|
|
200
|
-
default:
|
|
201
|
-
return JSON.stringify({ type: "error", message: "Unknown message type" });
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
function validateChannel(channel) {
|
|
205
|
-
if (typeof channel !== "string" || !channel) {
|
|
206
|
-
return "Missing or invalid channel";
|
|
207
|
-
}
|
|
208
|
-
if (channel.length > MAX_CHANNEL_LENGTH) {
|
|
209
|
-
return `Channel name exceeds ${MAX_CHANNEL_LENGTH} characters`;
|
|
210
|
-
}
|
|
211
|
-
if (!VALID_EXACT_CHANNELS.includes(channel) && !VALID_CHANNEL_PREFIXES.some((p) => channel.startsWith(p))) {
|
|
212
|
-
return `Invalid channel: ${channel}`;
|
|
213
|
-
}
|
|
214
|
-
return null;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
// src/server/ws/handler.ts
|
|
218
|
-
function createWsHandlers(connMgr) {
|
|
219
|
-
return {
|
|
220
|
-
onOpen(_event, ws) {
|
|
221
|
-
connMgr.add(ws);
|
|
222
|
-
},
|
|
223
|
-
onMessage(event, ws) {
|
|
224
|
-
const reply = handleWsMessage(String(event.data), ws, connMgr);
|
|
225
|
-
if (reply) ws.send(reply);
|
|
226
|
-
},
|
|
227
|
-
onClose(_event, ws) {
|
|
228
|
-
connMgr.remove(ws);
|
|
229
|
-
},
|
|
230
|
-
onError(_event, ws) {
|
|
231
|
-
connMgr.remove(ws);
|
|
232
|
-
}
|
|
233
|
-
};
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
// src/server/cost-aggregator.ts
|
|
237
|
-
var CostAggregator = class {
|
|
238
|
-
constructor(connMgr) {
|
|
239
|
-
this.connMgr = connMgr;
|
|
240
|
-
}
|
|
241
|
-
data = {
|
|
242
|
-
totalCost: 0,
|
|
243
|
-
totalTokens: { input: 0, output: 0, reasoning: 0 },
|
|
244
|
-
byAgent: {},
|
|
245
|
-
byModel: {},
|
|
246
|
-
byWorkflow: {}
|
|
247
|
-
};
|
|
248
|
-
/** Process a trace event and update cost data. */
|
|
249
|
-
onTrace(event) {
|
|
250
|
-
if (event.cost == null && !event.tokens) return;
|
|
251
|
-
const cost = Number.isFinite(event.cost) ? event.cost : 0;
|
|
252
|
-
const tokens = event.tokens ?? {};
|
|
253
|
-
this.data.totalCost += cost;
|
|
254
|
-
this.data.totalTokens.input += tokens.input ?? 0;
|
|
255
|
-
this.data.totalTokens.output += tokens.output ?? 0;
|
|
256
|
-
this.data.totalTokens.reasoning += tokens.reasoning ?? 0;
|
|
257
|
-
if (event.agent) {
|
|
258
|
-
const entry = this.data.byAgent[event.agent] ?? { cost: 0, calls: 0 };
|
|
259
|
-
entry.cost += cost;
|
|
260
|
-
entry.calls += 1;
|
|
261
|
-
this.data.byAgent[event.agent] = entry;
|
|
262
|
-
}
|
|
263
|
-
if (event.model) {
|
|
264
|
-
const entry = this.data.byModel[event.model] ?? {
|
|
265
|
-
cost: 0,
|
|
266
|
-
calls: 0,
|
|
267
|
-
tokens: { input: 0, output: 0 }
|
|
268
|
-
};
|
|
269
|
-
entry.cost += cost;
|
|
270
|
-
entry.calls += 1;
|
|
271
|
-
entry.tokens.input += tokens.input ?? 0;
|
|
272
|
-
entry.tokens.output += tokens.output ?? 0;
|
|
273
|
-
this.data.byModel[event.model] = entry;
|
|
274
|
-
}
|
|
275
|
-
if (event.workflow) {
|
|
276
|
-
const entry = this.data.byWorkflow[event.workflow] ?? { cost: 0, executions: 0 };
|
|
277
|
-
entry.cost += cost;
|
|
278
|
-
if (event.type === "workflow_start") entry.executions += 1;
|
|
279
|
-
this.data.byWorkflow[event.workflow] = entry;
|
|
280
|
-
}
|
|
281
|
-
this.connMgr.broadcast("costs", this.data);
|
|
282
|
-
}
|
|
283
|
-
/** Get current aggregated cost data. */
|
|
284
|
-
getData() {
|
|
285
|
-
return this.data;
|
|
286
|
-
}
|
|
287
|
-
/** Reset all accumulated data. */
|
|
288
|
-
reset() {
|
|
289
|
-
this.data = {
|
|
290
|
-
totalCost: 0,
|
|
291
|
-
totalTokens: { input: 0, output: 0, reasoning: 0 },
|
|
292
|
-
byAgent: {},
|
|
293
|
-
byModel: {},
|
|
294
|
-
byWorkflow: {}
|
|
295
|
-
};
|
|
296
|
-
}
|
|
297
|
-
};
|
|
298
|
-
|
|
299
|
-
// src/server/routes/health.ts
|
|
300
|
-
import { Hono } from "hono";
|
|
301
|
-
var app = new Hono();
|
|
302
|
-
app.get("/health", (c) => {
|
|
303
|
-
const runtime = c.get("runtime");
|
|
304
|
-
return c.json({
|
|
305
|
-
ok: true,
|
|
306
|
-
data: {
|
|
307
|
-
status: "healthy",
|
|
308
|
-
workflows: runtime.getWorkflowNames().length,
|
|
309
|
-
agents: runtime.getAgents().length,
|
|
310
|
-
tools: runtime.getTools().length
|
|
311
|
-
}
|
|
312
|
-
});
|
|
313
|
-
});
|
|
314
|
-
var health_default = app;
|
|
315
|
-
|
|
316
|
-
// src/server/routes/workflows.ts
|
|
317
|
-
import { Hono as Hono2 } from "hono";
|
|
318
|
-
import { zodToJsonSchema } from "@axlsdk/axl";
|
|
319
|
-
function createWorkflowRoutes(connMgr) {
|
|
320
|
-
const app7 = new Hono2();
|
|
321
|
-
app7.get("/workflows", (c) => {
|
|
322
|
-
const runtime = c.get("runtime");
|
|
323
|
-
const workflows = runtime.getWorkflows().map((w) => ({
|
|
324
|
-
name: w.name,
|
|
325
|
-
hasInputSchema: !!w.inputSchema,
|
|
326
|
-
hasOutputSchema: !!w.outputSchema
|
|
327
|
-
}));
|
|
328
|
-
return c.json({ ok: true, data: workflows });
|
|
329
|
-
});
|
|
330
|
-
app7.get("/workflows/:name", (c) => {
|
|
331
|
-
const runtime = c.get("runtime");
|
|
332
|
-
const name = c.req.param("name");
|
|
333
|
-
const workflow = runtime.getWorkflow(name);
|
|
334
|
-
if (!workflow) {
|
|
335
|
-
return c.json(
|
|
336
|
-
{ ok: false, error: { code: "NOT_FOUND", message: `Workflow "${name}" not found` } },
|
|
337
|
-
404
|
|
338
|
-
);
|
|
339
|
-
}
|
|
340
|
-
return c.json({
|
|
341
|
-
ok: true,
|
|
342
|
-
data: {
|
|
343
|
-
name: workflow.name,
|
|
344
|
-
inputSchema: workflow.inputSchema ? zodToJsonSchema(workflow.inputSchema) : null,
|
|
345
|
-
outputSchema: workflow.outputSchema ? zodToJsonSchema(workflow.outputSchema) : null
|
|
346
|
-
}
|
|
347
|
-
});
|
|
348
|
-
});
|
|
349
|
-
app7.post("/workflows/:name/execute", async (c) => {
|
|
350
|
-
const runtime = c.get("runtime");
|
|
351
|
-
const name = c.req.param("name");
|
|
352
|
-
const workflow = runtime.getWorkflow(name);
|
|
353
|
-
if (!workflow) {
|
|
354
|
-
return c.json(
|
|
355
|
-
{ ok: false, error: { code: "NOT_FOUND", message: `Workflow "${name}" not found` } },
|
|
356
|
-
404
|
|
357
|
-
);
|
|
358
|
-
}
|
|
359
|
-
const body = await c.req.json();
|
|
360
|
-
if (body.stream) {
|
|
361
|
-
const stream = runtime.stream(name, body.input ?? {}, { metadata: body.metadata });
|
|
362
|
-
const executionId = `stream-${Date.now()}`;
|
|
363
|
-
(async () => {
|
|
364
|
-
for await (const event of stream) {
|
|
365
|
-
connMgr.broadcastWithWildcard(`execution:${executionId}`, event);
|
|
366
|
-
}
|
|
367
|
-
})();
|
|
368
|
-
return c.json({ ok: true, data: { executionId, streaming: true } });
|
|
369
|
-
}
|
|
370
|
-
const result = await runtime.execute(name, body.input ?? {}, { metadata: body.metadata });
|
|
371
|
-
return c.json({ ok: true, data: { result } });
|
|
372
|
-
});
|
|
373
|
-
return app7;
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
// src/server/routes/executions.ts
|
|
377
|
-
import { Hono as Hono3 } from "hono";
|
|
378
|
-
var app2 = new Hono3();
|
|
379
|
-
app2.get("/executions", async (c) => {
|
|
380
|
-
const runtime = c.get("runtime");
|
|
381
|
-
const executions = await runtime.getExecutions();
|
|
382
|
-
return c.json({ ok: true, data: executions });
|
|
383
|
-
});
|
|
384
|
-
app2.get("/executions/:id", async (c) => {
|
|
385
|
-
const runtime = c.get("runtime");
|
|
386
|
-
const id = c.req.param("id");
|
|
387
|
-
const execution = await runtime.getExecution(id);
|
|
388
|
-
if (!execution) {
|
|
389
|
-
return c.json(
|
|
390
|
-
{ ok: false, error: { code: "NOT_FOUND", message: `Execution "${id}" not found` } },
|
|
391
|
-
404
|
|
392
|
-
);
|
|
393
|
-
}
|
|
394
|
-
return c.json({ ok: true, data: execution });
|
|
395
|
-
});
|
|
396
|
-
app2.post("/executions/:id/abort", (c) => {
|
|
397
|
-
const runtime = c.get("runtime");
|
|
398
|
-
const id = c.req.param("id");
|
|
399
|
-
runtime.abort(id);
|
|
400
|
-
return c.json({ ok: true, data: { aborted: true } });
|
|
401
|
-
});
|
|
402
|
-
var executions_default = app2;
|
|
403
|
-
|
|
404
|
-
// src/server/routes/sessions.ts
|
|
405
|
-
import { Hono as Hono4 } from "hono";
|
|
406
|
-
function createSessionRoutes(connMgr) {
|
|
407
|
-
const app7 = new Hono4();
|
|
408
|
-
app7.get("/sessions", async (c) => {
|
|
409
|
-
const runtime = c.get("runtime");
|
|
410
|
-
const store = runtime.getStateStore();
|
|
411
|
-
if (!store.listSessions) {
|
|
412
|
-
return c.json({ ok: true, data: [] });
|
|
413
|
-
}
|
|
414
|
-
const ids = await store.listSessions();
|
|
415
|
-
const sessions = [];
|
|
416
|
-
for (const id of ids) {
|
|
417
|
-
const history = await store.getSession(id);
|
|
418
|
-
sessions.push({ id, messageCount: history.length });
|
|
419
|
-
}
|
|
420
|
-
return c.json({ ok: true, data: sessions });
|
|
421
|
-
});
|
|
422
|
-
app7.get("/sessions/:id", async (c) => {
|
|
423
|
-
const runtime = c.get("runtime");
|
|
424
|
-
const store = runtime.getStateStore();
|
|
425
|
-
const id = c.req.param("id");
|
|
426
|
-
const history = await store.getSession(id);
|
|
427
|
-
const handoffHistory = await store.getSessionMeta(id, "handoffHistory");
|
|
428
|
-
return c.json({ ok: true, data: { id, history, handoffHistory: handoffHistory ?? [] } });
|
|
429
|
-
});
|
|
430
|
-
app7.post("/sessions/:id/send", async (c) => {
|
|
431
|
-
const runtime = c.get("runtime");
|
|
432
|
-
const id = c.req.param("id");
|
|
433
|
-
const body = await c.req.json();
|
|
434
|
-
const session = runtime.session(id);
|
|
435
|
-
const result = await session.send(body.workflow, body.message);
|
|
436
|
-
return c.json({ ok: true, data: { result } });
|
|
437
|
-
});
|
|
438
|
-
app7.post("/sessions/:id/stream", async (c) => {
|
|
439
|
-
const runtime = c.get("runtime");
|
|
440
|
-
const id = c.req.param("id");
|
|
441
|
-
const body = await c.req.json();
|
|
442
|
-
const session = runtime.session(id);
|
|
443
|
-
const stream = await session.stream(body.workflow, body.message);
|
|
444
|
-
const executionId = `session-${id}-${Date.now()}`;
|
|
445
|
-
(async () => {
|
|
446
|
-
for await (const event of stream) {
|
|
447
|
-
connMgr.broadcastWithWildcard(`execution:${executionId}`, event);
|
|
448
|
-
}
|
|
449
|
-
})();
|
|
450
|
-
return c.json({ ok: true, data: { executionId, streaming: true } });
|
|
451
|
-
});
|
|
452
|
-
app7.delete("/sessions/:id", async (c) => {
|
|
453
|
-
const runtime = c.get("runtime");
|
|
454
|
-
const store = runtime.getStateStore();
|
|
455
|
-
const id = c.req.param("id");
|
|
456
|
-
await store.deleteSession(id);
|
|
457
|
-
return c.json({ ok: true, data: { deleted: true } });
|
|
458
|
-
});
|
|
459
|
-
return app7;
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
// src/server/routes/agents.ts
|
|
463
|
-
import { Hono as Hono5 } from "hono";
|
|
464
|
-
import { zodToJsonSchema as zodToJsonSchema2 } from "@axlsdk/axl";
|
|
465
|
-
var app3 = new Hono5();
|
|
466
|
-
app3.get("/agents", (c) => {
|
|
467
|
-
const runtime = c.get("runtime");
|
|
468
|
-
const agents = runtime.getAgents().map((a) => ({
|
|
469
|
-
name: a._name,
|
|
470
|
-
model: a.resolveModel(),
|
|
471
|
-
system: a.resolveSystem(),
|
|
472
|
-
tools: a._config.tools?.map((t) => t.name) ?? [],
|
|
473
|
-
handoffs: typeof a._config.handoffs === "function" ? ["(dynamic)"] : a._config.handoffs?.map((h) => h.agent._name) ?? [],
|
|
474
|
-
maxTurns: a._config.maxTurns,
|
|
475
|
-
temperature: a._config.temperature,
|
|
476
|
-
maxTokens: a._config.maxTokens,
|
|
477
|
-
effort: a._config.effort,
|
|
478
|
-
thinkingBudget: a._config.thinkingBudget,
|
|
479
|
-
includeThoughts: a._config.includeThoughts,
|
|
480
|
-
toolChoice: a._config.toolChoice,
|
|
481
|
-
stop: a._config.stop
|
|
482
|
-
}));
|
|
483
|
-
return c.json({ ok: true, data: agents });
|
|
484
|
-
});
|
|
485
|
-
app3.get("/agents/:name", (c) => {
|
|
486
|
-
const runtime = c.get("runtime");
|
|
487
|
-
const name = c.req.param("name");
|
|
488
|
-
const agent = runtime.getAgent(name);
|
|
489
|
-
if (!agent) {
|
|
490
|
-
return c.json(
|
|
491
|
-
{ ok: false, error: { code: "NOT_FOUND", message: `Agent "${name}" not found` } },
|
|
492
|
-
404
|
|
493
|
-
);
|
|
494
|
-
}
|
|
495
|
-
const cfg = agent._config;
|
|
496
|
-
return c.json({
|
|
497
|
-
ok: true,
|
|
498
|
-
data: {
|
|
499
|
-
name: agent._name,
|
|
500
|
-
model: agent.resolveModel(),
|
|
501
|
-
system: agent.resolveSystem(),
|
|
502
|
-
tools: cfg.tools?.map((t) => ({
|
|
503
|
-
name: t.name,
|
|
504
|
-
description: t.description,
|
|
505
|
-
inputSchema: zodToJsonSchema2(t.inputSchema)
|
|
506
|
-
})) ?? [],
|
|
507
|
-
handoffs: typeof cfg.handoffs === "function" ? [
|
|
508
|
-
{
|
|
509
|
-
agent: "(dynamic)",
|
|
510
|
-
description: "Resolved at runtime from metadata",
|
|
511
|
-
mode: "oneway"
|
|
512
|
-
}
|
|
513
|
-
] : cfg.handoffs?.map((h) => ({
|
|
514
|
-
agent: h.agent._name,
|
|
515
|
-
description: h.description,
|
|
516
|
-
mode: h.mode ?? "oneway"
|
|
517
|
-
})) ?? [],
|
|
518
|
-
maxTurns: cfg.maxTurns,
|
|
519
|
-
temperature: cfg.temperature,
|
|
520
|
-
maxTokens: cfg.maxTokens,
|
|
521
|
-
effort: cfg.effort,
|
|
522
|
-
thinkingBudget: cfg.thinkingBudget,
|
|
523
|
-
includeThoughts: cfg.includeThoughts,
|
|
524
|
-
toolChoice: cfg.toolChoice,
|
|
525
|
-
stop: cfg.stop,
|
|
526
|
-
timeout: cfg.timeout,
|
|
527
|
-
maxContext: cfg.maxContext,
|
|
528
|
-
version: cfg.version,
|
|
529
|
-
mcp: cfg.mcp,
|
|
530
|
-
mcpTools: cfg.mcpTools,
|
|
531
|
-
hasGuardrails: !!cfg.guardrails,
|
|
532
|
-
guardrails: cfg.guardrails ? {
|
|
533
|
-
hasInput: !!cfg.guardrails.input,
|
|
534
|
-
hasOutput: !!cfg.guardrails.output,
|
|
535
|
-
onBlock: cfg.guardrails.onBlock ?? "throw",
|
|
536
|
-
maxRetries: cfg.guardrails.maxRetries
|
|
537
|
-
} : null
|
|
538
|
-
}
|
|
539
|
-
});
|
|
540
|
-
});
|
|
541
|
-
var agents_default = app3;
|
|
542
|
-
|
|
543
|
-
// src/server/routes/tools.ts
|
|
544
|
-
import { Hono as Hono6 } from "hono";
|
|
545
|
-
import { zodToJsonSchema as zodToJsonSchema3 } from "@axlsdk/axl";
|
|
546
|
-
var app4 = new Hono6();
|
|
547
|
-
app4.get("/tools", (c) => {
|
|
548
|
-
const runtime = c.get("runtime");
|
|
549
|
-
const tools = runtime.getTools().map((t) => ({
|
|
550
|
-
name: t.name,
|
|
551
|
-
description: t.description,
|
|
552
|
-
inputSchema: t.inputSchema ? zodToJsonSchema3(t.inputSchema) : {},
|
|
553
|
-
sensitive: t.sensitive ?? false,
|
|
554
|
-
requireApproval: t.requireApproval ?? false
|
|
555
|
-
}));
|
|
556
|
-
return c.json({ ok: true, data: tools });
|
|
557
|
-
});
|
|
558
|
-
app4.get("/tools/:name", (c) => {
|
|
559
|
-
const runtime = c.get("runtime");
|
|
560
|
-
const name = c.req.param("name");
|
|
561
|
-
const tool = runtime.getTool(name);
|
|
562
|
-
if (!tool) {
|
|
563
|
-
return c.json(
|
|
564
|
-
{ ok: false, error: { code: "NOT_FOUND", message: `Tool "${name}" not found` } },
|
|
565
|
-
404
|
|
566
|
-
);
|
|
567
|
-
}
|
|
568
|
-
return c.json({
|
|
569
|
-
ok: true,
|
|
570
|
-
data: {
|
|
571
|
-
name: tool.name,
|
|
572
|
-
description: tool.description,
|
|
573
|
-
inputSchema: tool.inputSchema ? zodToJsonSchema3(tool.inputSchema) : {},
|
|
574
|
-
sensitive: tool.sensitive,
|
|
575
|
-
requireApproval: tool.requireApproval,
|
|
576
|
-
retry: tool.retry,
|
|
577
|
-
hasHooks: !!tool.hooks,
|
|
578
|
-
hooks: tool.hooks ? {
|
|
579
|
-
hasBefore: !!tool.hooks.before,
|
|
580
|
-
hasAfter: !!tool.hooks.after
|
|
581
|
-
} : null
|
|
582
|
-
}
|
|
583
|
-
});
|
|
584
|
-
});
|
|
585
|
-
app4.post("/tools/:name/test", async (c) => {
|
|
586
|
-
const runtime = c.get("runtime");
|
|
587
|
-
const name = c.req.param("name");
|
|
588
|
-
const tool = runtime.getTool(name);
|
|
589
|
-
if (!tool) {
|
|
590
|
-
return c.json(
|
|
591
|
-
{ ok: false, error: { code: "NOT_FOUND", message: `Tool "${name}" not found` } },
|
|
592
|
-
404
|
|
593
|
-
);
|
|
594
|
-
}
|
|
595
|
-
const body = await c.req.json();
|
|
596
|
-
const ctx = runtime.createContext();
|
|
597
|
-
const result = await tool.run(ctx, body.input);
|
|
598
|
-
return c.json({ ok: true, data: { result } });
|
|
599
|
-
});
|
|
600
|
-
var tools_default = app4;
|
|
601
|
-
|
|
602
|
-
// src/server/routes/memory.ts
|
|
603
|
-
import { Hono as Hono7 } from "hono";
|
|
604
|
-
var app5 = new Hono7();
|
|
605
|
-
app5.get("/memory/:scope", async (c) => {
|
|
606
|
-
const runtime = c.get("runtime");
|
|
607
|
-
const store = runtime.getStateStore();
|
|
608
|
-
const scope = c.req.param("scope");
|
|
609
|
-
if (!store.getAllMemory) {
|
|
610
|
-
return c.json({ ok: true, data: [] });
|
|
611
|
-
}
|
|
612
|
-
const entries = await store.getAllMemory(scope);
|
|
613
|
-
return c.json({ ok: true, data: entries });
|
|
614
|
-
});
|
|
615
|
-
app5.get("/memory/:scope/:key", async (c) => {
|
|
616
|
-
const runtime = c.get("runtime");
|
|
617
|
-
const store = runtime.getStateStore();
|
|
618
|
-
const scope = c.req.param("scope");
|
|
619
|
-
const key = c.req.param("key");
|
|
620
|
-
if (!store.getMemory) {
|
|
621
|
-
return c.json(
|
|
622
|
-
{ ok: false, error: { code: "NOT_SUPPORTED", message: "Memory not supported" } },
|
|
623
|
-
501
|
|
624
|
-
);
|
|
625
|
-
}
|
|
626
|
-
const value = await store.getMemory(scope, key);
|
|
627
|
-
if (value === null) {
|
|
628
|
-
return c.json(
|
|
629
|
-
{ ok: false, error: { code: "NOT_FOUND", message: `Memory "${scope}/${key}" not found` } },
|
|
630
|
-
404
|
|
631
|
-
);
|
|
632
|
-
}
|
|
633
|
-
return c.json({ ok: true, data: { key, value } });
|
|
634
|
-
});
|
|
635
|
-
app5.put("/memory/:scope/:key", async (c) => {
|
|
636
|
-
const runtime = c.get("runtime");
|
|
637
|
-
const store = runtime.getStateStore();
|
|
638
|
-
const scope = c.req.param("scope");
|
|
639
|
-
const key = c.req.param("key");
|
|
640
|
-
if (!store.saveMemory) {
|
|
641
|
-
return c.json(
|
|
642
|
-
{ ok: false, error: { code: "NOT_SUPPORTED", message: "Memory not supported" } },
|
|
643
|
-
501
|
|
644
|
-
);
|
|
645
|
-
}
|
|
646
|
-
const body = await c.req.json();
|
|
647
|
-
await store.saveMemory(scope, key, body.value);
|
|
648
|
-
return c.json({ ok: true, data: { saved: true } });
|
|
649
|
-
});
|
|
650
|
-
app5.delete("/memory/:scope/:key", async (c) => {
|
|
651
|
-
const runtime = c.get("runtime");
|
|
652
|
-
const store = runtime.getStateStore();
|
|
653
|
-
const scope = c.req.param("scope");
|
|
654
|
-
const key = c.req.param("key");
|
|
655
|
-
if (!store.deleteMemory) {
|
|
656
|
-
return c.json(
|
|
657
|
-
{ ok: false, error: { code: "NOT_SUPPORTED", message: "Memory not supported" } },
|
|
658
|
-
501
|
|
659
|
-
);
|
|
660
|
-
}
|
|
661
|
-
await store.deleteMemory(scope, key);
|
|
662
|
-
return c.json({ ok: true, data: { deleted: true } });
|
|
663
|
-
});
|
|
664
|
-
app5.post("/memory/search", async (c) => {
|
|
665
|
-
return c.json({
|
|
666
|
-
ok: true,
|
|
667
|
-
data: { results: [], message: "Semantic search requires MemoryManager with vector store" }
|
|
668
|
-
});
|
|
669
|
-
});
|
|
670
|
-
var memory_default = app5;
|
|
671
|
-
|
|
672
|
-
// src/server/routes/decisions.ts
|
|
673
|
-
import { Hono as Hono8 } from "hono";
|
|
674
|
-
var app6 = new Hono8();
|
|
675
|
-
app6.get("/decisions", async (c) => {
|
|
676
|
-
const runtime = c.get("runtime");
|
|
677
|
-
const decisions = await runtime.getPendingDecisions();
|
|
678
|
-
return c.json({ ok: true, data: decisions });
|
|
679
|
-
});
|
|
680
|
-
app6.post("/decisions/:executionId/resolve", async (c) => {
|
|
681
|
-
const runtime = c.get("runtime");
|
|
682
|
-
const executionId = c.req.param("executionId");
|
|
683
|
-
const body = await c.req.json();
|
|
684
|
-
await runtime.resolveDecision(executionId, body);
|
|
685
|
-
return c.json({ ok: true, data: { resolved: true } });
|
|
686
|
-
});
|
|
687
|
-
var decisions_default = app6;
|
|
688
|
-
|
|
689
|
-
// src/server/routes/costs.ts
|
|
690
|
-
import { Hono as Hono9 } from "hono";
|
|
691
|
-
function createCostRoutes(costAggregator) {
|
|
692
|
-
const app7 = new Hono9();
|
|
693
|
-
app7.get("/costs", (c) => {
|
|
694
|
-
return c.json({ ok: true, data: costAggregator.getData() });
|
|
695
|
-
});
|
|
696
|
-
app7.post("/costs/reset", (c) => {
|
|
697
|
-
costAggregator.reset();
|
|
698
|
-
return c.json({ ok: true, data: { reset: true } });
|
|
699
|
-
});
|
|
700
|
-
return app7;
|
|
701
|
-
}
|
|
702
|
-
|
|
703
|
-
// src/server/routes/evals.ts
|
|
704
|
-
import { Hono as Hono10 } from "hono";
|
|
705
|
-
function createEvalRoutes(evalLoader) {
|
|
706
|
-
const app7 = new Hono10();
|
|
707
|
-
app7.get("/evals", async (c) => {
|
|
708
|
-
if (evalLoader) await evalLoader();
|
|
709
|
-
const runtime = c.get("runtime");
|
|
710
|
-
const evals = runtime.getRegisteredEvals();
|
|
711
|
-
return c.json({ ok: true, data: evals });
|
|
712
|
-
});
|
|
713
|
-
app7.get("/evals/history", async (c) => {
|
|
714
|
-
const runtime = c.get("runtime");
|
|
715
|
-
const history = await runtime.getEvalHistory();
|
|
716
|
-
return c.json({ ok: true, data: history });
|
|
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
|
-
let runs = 1;
|
|
730
|
-
try {
|
|
731
|
-
const body = await c.req.json().catch(() => ({}));
|
|
732
|
-
if (typeof body.runs === "number" && Number.isFinite(body.runs) && body.runs > 1) {
|
|
733
|
-
runs = Math.min(Math.floor(body.runs), 25);
|
|
734
|
-
}
|
|
735
|
-
} catch {
|
|
736
|
-
}
|
|
737
|
-
try {
|
|
738
|
-
if (runs > 1) {
|
|
739
|
-
const { randomUUID } = await import("crypto");
|
|
740
|
-
const { aggregateRuns } = await import("@axlsdk/eval");
|
|
741
|
-
const runGroupId = randomUUID();
|
|
742
|
-
const results = [];
|
|
743
|
-
for (let r = 0; r < runs; r++) {
|
|
744
|
-
const result2 = await runtime.runRegisteredEval(name, {
|
|
745
|
-
metadata: { runGroupId, runIndex: r }
|
|
746
|
-
});
|
|
747
|
-
results.push(result2);
|
|
748
|
-
}
|
|
749
|
-
const typedResults = results;
|
|
750
|
-
const aggregate = aggregateRuns(typedResults);
|
|
751
|
-
const first = typedResults[0];
|
|
752
|
-
const result = { ...first, _multiRun: { aggregate, allRuns: typedResults } };
|
|
753
|
-
return c.json({ ok: true, data: result });
|
|
754
|
-
} else {
|
|
755
|
-
const result = await runtime.runRegisteredEval(name);
|
|
756
|
-
return c.json({ ok: true, data: result });
|
|
757
|
-
}
|
|
758
|
-
} catch (err) {
|
|
759
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
760
|
-
return c.json({ ok: false, error: { code: "EVAL_ERROR", message } }, 400);
|
|
761
|
-
}
|
|
762
|
-
});
|
|
763
|
-
app7.post("/evals/:name/rescore", async (c) => {
|
|
764
|
-
if (evalLoader) await evalLoader();
|
|
765
|
-
const runtime = c.get("runtime");
|
|
766
|
-
const name = c.req.param("name");
|
|
767
|
-
const body = await c.req.json();
|
|
768
|
-
if (!body.resultId || typeof body.resultId !== "string") {
|
|
769
|
-
return c.json(
|
|
770
|
-
{ ok: false, error: { code: "BAD_REQUEST", message: "resultId is required" } },
|
|
771
|
-
400
|
|
772
|
-
);
|
|
773
|
-
}
|
|
774
|
-
const entry = runtime.getRegisteredEval(name);
|
|
775
|
-
if (!entry) {
|
|
776
|
-
return c.json(
|
|
777
|
-
{ ok: false, error: { code: "NOT_FOUND", message: `Eval "${name}" not found` } },
|
|
778
|
-
404
|
|
779
|
-
);
|
|
780
|
-
}
|
|
781
|
-
const history = await runtime.getEvalHistory();
|
|
782
|
-
const historyEntry = history.find((h) => h.id === body.resultId);
|
|
783
|
-
if (!historyEntry) {
|
|
784
|
-
return c.json(
|
|
785
|
-
{ ok: false, error: { code: "NOT_FOUND", message: `Result "${body.resultId}" not found` } },
|
|
786
|
-
404
|
|
787
|
-
);
|
|
788
|
-
}
|
|
789
|
-
try {
|
|
790
|
-
const { rescore } = await import("@axlsdk/eval");
|
|
791
|
-
const config = entry.config;
|
|
792
|
-
const result = await rescore(
|
|
793
|
-
historyEntry.data,
|
|
794
|
-
config.scorers,
|
|
795
|
-
runtime
|
|
796
|
-
);
|
|
797
|
-
await runtime.saveEvalResult({
|
|
798
|
-
id: result.id,
|
|
799
|
-
eval: name,
|
|
800
|
-
timestamp: Date.now(),
|
|
801
|
-
data: result
|
|
802
|
-
});
|
|
803
|
-
return c.json({ ok: true, data: result });
|
|
804
|
-
} catch (err) {
|
|
805
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
806
|
-
return c.json({ ok: false, error: { code: "EVAL_ERROR", message } }, 400);
|
|
807
|
-
}
|
|
808
|
-
});
|
|
809
|
-
app7.post("/evals/compare", async (c) => {
|
|
810
|
-
const runtime = c.get("runtime");
|
|
811
|
-
const body = await c.req.json();
|
|
812
|
-
try {
|
|
813
|
-
const result = await runtime.evalCompare(body.baseline, body.candidate, body.options);
|
|
814
|
-
return c.json({ ok: true, data: result });
|
|
815
|
-
} catch (err) {
|
|
816
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
817
|
-
return c.json({ ok: false, error: { code: "EVAL_ERROR", message } }, 400);
|
|
818
|
-
}
|
|
819
|
-
});
|
|
820
|
-
return app7;
|
|
821
|
-
}
|
|
822
|
-
|
|
823
|
-
// src/server/routes/playground.ts
|
|
824
|
-
import { Hono as Hono11 } from "hono";
|
|
825
|
-
function createPlaygroundRoutes(connMgr) {
|
|
826
|
-
const app7 = new Hono11();
|
|
827
|
-
app7.post("/playground/chat", async (c) => {
|
|
828
|
-
const runtime = c.get("runtime");
|
|
829
|
-
const body = await c.req.json();
|
|
830
|
-
if (!body.message || typeof body.message !== "string" || !body.message.trim()) {
|
|
831
|
-
return c.json(
|
|
832
|
-
{
|
|
833
|
-
ok: false,
|
|
834
|
-
error: {
|
|
835
|
-
code: "INVALID_INPUT",
|
|
836
|
-
message: "message is required and must be a non-empty string"
|
|
837
|
-
}
|
|
838
|
-
},
|
|
839
|
-
400
|
|
840
|
-
);
|
|
841
|
-
}
|
|
842
|
-
const agents = runtime.getAgents();
|
|
843
|
-
const agent = body.agent ? agents.find((a) => a._name === body.agent) : agents[0];
|
|
844
|
-
if (!agent) {
|
|
845
|
-
return c.json(
|
|
846
|
-
{
|
|
847
|
-
ok: false,
|
|
848
|
-
error: { code: "NO_AGENT", message: `Agent "${body.agent ?? ""}" not found` }
|
|
849
|
-
},
|
|
850
|
-
400
|
|
851
|
-
);
|
|
852
|
-
}
|
|
853
|
-
const sessionId = body.sessionId ?? `playground-${Date.now()}`;
|
|
854
|
-
const executionId = `playground-${sessionId}-${Date.now()}`;
|
|
855
|
-
const store = runtime.getStateStore();
|
|
856
|
-
const history = await store.getSession(sessionId);
|
|
857
|
-
history.push({ role: "user", content: body.message });
|
|
858
|
-
const ctx = runtime.createContext({
|
|
859
|
-
sessionHistory: history,
|
|
860
|
-
onToken: (token) => {
|
|
861
|
-
connMgr.broadcastWithWildcard(`execution:${executionId}`, {
|
|
862
|
-
type: "token",
|
|
863
|
-
data: token
|
|
864
|
-
});
|
|
865
|
-
}
|
|
866
|
-
});
|
|
867
|
-
(async () => {
|
|
868
|
-
try {
|
|
869
|
-
const result = await ctx.ask(agent, body.message);
|
|
870
|
-
const resultText = typeof result === "string" ? result : JSON.stringify(result);
|
|
871
|
-
history.push({ role: "assistant", content: resultText });
|
|
872
|
-
await store.saveSession(sessionId, history);
|
|
873
|
-
connMgr.broadcastWithWildcard(`execution:${executionId}`, {
|
|
874
|
-
type: "done",
|
|
875
|
-
data: resultText
|
|
876
|
-
});
|
|
877
|
-
} catch (err) {
|
|
878
|
-
connMgr.broadcastWithWildcard(`execution:${executionId}`, {
|
|
879
|
-
type: "error",
|
|
880
|
-
message: err instanceof Error ? err.message : String(err)
|
|
881
|
-
});
|
|
882
|
-
}
|
|
883
|
-
})();
|
|
884
|
-
return c.json({
|
|
885
|
-
ok: true,
|
|
886
|
-
data: { sessionId, executionId, streaming: true }
|
|
887
|
-
});
|
|
888
|
-
});
|
|
889
|
-
return app7;
|
|
890
|
-
}
|
|
891
|
-
|
|
892
|
-
// src/server/index.ts
|
|
893
|
-
function createServer(options) {
|
|
894
|
-
const { runtime, staticRoot, basePath = "", readOnly = false } = options;
|
|
895
|
-
const app7 = new Hono12();
|
|
896
|
-
const connMgr = new ConnectionManager();
|
|
897
|
-
const costAggregator = new CostAggregator(connMgr);
|
|
898
|
-
if (options.cors !== false) {
|
|
899
|
-
app7.use("*", cors());
|
|
900
|
-
}
|
|
901
|
-
app7.use("*", errorHandler);
|
|
902
|
-
app7.use("*", async (c, next) => {
|
|
903
|
-
c.set("runtime", runtime);
|
|
904
|
-
await next();
|
|
905
|
-
});
|
|
906
|
-
if (readOnly) {
|
|
907
|
-
const blocked = [
|
|
908
|
-
"POST /api/workflows",
|
|
909
|
-
"POST /api/executions",
|
|
910
|
-
"POST /api/sessions",
|
|
911
|
-
"DELETE /api/sessions",
|
|
912
|
-
"PUT /api/memory",
|
|
913
|
-
"DELETE /api/memory",
|
|
914
|
-
"POST /api/decisions",
|
|
915
|
-
"POST /api/costs",
|
|
916
|
-
"POST /api/tools",
|
|
917
|
-
"POST /api/evals",
|
|
918
|
-
"POST /api/playground"
|
|
919
|
-
];
|
|
920
|
-
app7.use("/api/*", async (c, next) => {
|
|
921
|
-
const apiIdx = c.req.path.indexOf("/api/");
|
|
922
|
-
const apiPath = apiIdx >= 0 ? c.req.path.slice(apiIdx) : c.req.path;
|
|
923
|
-
const key = `${c.req.method} ${apiPath}`;
|
|
924
|
-
if (blocked.some((b) => key.startsWith(b))) {
|
|
925
|
-
return c.json(
|
|
926
|
-
{
|
|
927
|
-
ok: false,
|
|
928
|
-
error: { code: "READ_ONLY", message: "Studio is mounted in read-only mode" }
|
|
929
|
-
},
|
|
930
|
-
405
|
|
931
|
-
);
|
|
932
|
-
}
|
|
933
|
-
await next();
|
|
934
|
-
});
|
|
935
|
-
}
|
|
936
|
-
const api = new Hono12();
|
|
937
|
-
api.route("/", health_default);
|
|
938
|
-
api.route("/", createWorkflowRoutes(connMgr));
|
|
939
|
-
api.route("/", executions_default);
|
|
940
|
-
api.route("/", createSessionRoutes(connMgr));
|
|
941
|
-
api.route("/", agents_default);
|
|
942
|
-
api.route("/", tools_default);
|
|
943
|
-
api.route("/", memory_default);
|
|
944
|
-
api.route("/", decisions_default);
|
|
945
|
-
api.route("/", createCostRoutes(costAggregator));
|
|
946
|
-
api.route("/", createEvalRoutes(options.evalLoader));
|
|
947
|
-
api.route("/", createPlaygroundRoutes(connMgr));
|
|
948
|
-
app7.route("/api", api);
|
|
949
|
-
const traceListener = (event) => {
|
|
950
|
-
const traceEvent = event;
|
|
951
|
-
if (traceEvent.executionId) {
|
|
952
|
-
connMgr.broadcastWithWildcard(`trace:${traceEvent.executionId}`, traceEvent);
|
|
953
|
-
}
|
|
954
|
-
costAggregator.onTrace(traceEvent);
|
|
955
|
-
if (traceEvent.type === "await_human") {
|
|
956
|
-
connMgr.broadcast("decisions", traceEvent);
|
|
957
|
-
}
|
|
958
|
-
};
|
|
959
|
-
runtime.on("trace", traceListener);
|
|
960
|
-
if (staticRoot) {
|
|
961
|
-
const indexPath = resolve(staticRoot, "index.html");
|
|
962
|
-
let spaHtml;
|
|
963
|
-
if (!existsSync(indexPath)) {
|
|
964
|
-
console.warn(`[axl-studio] index.html not found at ${indexPath}`);
|
|
965
|
-
} else {
|
|
966
|
-
const rawHtml = readFileSync(indexPath, "utf-8");
|
|
967
|
-
if (basePath) {
|
|
968
|
-
const safeBasePath = JSON.stringify(basePath).replace(/</g, "\\u003c");
|
|
969
|
-
const injected = rawHtml.replace(
|
|
970
|
-
"<head>",
|
|
971
|
-
`<head>
|
|
972
|
-
<base href="${basePath}/">
|
|
973
|
-
<script>window.__AXL_STUDIO_BASE__=${safeBasePath}</script>`
|
|
974
|
-
);
|
|
975
|
-
if (injected === rawHtml) {
|
|
976
|
-
console.warn(
|
|
977
|
-
"[axl-studio] Could not inject basePath into index.html \u2014 <head> tag not found. The SPA may not route correctly."
|
|
978
|
-
);
|
|
979
|
-
}
|
|
980
|
-
spaHtml = injected;
|
|
981
|
-
} else {
|
|
982
|
-
spaHtml = rawHtml;
|
|
983
|
-
}
|
|
984
|
-
}
|
|
985
|
-
const staticHandler = serveStatic({
|
|
986
|
-
root: staticRoot,
|
|
987
|
-
rewriteRequestPath: basePath ? (path) => path.startsWith(basePath) ? path.slice(basePath.length) || "/" : path : void 0
|
|
988
|
-
});
|
|
989
|
-
app7.use("/*", async (c, next) => {
|
|
990
|
-
const reqPath = c.req.path;
|
|
991
|
-
const resolved = basePath && reqPath.startsWith(basePath) ? reqPath.slice(basePath.length) || "/" : reqPath;
|
|
992
|
-
if (resolved === "/" || resolved === "/index.html" || resolved === "/ws") {
|
|
993
|
-
return next();
|
|
994
|
-
}
|
|
995
|
-
return staticHandler(c, next);
|
|
996
|
-
});
|
|
997
|
-
if (spaHtml) {
|
|
998
|
-
app7.get("*", async (c, next) => {
|
|
999
|
-
const resolved = basePath && c.req.path.startsWith(basePath) ? c.req.path.slice(basePath.length) || "/" : c.req.path;
|
|
1000
|
-
if (resolved === "/ws") return next();
|
|
1001
|
-
return c.html(spaHtml);
|
|
1002
|
-
});
|
|
1003
|
-
}
|
|
1004
|
-
}
|
|
1005
|
-
return {
|
|
1006
|
-
app: app7,
|
|
1007
|
-
connMgr,
|
|
1008
|
-
costAggregator,
|
|
1009
|
-
/** Create WS handlers. Call before registering static/SPA routes are reached. */
|
|
1010
|
-
createWsHandlers: () => createWsHandlers(connMgr),
|
|
1011
|
-
traceListener
|
|
1012
|
-
};
|
|
1013
|
-
}
|
|
1014
|
-
|
|
1015
|
-
export {
|
|
1016
|
-
ConnectionManager,
|
|
1017
|
-
handleWsMessage,
|
|
1018
|
-
CostAggregator,
|
|
1019
|
-
createServer
|
|
1020
|
-
};
|
|
1021
|
-
//# sourceMappingURL=chunk-YWRYXT7U.js.map
|