@axlsdk/studio 0.13.5 → 0.13.7
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 +6 -4
- package/dist/{chunk-NU6255VY.js → chunk-YWRYXT7U.js} +171 -36
- package/dist/chunk-YWRYXT7U.js.map +1 -0
- package/dist/cli.cjs +170 -35
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/client/assets/index-C_uwupnn.js +221 -0
- package/dist/client/assets/index-DVcH6P9w.css +1 -0
- package/dist/client/index.html +2 -2
- package/dist/{connection-manager-DbOgO_gK.d.cts → connection-manager-B7AWpsCD.d.cts} +9 -3
- package/dist/{connection-manager-DbOgO_gK.d.ts → connection-manager-B7AWpsCD.d.ts} +9 -3
- package/dist/middleware.cjs +170 -35
- package/dist/middleware.cjs.map +1 -1
- package/dist/middleware.d.cts +1 -1
- package/dist/middleware.d.ts +1 -1
- package/dist/middleware.js +1 -1
- package/dist/server/index.cjs +180 -35
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +3 -2
- package/dist/server/index.d.ts +3 -2
- package/dist/server/index.js +1 -1
- package/package.json +5 -5
- package/dist/chunk-NU6255VY.js.map +0 -1
- package/dist/client/assets/index-DG2zy3iH.js +0 -150
- package/dist/client/assets/index-WUBHc-Rd.css +0 -1
package/dist/cli.cjs
CHANGED
|
@@ -63,11 +63,18 @@ async function errorHandler(c, next) {
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
// src/server/ws/connection-manager.ts
|
|
66
|
+
function isBufferedChannel(channel) {
|
|
67
|
+
return channel.startsWith("execution:");
|
|
68
|
+
}
|
|
69
|
+
var BUFFER_TTL_MS = 3e4;
|
|
70
|
+
var MAX_BUFFER_EVENTS = 500;
|
|
66
71
|
var ConnectionManager = class {
|
|
67
72
|
/** channel -> set of WS connections */
|
|
68
73
|
channels = /* @__PURE__ */ new Map();
|
|
69
74
|
/** ws -> set of subscribed channels (for cleanup) */
|
|
70
75
|
connections = /* @__PURE__ */ new Map();
|
|
76
|
+
/** channel -> replay buffer for execution streams */
|
|
77
|
+
buffers = /* @__PURE__ */ new Map();
|
|
71
78
|
maxConnections = 100;
|
|
72
79
|
/** Register a new WS connection. */
|
|
73
80
|
add(ws) {
|
|
@@ -90,7 +97,7 @@ var ConnectionManager = class {
|
|
|
90
97
|
}
|
|
91
98
|
this.connections.delete(ws);
|
|
92
99
|
}
|
|
93
|
-
/** Subscribe a connection to a channel.
|
|
100
|
+
/** Subscribe a connection to a channel. Replays buffered events for execution channels. */
|
|
94
101
|
subscribe(ws, channel) {
|
|
95
102
|
if (!this.connections.has(ws)) return;
|
|
96
103
|
let subs = this.channels.get(channel);
|
|
@@ -100,6 +107,17 @@ var ConnectionManager = class {
|
|
|
100
107
|
}
|
|
101
108
|
subs.add(ws);
|
|
102
109
|
this.connections.get(ws).add(channel);
|
|
110
|
+
const buffer = this.buffers.get(channel);
|
|
111
|
+
if (buffer) {
|
|
112
|
+
for (const msg of buffer.events) {
|
|
113
|
+
try {
|
|
114
|
+
ws.send(msg);
|
|
115
|
+
} catch {
|
|
116
|
+
this.remove(ws);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
103
121
|
}
|
|
104
122
|
/** Unsubscribe a connection from a channel. */
|
|
105
123
|
unsubscribe(ws, channel) {
|
|
@@ -109,11 +127,30 @@ var ConnectionManager = class {
|
|
|
109
127
|
}
|
|
110
128
|
this.connections.get(ws)?.delete(channel);
|
|
111
129
|
}
|
|
112
|
-
/** Broadcast data to all subscribers of a channel. */
|
|
130
|
+
/** Broadcast data to all subscribers of a channel. Buffers events for execution channels. */
|
|
113
131
|
broadcast(channel, data) {
|
|
132
|
+
const msg = JSON.stringify({ type: "event", channel, data });
|
|
133
|
+
if (isBufferedChannel(channel)) {
|
|
134
|
+
let buffer = this.buffers.get(channel);
|
|
135
|
+
if (!buffer) {
|
|
136
|
+
buffer = { events: [], complete: false };
|
|
137
|
+
this.buffers.set(channel, buffer);
|
|
138
|
+
}
|
|
139
|
+
const event = data;
|
|
140
|
+
const isTerminal = event.type === "done" || event.type === "error";
|
|
141
|
+
if (buffer.events.length < MAX_BUFFER_EVENTS || isTerminal) {
|
|
142
|
+
buffer.events.push(msg);
|
|
143
|
+
}
|
|
144
|
+
if (isTerminal) {
|
|
145
|
+
buffer.complete = true;
|
|
146
|
+
if (buffer.timer) clearTimeout(buffer.timer);
|
|
147
|
+
buffer.timer = setTimeout(() => {
|
|
148
|
+
this.buffers.delete(channel);
|
|
149
|
+
}, BUFFER_TTL_MS);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
114
152
|
const subs = this.channels.get(channel);
|
|
115
153
|
if (!subs || subs.size === 0) return;
|
|
116
|
-
const msg = JSON.stringify({ type: "event", channel, data });
|
|
117
154
|
for (const ws of [...subs]) {
|
|
118
155
|
try {
|
|
119
156
|
ws.send(msg);
|
|
@@ -140,13 +177,17 @@ var ConnectionManager = class {
|
|
|
140
177
|
}
|
|
141
178
|
}
|
|
142
179
|
}
|
|
143
|
-
/** Close all connections
|
|
180
|
+
/** Close all connections, clear all state and buffers. Used during shutdown. */
|
|
144
181
|
closeAll() {
|
|
145
182
|
for (const ws of this.connections.keys()) {
|
|
146
183
|
ws.close?.();
|
|
147
184
|
}
|
|
185
|
+
for (const buffer of this.buffers.values()) {
|
|
186
|
+
if (buffer.timer) clearTimeout(buffer.timer);
|
|
187
|
+
}
|
|
148
188
|
this.connections.clear();
|
|
149
189
|
this.channels.clear();
|
|
190
|
+
this.buffers.clear();
|
|
150
191
|
}
|
|
151
192
|
/** Get the number of active connections. */
|
|
152
193
|
get connectionCount() {
|
|
@@ -351,15 +392,8 @@ function createWorkflowRoutes(connMgr) {
|
|
|
351
392
|
const stream = runtime.stream(name, body.input ?? {}, { metadata: body.metadata });
|
|
352
393
|
const executionId = `stream-${Date.now()}`;
|
|
353
394
|
(async () => {
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
connMgr.broadcastWithWildcard(`execution:${executionId}`, event);
|
|
357
|
-
}
|
|
358
|
-
} catch (err) {
|
|
359
|
-
connMgr.broadcastWithWildcard(`execution:${executionId}`, {
|
|
360
|
-
type: "error",
|
|
361
|
-
message: err instanceof Error ? err.message : "Stream error"
|
|
362
|
-
});
|
|
395
|
+
for await (const event of stream) {
|
|
396
|
+
connMgr.broadcastWithWildcard(`execution:${executionId}`, event);
|
|
363
397
|
}
|
|
364
398
|
})();
|
|
365
399
|
return c.json({ ok: true, data: { executionId, streaming: true } });
|
|
@@ -440,15 +474,8 @@ function createSessionRoutes(connMgr) {
|
|
|
440
474
|
const stream = await session.stream(body.workflow, body.message);
|
|
441
475
|
const executionId = `session-${id}-${Date.now()}`;
|
|
442
476
|
(async () => {
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
connMgr.broadcastWithWildcard(`execution:${executionId}`, event);
|
|
446
|
-
}
|
|
447
|
-
} catch (err) {
|
|
448
|
-
connMgr.broadcastWithWildcard(`execution:${executionId}`, {
|
|
449
|
-
type: "error",
|
|
450
|
-
message: err instanceof Error ? err.message : "Stream error"
|
|
451
|
-
});
|
|
477
|
+
for await (const event of stream) {
|
|
478
|
+
connMgr.broadcastWithWildcard(`execution:${executionId}`, event);
|
|
452
479
|
}
|
|
453
480
|
})();
|
|
454
481
|
return c.json({ ok: true, data: { executionId, streaming: true } });
|
|
@@ -730,8 +757,80 @@ function createEvalRoutes(evalLoader) {
|
|
|
730
757
|
404
|
|
731
758
|
);
|
|
732
759
|
}
|
|
760
|
+
let runs = 1;
|
|
761
|
+
try {
|
|
762
|
+
const body = await c.req.json().catch(() => ({}));
|
|
763
|
+
if (typeof body.runs === "number" && Number.isFinite(body.runs) && body.runs > 1) {
|
|
764
|
+
runs = Math.min(Math.floor(body.runs), 25);
|
|
765
|
+
}
|
|
766
|
+
} catch {
|
|
767
|
+
}
|
|
768
|
+
try {
|
|
769
|
+
if (runs > 1) {
|
|
770
|
+
const { randomUUID } = await import("crypto");
|
|
771
|
+
const { aggregateRuns } = await import("@axlsdk/eval");
|
|
772
|
+
const runGroupId = randomUUID();
|
|
773
|
+
const results = [];
|
|
774
|
+
for (let r = 0; r < runs; r++) {
|
|
775
|
+
const result2 = await runtime.runRegisteredEval(name, {
|
|
776
|
+
metadata: { runGroupId, runIndex: r }
|
|
777
|
+
});
|
|
778
|
+
results.push(result2);
|
|
779
|
+
}
|
|
780
|
+
const typedResults = results;
|
|
781
|
+
const aggregate = aggregateRuns(typedResults);
|
|
782
|
+
const first = typedResults[0];
|
|
783
|
+
const result = { ...first, _multiRun: { aggregate, allRuns: typedResults } };
|
|
784
|
+
return c.json({ ok: true, data: result });
|
|
785
|
+
} else {
|
|
786
|
+
const result = await runtime.runRegisteredEval(name);
|
|
787
|
+
return c.json({ ok: true, data: result });
|
|
788
|
+
}
|
|
789
|
+
} catch (err) {
|
|
790
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
791
|
+
return c.json({ ok: false, error: { code: "EVAL_ERROR", message } }, 400);
|
|
792
|
+
}
|
|
793
|
+
});
|
|
794
|
+
app7.post("/evals/:name/rescore", async (c) => {
|
|
795
|
+
if (evalLoader) await evalLoader();
|
|
796
|
+
const runtime = c.get("runtime");
|
|
797
|
+
const name = c.req.param("name");
|
|
798
|
+
const body = await c.req.json();
|
|
799
|
+
if (!body.resultId || typeof body.resultId !== "string") {
|
|
800
|
+
return c.json(
|
|
801
|
+
{ ok: false, error: { code: "BAD_REQUEST", message: "resultId is required" } },
|
|
802
|
+
400
|
|
803
|
+
);
|
|
804
|
+
}
|
|
805
|
+
const entry = runtime.getRegisteredEval(name);
|
|
806
|
+
if (!entry) {
|
|
807
|
+
return c.json(
|
|
808
|
+
{ ok: false, error: { code: "NOT_FOUND", message: `Eval "${name}" not found` } },
|
|
809
|
+
404
|
|
810
|
+
);
|
|
811
|
+
}
|
|
812
|
+
const history = await runtime.getEvalHistory();
|
|
813
|
+
const historyEntry = history.find((h) => h.id === body.resultId);
|
|
814
|
+
if (!historyEntry) {
|
|
815
|
+
return c.json(
|
|
816
|
+
{ ok: false, error: { code: "NOT_FOUND", message: `Result "${body.resultId}" not found` } },
|
|
817
|
+
404
|
|
818
|
+
);
|
|
819
|
+
}
|
|
733
820
|
try {
|
|
734
|
-
const
|
|
821
|
+
const { rescore } = await import("@axlsdk/eval");
|
|
822
|
+
const config = entry.config;
|
|
823
|
+
const result = await rescore(
|
|
824
|
+
historyEntry.data,
|
|
825
|
+
config.scorers,
|
|
826
|
+
runtime
|
|
827
|
+
);
|
|
828
|
+
await runtime.saveEvalResult({
|
|
829
|
+
id: result.id,
|
|
830
|
+
eval: name,
|
|
831
|
+
timestamp: Date.now(),
|
|
832
|
+
data: result
|
|
833
|
+
});
|
|
735
834
|
return c.json({ ok: true, data: result });
|
|
736
835
|
} catch (err) {
|
|
737
836
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -742,7 +841,7 @@ function createEvalRoutes(evalLoader) {
|
|
|
742
841
|
const runtime = c.get("runtime");
|
|
743
842
|
const body = await c.req.json();
|
|
744
843
|
try {
|
|
745
|
-
const result = await runtime.evalCompare(body.baseline, body.candidate);
|
|
844
|
+
const result = await runtime.evalCompare(body.baseline, body.candidate, body.options);
|
|
746
845
|
return c.json({ ok: true, data: result });
|
|
747
846
|
} catch (err) {
|
|
748
847
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -759,26 +858,57 @@ function createPlaygroundRoutes(connMgr) {
|
|
|
759
858
|
app7.post("/playground/chat", async (c) => {
|
|
760
859
|
const runtime = c.get("runtime");
|
|
761
860
|
const body = await c.req.json();
|
|
762
|
-
|
|
763
|
-
|
|
861
|
+
if (!body.message || typeof body.message !== "string" || !body.message.trim()) {
|
|
862
|
+
return c.json(
|
|
863
|
+
{
|
|
864
|
+
ok: false,
|
|
865
|
+
error: {
|
|
866
|
+
code: "INVALID_INPUT",
|
|
867
|
+
message: "message is required and must be a non-empty string"
|
|
868
|
+
}
|
|
869
|
+
},
|
|
870
|
+
400
|
|
871
|
+
);
|
|
872
|
+
}
|
|
873
|
+
const agents = runtime.getAgents();
|
|
874
|
+
const agent = body.agent ? agents.find((a) => a._name === body.agent) : agents[0];
|
|
875
|
+
if (!agent) {
|
|
764
876
|
return c.json(
|
|
765
|
-
{
|
|
877
|
+
{
|
|
878
|
+
ok: false,
|
|
879
|
+
error: { code: "NO_AGENT", message: `Agent "${body.agent ?? ""}" not found` }
|
|
880
|
+
},
|
|
766
881
|
400
|
|
767
882
|
);
|
|
768
883
|
}
|
|
769
884
|
const sessionId = body.sessionId ?? `playground-${Date.now()}`;
|
|
770
|
-
const session = runtime.session(sessionId);
|
|
771
|
-
const stream = await session.stream(workflowName, body.message);
|
|
772
885
|
const executionId = `playground-${sessionId}-${Date.now()}`;
|
|
886
|
+
const store = runtime.getStateStore();
|
|
887
|
+
const history = await store.getSession(sessionId);
|
|
888
|
+
history.push({ role: "user", content: body.message });
|
|
889
|
+
const ctx = runtime.createContext({
|
|
890
|
+
sessionHistory: history,
|
|
891
|
+
onToken: (token) => {
|
|
892
|
+
connMgr.broadcastWithWildcard(`execution:${executionId}`, {
|
|
893
|
+
type: "token",
|
|
894
|
+
data: token
|
|
895
|
+
});
|
|
896
|
+
}
|
|
897
|
+
});
|
|
773
898
|
(async () => {
|
|
774
899
|
try {
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
}
|
|
900
|
+
const result = await ctx.ask(agent, body.message);
|
|
901
|
+
const resultText = typeof result === "string" ? result : JSON.stringify(result);
|
|
902
|
+
history.push({ role: "assistant", content: resultText });
|
|
903
|
+
await store.saveSession(sessionId, history);
|
|
904
|
+
connMgr.broadcastWithWildcard(`execution:${executionId}`, {
|
|
905
|
+
type: "done",
|
|
906
|
+
data: resultText
|
|
907
|
+
});
|
|
778
908
|
} catch (err) {
|
|
779
909
|
connMgr.broadcastWithWildcard(`execution:${executionId}`, {
|
|
780
910
|
type: "error",
|
|
781
|
-
message: err instanceof Error ? err.message :
|
|
911
|
+
message: err instanceof Error ? err.message : String(err)
|
|
782
912
|
});
|
|
783
913
|
}
|
|
784
914
|
})();
|
|
@@ -890,19 +1020,24 @@ function createServer(options) {
|
|
|
890
1020
|
app7.use("/*", async (c, next) => {
|
|
891
1021
|
const reqPath = c.req.path;
|
|
892
1022
|
const resolved = basePath && reqPath.startsWith(basePath) ? reqPath.slice(basePath.length) || "/" : reqPath;
|
|
893
|
-
if (resolved === "/" || resolved === "/index.html") {
|
|
1023
|
+
if (resolved === "/" || resolved === "/index.html" || resolved === "/ws") {
|
|
894
1024
|
return next();
|
|
895
1025
|
}
|
|
896
1026
|
return staticHandler(c, next);
|
|
897
1027
|
});
|
|
898
1028
|
if (spaHtml) {
|
|
899
|
-
app7.get("*", (c) =>
|
|
1029
|
+
app7.get("*", async (c, next) => {
|
|
1030
|
+
const resolved = basePath && c.req.path.startsWith(basePath) ? c.req.path.slice(basePath.length) || "/" : c.req.path;
|
|
1031
|
+
if (resolved === "/ws") return next();
|
|
1032
|
+
return c.html(spaHtml);
|
|
1033
|
+
});
|
|
900
1034
|
}
|
|
901
1035
|
}
|
|
902
1036
|
return {
|
|
903
1037
|
app: app7,
|
|
904
1038
|
connMgr,
|
|
905
1039
|
costAggregator,
|
|
1040
|
+
/** Create WS handlers. Call before registering static/SPA routes are reached. */
|
|
906
1041
|
createWsHandlers: () => createWsHandlers(connMgr),
|
|
907
1042
|
traceListener
|
|
908
1043
|
};
|