@anvia/studio 0.6.0 → 0.7.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/dist/index.d.ts +2 -1
- package/dist/index.js +1455 -1522
- package/dist/index.js.map +1 -1
- package/dist/ui/assets/{ArrowClockwise.es-BA79KX3F.js → ArrowClockwise.es-CdkDSmVV.js} +2 -2
- package/dist/ui/assets/{ArrowClockwise.es-BA79KX3F.js.map → ArrowClockwise.es-CdkDSmVV.js.map} +1 -1
- package/dist/ui/assets/{Path.es-DTZ3zsLn.js → Path.es-CAqZdUXu.js} +2 -2
- package/dist/ui/assets/{Path.es-DTZ3zsLn.js.map → Path.es-CAqZdUXu.js.map} +1 -1
- package/dist/ui/assets/{Play.es-CJTRfv9R.js → Play.es-D9AQgyVC.js} +2 -2
- package/dist/ui/assets/{Play.es-CJTRfv9R.js.map → Play.es-D9AQgyVC.js.map} +1 -1
- package/dist/ui/assets/{evals-page-rS-P7eLF.js → evals-page-GEsRKWxr.js} +2 -2
- package/dist/ui/assets/{evals-page-rS-P7eLF.js.map → evals-page-GEsRKWxr.js.map} +1 -1
- package/dist/ui/assets/index-DW3P6_Qc.js +54 -0
- package/dist/ui/assets/index-DW3P6_Qc.js.map +1 -0
- package/dist/ui/assets/{knowledge-page-CR0JUneq.js → knowledge-page-CQJNZ8fA.js} +2 -2
- package/dist/ui/assets/{knowledge-page-CR0JUneq.js.map → knowledge-page-CQJNZ8fA.js.map} +1 -1
- package/dist/ui/assets/{mcps-page-D3P0UAWf.js → mcps-page-BRCLJmEX.js} +2 -2
- package/dist/ui/assets/{mcps-page-D3P0UAWf.js.map → mcps-page-BRCLJmEX.js.map} +1 -1
- package/dist/ui/assets/{memory-page-kVDqOAOd.js → memory-page-DsITtAok.js} +2 -2
- package/dist/ui/assets/{memory-page-kVDqOAOd.js.map → memory-page-DsITtAok.js.map} +1 -1
- package/dist/ui/assets/{pipelines-page-lMfsVNRy.js → pipelines-page-vBUhZ5x2.js} +2 -2
- package/dist/ui/assets/{pipelines-page-lMfsVNRy.js.map → pipelines-page-vBUhZ5x2.js.map} +1 -1
- package/dist/ui/assets/{renderers-Bc89UGTN.js → renderers-hYnJAoYZ.js} +2 -2
- package/dist/ui/assets/{renderers-Bc89UGTN.js.map → renderers-hYnJAoYZ.js.map} +1 -1
- package/dist/ui/assets/{sessions-page-CVlkRPfT.js → sessions-page-BYhPHSQS.js} +2 -2
- package/dist/ui/assets/{sessions-page-CVlkRPfT.js.map → sessions-page-BYhPHSQS.js.map} +1 -1
- package/dist/ui/assets/{status-page-XKvTGruQ.js → status-page-B16drVrZ.js} +2 -2
- package/dist/ui/assets/{status-page-XKvTGruQ.js.map → status-page-B16drVrZ.js.map} +1 -1
- package/dist/ui/assets/{tools-page-DJt_QdDe.js → tools-page-DwgbeCMm.js} +2 -2
- package/dist/ui/assets/{tools-page-DJt_QdDe.js.map → tools-page-DwgbeCMm.js.map} +1 -1
- package/dist/ui/assets/{trace-browser-BBITQELO.js → trace-browser-DLB0mURK.js} +2 -2
- package/dist/ui/assets/{trace-browser-BBITQELO.js.map → trace-browser-DLB0mURK.js.map} +1 -1
- package/dist/ui/assets/{transcript-item-BvaA1PBu.js → transcript-item-DM71m6Mp.js} +2 -2
- package/dist/ui/assets/{transcript-item-BvaA1PBu.js.map → transcript-item-DM71m6Mp.js.map} +1 -1
- package/dist/ui/index.html +1 -1
- package/package.json +4 -4
- package/dist/ui/assets/index-ChlKOnbD.js +0 -54
- package/dist/ui/assets/index-ChlKOnbD.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/runtime/studio.ts
|
|
2
2
|
import {
|
|
3
|
-
createHook as
|
|
3
|
+
createHook as createHook2
|
|
4
4
|
} from "@anvia/core/agent";
|
|
5
5
|
import { Message } from "@anvia/core/completion";
|
|
6
6
|
import { Agent } from "@anvia/core/internal/agent";
|
|
@@ -8,6 +8,17 @@ import { Pipeline } from "@anvia/core/pipeline";
|
|
|
8
8
|
import { serve } from "@hono/node-server";
|
|
9
9
|
import { Hono as HonoApp } from "hono";
|
|
10
10
|
|
|
11
|
+
// src/runtime/compact.ts
|
|
12
|
+
function compact(obj) {
|
|
13
|
+
const result = {};
|
|
14
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
15
|
+
if (value !== void 0) {
|
|
16
|
+
result[key] = value;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
21
|
+
|
|
11
22
|
// src/runtime/json.ts
|
|
12
23
|
function toJsonValue(value) {
|
|
13
24
|
return toJsonValueInternal(value, /* @__PURE__ */ new WeakSet());
|
|
@@ -65,6 +76,20 @@ function serializeUnknown(error) {
|
|
|
65
76
|
}
|
|
66
77
|
return toJsonValue(error);
|
|
67
78
|
}
|
|
79
|
+
function formatJson(value) {
|
|
80
|
+
try {
|
|
81
|
+
return JSON.stringify(value, null, 2);
|
|
82
|
+
} catch {
|
|
83
|
+
return String(value);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function formatUnknown(value) {
|
|
87
|
+
try {
|
|
88
|
+
return JSON.stringify(value);
|
|
89
|
+
} catch {
|
|
90
|
+
return void 0;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
68
93
|
|
|
69
94
|
// src/traces/trace-observer.ts
|
|
70
95
|
var StudioTraceObserver = class {
|
|
@@ -191,7 +216,7 @@ var StudioRunTraceObserver = class {
|
|
|
191
216
|
const trace = {
|
|
192
217
|
id: this.props.id,
|
|
193
218
|
sessionId,
|
|
194
|
-
...
|
|
219
|
+
...compact({ name: this.props.args.trace?.name }),
|
|
195
220
|
status,
|
|
196
221
|
trace: this.trace,
|
|
197
222
|
startedAt: this.startedAt.toISOString(),
|
|
@@ -202,9 +227,9 @@ var StudioRunTraceObserver = class {
|
|
|
202
227
|
prompt: this.props.args.prompt,
|
|
203
228
|
history: this.props.args.history
|
|
204
229
|
}),
|
|
205
|
-
...
|
|
206
|
-
...
|
|
207
|
-
...
|
|
230
|
+
...compact({ output: result.output }),
|
|
231
|
+
...compact({ error: result.error }),
|
|
232
|
+
...compact({ usage: result.usage }),
|
|
208
233
|
metadata,
|
|
209
234
|
observations: this.observations,
|
|
210
235
|
observationCount: this.observations.length
|
|
@@ -234,7 +259,7 @@ var ChildAgentToolTraceAccumulator = class {
|
|
|
234
259
|
this.agentStarts.set(agentId, {
|
|
235
260
|
startedAt: /* @__PURE__ */ new Date(),
|
|
236
261
|
agentId,
|
|
237
|
-
...
|
|
262
|
+
...compact({ agentName })
|
|
238
263
|
});
|
|
239
264
|
}
|
|
240
265
|
if (child.type === "turn_start") {
|
|
@@ -245,7 +270,7 @@ var ChildAgentToolTraceAccumulator = class {
|
|
|
245
270
|
history: child.history
|
|
246
271
|
}),
|
|
247
272
|
agentId,
|
|
248
|
-
...
|
|
273
|
+
...compact({ agentName }),
|
|
249
274
|
childTurn
|
|
250
275
|
});
|
|
251
276
|
return;
|
|
@@ -261,7 +286,7 @@ var ChildAgentToolTraceAccumulator = class {
|
|
|
261
286
|
status: "success",
|
|
262
287
|
turn: this.parent.turn,
|
|
263
288
|
startedAt: start?.startedAt ?? /* @__PURE__ */ new Date(),
|
|
264
|
-
...
|
|
289
|
+
...compact({ input: start?.input }),
|
|
265
290
|
output: toJsonValue(child.response),
|
|
266
291
|
metadata: this.childMetadata(agentId, agentName, childTurn)
|
|
267
292
|
})
|
|
@@ -276,10 +301,10 @@ var ChildAgentToolTraceAccumulator = class {
|
|
|
276
301
|
this.toolStarts.push({
|
|
277
302
|
startedAt: /* @__PURE__ */ new Date(),
|
|
278
303
|
agentId,
|
|
279
|
-
...
|
|
304
|
+
...compact({ agentName }),
|
|
280
305
|
childTurn,
|
|
281
306
|
toolName,
|
|
282
|
-
...
|
|
307
|
+
...compact({ toolCallId: callId }),
|
|
283
308
|
input: toJsonValue(toolCallFunction?.arguments ?? {}),
|
|
284
309
|
completed: false
|
|
285
310
|
});
|
|
@@ -301,12 +326,12 @@ var ChildAgentToolTraceAccumulator = class {
|
|
|
301
326
|
status: "success",
|
|
302
327
|
turn: this.parent.turn,
|
|
303
328
|
startedAt: start?.startedAt ?? /* @__PURE__ */ new Date(),
|
|
304
|
-
...
|
|
329
|
+
...compact({ input }),
|
|
305
330
|
...typeof child.result === "string" ? { output: parseOrString(child.result) } : {},
|
|
306
331
|
metadata: {
|
|
307
332
|
...this.childMetadata(agentId, agentName, childTurn),
|
|
308
|
-
...
|
|
309
|
-
...
|
|
333
|
+
...compact({ toolCallId }),
|
|
334
|
+
...compact({ internalCallId })
|
|
310
335
|
}
|
|
311
336
|
})
|
|
312
337
|
);
|
|
@@ -404,10 +429,10 @@ function traceObservation(props) {
|
|
|
404
429
|
startedAt: props.startedAt.toISOString(),
|
|
405
430
|
endedAt: endedAt.toISOString(),
|
|
406
431
|
durationMs: durationMs(props.startedAt, endedAt),
|
|
407
|
-
...
|
|
408
|
-
...
|
|
409
|
-
...
|
|
410
|
-
...
|
|
432
|
+
...compact({ input: props.input }),
|
|
433
|
+
...compact({ output: props.output }),
|
|
434
|
+
...compact({ error: props.error }),
|
|
435
|
+
...compact({ metadata: props.metadata })
|
|
411
436
|
};
|
|
412
437
|
}
|
|
413
438
|
function traceMetadata(args, messages) {
|
|
@@ -816,385 +841,334 @@ function escapeHtml(value) {
|
|
|
816
841
|
return value.replaceAll("&", "&").replaceAll('"', """).replaceAll("<", "<").replaceAll(">", ">");
|
|
817
842
|
}
|
|
818
843
|
|
|
819
|
-
// src/runtime/
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
} from "@anvia/core/agent";
|
|
823
|
-
import {
|
|
824
|
-
parseToolArgs
|
|
825
|
-
} from "@anvia/core/tool";
|
|
826
|
-
|
|
827
|
-
// src/runtime/transcript.ts
|
|
828
|
-
function renumberTranscript(entries) {
|
|
829
|
-
return entries.map((entry, entryId) => ({ ...entry, entryId }));
|
|
844
|
+
// src/runtime/type-guards.ts
|
|
845
|
+
function isObject(value) {
|
|
846
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
830
847
|
}
|
|
831
|
-
function
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
if (message.role === "user") {
|
|
838
|
-
const attachments = attachmentsFromMessage(message);
|
|
839
|
-
let textEntryAdded = false;
|
|
840
|
-
for (const content of message.content) {
|
|
841
|
-
if (content.type === "text") {
|
|
842
|
-
transcript.push({
|
|
843
|
-
entryId: transcript.length,
|
|
844
|
-
kind: "message",
|
|
845
|
-
role: "user",
|
|
846
|
-
text: content.text,
|
|
847
|
-
...attachments.length === 0 ? {} : { attachments }
|
|
848
|
-
});
|
|
849
|
-
textEntryAdded = true;
|
|
850
|
-
}
|
|
851
|
-
}
|
|
852
|
-
if (!textEntryAdded && attachments.length > 0) {
|
|
853
|
-
transcript.push({
|
|
854
|
-
entryId: transcript.length,
|
|
855
|
-
kind: "message",
|
|
856
|
-
role: "user",
|
|
857
|
-
text: "",
|
|
858
|
-
attachments
|
|
859
|
-
});
|
|
860
|
-
}
|
|
861
|
-
continue;
|
|
862
|
-
}
|
|
863
|
-
if (message.role === "tool") {
|
|
864
|
-
for (const content of message.content) {
|
|
865
|
-
transcript.push({
|
|
866
|
-
entryId: transcript.length,
|
|
867
|
-
kind: "tool",
|
|
868
|
-
toolName: "tool_result",
|
|
869
|
-
callId: content.callId ?? content.id,
|
|
870
|
-
result: content.content.map(
|
|
871
|
-
(item) => "text" in item ? item.text : `[image:${item.mediaType ?? "image/png"}]`
|
|
872
|
-
).join("\n"),
|
|
873
|
-
structuredResult: content.content
|
|
874
|
-
});
|
|
875
|
-
}
|
|
876
|
-
continue;
|
|
877
|
-
}
|
|
878
|
-
for (const content of message.content) {
|
|
879
|
-
if (content.type === "text") {
|
|
880
|
-
appendAssistantTranscriptText(transcript, content.text);
|
|
881
|
-
} else if (content.type === "reasoning") {
|
|
882
|
-
transcript.push({
|
|
883
|
-
entryId: transcript.length,
|
|
884
|
-
kind: "reasoning",
|
|
885
|
-
...content.id === void 0 ? {} : { reasoningId: content.id },
|
|
886
|
-
text: content.text
|
|
887
|
-
});
|
|
888
|
-
} else if (content.type === "tool_call") {
|
|
889
|
-
transcript.push({
|
|
890
|
-
entryId: transcript.length,
|
|
891
|
-
kind: "tool",
|
|
892
|
-
toolName: content.function.name,
|
|
893
|
-
callId: content.callId ?? content.id,
|
|
894
|
-
args: formatJson(content.function.arguments)
|
|
895
|
-
});
|
|
896
|
-
}
|
|
897
|
-
}
|
|
848
|
+
function isJsonObject(value) {
|
|
849
|
+
return isObject(value) && Object.values(value).every(isJsonValue);
|
|
850
|
+
}
|
|
851
|
+
function isJsonValue(value) {
|
|
852
|
+
if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
853
|
+
return true;
|
|
898
854
|
}
|
|
899
|
-
|
|
855
|
+
if (Array.isArray(value)) {
|
|
856
|
+
return value.every(isJsonValue);
|
|
857
|
+
}
|
|
858
|
+
return isJsonObject(value);
|
|
900
859
|
}
|
|
901
|
-
function
|
|
902
|
-
|
|
903
|
-
|
|
860
|
+
function isMessageInput(value) {
|
|
861
|
+
return typeof value === "string" || isMessage(value);
|
|
862
|
+
}
|
|
863
|
+
function isMessage(value) {
|
|
864
|
+
if (!isObject(value) || typeof value.role !== "string") {
|
|
865
|
+
return false;
|
|
904
866
|
}
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
];
|
|
913
|
-
}
|
|
914
|
-
if (content.type === "document") {
|
|
915
|
-
return [
|
|
916
|
-
{
|
|
917
|
-
kind: "document",
|
|
918
|
-
...content.source.filename === void 0 ? {} : { name: content.source.filename },
|
|
919
|
-
...content.source.mediaType === void 0 ? {} : { mediaType: content.source.mediaType },
|
|
920
|
-
...content.source.type === "base64" ? { data: content.source.data } : content.source.type === "url" ? { url: content.source.url } : {}
|
|
921
|
-
}
|
|
922
|
-
];
|
|
923
|
-
}
|
|
924
|
-
return [];
|
|
925
|
-
});
|
|
867
|
+
if (value.role === "system") {
|
|
868
|
+
return typeof value.content === "string";
|
|
869
|
+
}
|
|
870
|
+
if (value.role === "user" || value.role === "assistant" || value.role === "tool") {
|
|
871
|
+
return Array.isArray(value.content);
|
|
872
|
+
}
|
|
873
|
+
return false;
|
|
926
874
|
}
|
|
927
|
-
function
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
last.text = `${last.text}${text}`;
|
|
931
|
-
return;
|
|
875
|
+
function isAgentTraceOptions(value) {
|
|
876
|
+
if (!isObject(value)) {
|
|
877
|
+
return false;
|
|
932
878
|
}
|
|
933
|
-
|
|
934
|
-
entryId: transcript.length,
|
|
935
|
-
kind: "message",
|
|
936
|
-
role: "assistant",
|
|
937
|
-
text
|
|
938
|
-
});
|
|
879
|
+
return optionalString(value.name) && optionalString(value.userId) && optionalString(value.sessionId) && optionalString(value.version) && optionalString(value.traceId) && optionalBoolean(value.failOnObserverError) && optionalStringArray(value.tags) && optionalObject(value.metadata);
|
|
939
880
|
}
|
|
940
|
-
function
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
881
|
+
function isNonNegativeInteger(value) {
|
|
882
|
+
return Number.isInteger(value) && typeof value === "number" && value >= 0;
|
|
883
|
+
}
|
|
884
|
+
function isPositiveInteger(value) {
|
|
885
|
+
return Number.isInteger(value) && typeof value === "number" && value > 0;
|
|
886
|
+
}
|
|
887
|
+
function optionalString(value) {
|
|
888
|
+
return value === void 0 || typeof value === "string";
|
|
889
|
+
}
|
|
890
|
+
function optionalBoolean(value) {
|
|
891
|
+
return value === void 0 || typeof value === "boolean";
|
|
892
|
+
}
|
|
893
|
+
function optionalStringArray(value) {
|
|
894
|
+
return value === void 0 || Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
895
|
+
}
|
|
896
|
+
function optionalObject(value) {
|
|
897
|
+
return value === void 0 || isObject(value);
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
// src/runtime/http.ts
|
|
901
|
+
function errorResponse(c, status, code, message, details) {
|
|
902
|
+
const body = {
|
|
903
|
+
error: {
|
|
904
|
+
code,
|
|
905
|
+
message
|
|
906
|
+
}
|
|
907
|
+
};
|
|
908
|
+
if (details !== void 0) {
|
|
909
|
+
body.error.details = details;
|
|
945
910
|
}
|
|
911
|
+
return c.json(body, status);
|
|
912
|
+
}
|
|
913
|
+
function unsupportedCapability(c, capability) {
|
|
914
|
+
return errorResponse(
|
|
915
|
+
c,
|
|
916
|
+
501,
|
|
917
|
+
"unsupported_capability",
|
|
918
|
+
`Capability "${capability}" is not implemented by this runner`,
|
|
919
|
+
{ capability }
|
|
920
|
+
);
|
|
921
|
+
}
|
|
922
|
+
function serializeError(error) {
|
|
923
|
+
return serializeUnknown(error);
|
|
946
924
|
}
|
|
947
925
|
|
|
948
|
-
// src/
|
|
949
|
-
function
|
|
950
|
-
|
|
926
|
+
// src/runtime/query.ts
|
|
927
|
+
function optionalQueryString(value) {
|
|
928
|
+
const trimmed = value?.trim();
|
|
929
|
+
return trimmed === void 0 || trimmed.length === 0 ? void 0 : trimmed;
|
|
951
930
|
}
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
traces = /* @__PURE__ */ new Map();
|
|
956
|
-
pipelineLogs = /* @__PURE__ */ new Map();
|
|
957
|
-
pipelineRuns = /* @__PURE__ */ new Map();
|
|
958
|
-
listSessions(options) {
|
|
959
|
-
return [...this.sessions.values()].filter((session) => options.agentId === void 0 || session.agentId === options.agentId).sort((left, right) => Date.parse(right.updatedAt) - Date.parse(left.updatedAt)).slice(0, options.limit).map(sessionSummary);
|
|
960
|
-
}
|
|
961
|
-
createSession(input) {
|
|
962
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
963
|
-
const session = {
|
|
964
|
-
id: input.id,
|
|
965
|
-
agentId: input.agentId,
|
|
966
|
-
...input.title === void 0 ? {} : { title: input.title },
|
|
967
|
-
createdAt: now,
|
|
968
|
-
updatedAt: now,
|
|
969
|
-
messageCount: 0,
|
|
970
|
-
...input.metadata === void 0 ? {} : { metadata: input.metadata },
|
|
971
|
-
messages: [],
|
|
972
|
-
runs: [],
|
|
973
|
-
logs: []
|
|
974
|
-
};
|
|
975
|
-
this.sessions.set(input.id, session);
|
|
976
|
-
return sessionSummary(session);
|
|
931
|
+
function parseLimit(value, defaultMax = 50, max = 100) {
|
|
932
|
+
if (value === void 0 || value.trim().length === 0) {
|
|
933
|
+
return defaultMax;
|
|
977
934
|
}
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
return
|
|
935
|
+
const limit = Number(value);
|
|
936
|
+
if (!Number.isInteger(limit) || limit <= 0) {
|
|
937
|
+
return void 0;
|
|
981
938
|
}
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
delete session.metadata;
|
|
989
|
-
} else {
|
|
990
|
-
session.metadata = metadata;
|
|
991
|
-
}
|
|
992
|
-
session.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
993
|
-
return materializeSession(session);
|
|
939
|
+
return Math.min(limit, max);
|
|
940
|
+
}
|
|
941
|
+
function parseTraceStatus(value) {
|
|
942
|
+
const status = optionalQueryString(value);
|
|
943
|
+
if (status === void 0) {
|
|
944
|
+
return void 0;
|
|
994
945
|
}
|
|
995
|
-
|
|
996
|
-
|
|
946
|
+
return status === "running" || status === "success" || status === "error" ? status : false;
|
|
947
|
+
}
|
|
948
|
+
function parseAfter(value) {
|
|
949
|
+
if (value === void 0 || value.trim().length === 0) {
|
|
950
|
+
return void 0;
|
|
997
951
|
}
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
session.messages.push(...input.messages);
|
|
1002
|
-
session.messageCount = session.messages.length;
|
|
1003
|
-
session.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1004
|
-
}
|
|
1005
|
-
return Promise.resolve();
|
|
952
|
+
const after = Number(value);
|
|
953
|
+
if (!Number.isInteger(after) || after < 0) {
|
|
954
|
+
return false;
|
|
1006
955
|
}
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
956
|
+
return after;
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
// src/runtime/approvals.ts
|
|
960
|
+
function registerApprovalRoutes(app, approvals) {
|
|
961
|
+
app.get("/approvals", (c) => {
|
|
962
|
+
const status = parseApprovalStatus(c.req.query("status"));
|
|
963
|
+
if (status === false) {
|
|
964
|
+
return errorResponse(c, 400, "bad_request", "status must be pending or resolved");
|
|
1014
965
|
}
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
transcript: transcriptFromMessages(input.messages),
|
|
1022
|
-
status: "error",
|
|
1023
|
-
error: serializeJsonError(input.error)
|
|
1024
|
-
});
|
|
1025
|
-
}
|
|
1026
|
-
saveSessionRunTranscript(input) {
|
|
1027
|
-
const session = this.sessions.get(input.id);
|
|
1028
|
-
if (session === void 0) {
|
|
1029
|
-
return void 0;
|
|
966
|
+
const options = {};
|
|
967
|
+
const runId = optionalQueryString(c.req.query("runId"));
|
|
968
|
+
const agentId = optionalQueryString(c.req.query("agentId"));
|
|
969
|
+
const sessionId = optionalQueryString(c.req.query("sessionId"));
|
|
970
|
+
if (status !== void 0) {
|
|
971
|
+
options.status = status;
|
|
1030
972
|
}
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
const run = {
|
|
1034
|
-
...input,
|
|
1035
|
-
transcript: renumberTranscript(input.transcript),
|
|
1036
|
-
createdAt: existingIndex === -1 ? now : session.runs[existingIndex]?.createdAt ?? now,
|
|
1037
|
-
updatedAt: now
|
|
1038
|
-
};
|
|
1039
|
-
if (existingIndex === -1) {
|
|
1040
|
-
session.runs.push(run);
|
|
1041
|
-
} else {
|
|
1042
|
-
session.runs[existingIndex] = run;
|
|
973
|
+
if (runId !== void 0) {
|
|
974
|
+
options.runId = runId;
|
|
1043
975
|
}
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
}
|
|
1047
|
-
appendSessionLog(input) {
|
|
1048
|
-
const session = this.sessions.get(input.sessionId);
|
|
1049
|
-
const logs = session?.logs ?? [];
|
|
1050
|
-
const entry = {
|
|
1051
|
-
id: globalThis.crypto.randomUUID(),
|
|
1052
|
-
sessionId: input.sessionId,
|
|
1053
|
-
...input.runId === void 0 ? {} : { runId: input.runId },
|
|
1054
|
-
sequence: logs.length,
|
|
1055
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1056
|
-
level: input.level,
|
|
1057
|
-
category: input.category,
|
|
1058
|
-
event: input.event,
|
|
1059
|
-
message: input.message,
|
|
1060
|
-
...input.metadata === void 0 ? {} : { metadata: input.metadata }
|
|
1061
|
-
};
|
|
1062
|
-
if (session !== void 0) {
|
|
1063
|
-
session.logs.push(entry);
|
|
1064
|
-
session.updatedAt = entry.timestamp;
|
|
976
|
+
if (agentId !== void 0) {
|
|
977
|
+
options.agentId = agentId;
|
|
1065
978
|
}
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
listSessionLogs(options) {
|
|
1069
|
-
return (this.sessions.get(options.sessionId)?.logs ?? []).filter((log) => options.after === void 0 || log.sequence > options.after).slice(0, options.limit);
|
|
1070
|
-
}
|
|
1071
|
-
deleteSession(id) {
|
|
1072
|
-
for (const trace of this.traces.values()) {
|
|
1073
|
-
if (trace.sessionId === id) {
|
|
1074
|
-
this.traces.delete(trace.id);
|
|
1075
|
-
}
|
|
979
|
+
if (sessionId !== void 0) {
|
|
980
|
+
options.sessionId = sessionId;
|
|
1076
981
|
}
|
|
1077
|
-
return
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
level: input.level,
|
|
1101
|
-
category: input.category,
|
|
1102
|
-
event: input.event,
|
|
1103
|
-
message: input.message,
|
|
1104
|
-
...input.metadata === void 0 ? {} : { metadata: input.metadata }
|
|
1105
|
-
};
|
|
1106
|
-
this.pipelineLogs.set(input.pipelineId, [...logs, entry]);
|
|
1107
|
-
return entry;
|
|
982
|
+
return c.json({
|
|
983
|
+
approvals: approvals.list(options)
|
|
984
|
+
});
|
|
985
|
+
});
|
|
986
|
+
app.post("/approvals/:approvalId/decision", async (c) => {
|
|
987
|
+
const body = await parseApprovalDecisionRequest(c);
|
|
988
|
+
if ("error" in body) {
|
|
989
|
+
return body.error;
|
|
990
|
+
}
|
|
991
|
+
const result = approvals.decide(c.req.param("approvalId"), body);
|
|
992
|
+
if (result === "missing") {
|
|
993
|
+
return errorResponse(c, 404, "not_found", "Approval not found");
|
|
994
|
+
}
|
|
995
|
+
if (result === "resolved") {
|
|
996
|
+
return errorResponse(c, 409, "conflict", "Approval is already resolved");
|
|
997
|
+
}
|
|
998
|
+
return c.json(result);
|
|
999
|
+
});
|
|
1000
|
+
}
|
|
1001
|
+
function parseApprovalStatus(value) {
|
|
1002
|
+
const status = optionalQueryString(value);
|
|
1003
|
+
if (status === void 0) {
|
|
1004
|
+
return void 0;
|
|
1108
1005
|
}
|
|
1109
|
-
|
|
1110
|
-
|
|
1006
|
+
return status === "pending" || status === "resolved" ? status : false;
|
|
1007
|
+
}
|
|
1008
|
+
async function parseApprovalDecisionRequest(c) {
|
|
1009
|
+
let body;
|
|
1010
|
+
try {
|
|
1011
|
+
body = await c.req.json();
|
|
1012
|
+
} catch {
|
|
1013
|
+
return { error: errorResponse(c, 400, "bad_request", "Request body must be JSON") };
|
|
1111
1014
|
}
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
runId: input.runId,
|
|
1115
|
-
pipelineId: input.pipelineId,
|
|
1116
|
-
status: input.status,
|
|
1117
|
-
input: input.input,
|
|
1118
|
-
...input.output === void 0 ? {} : { output: input.output },
|
|
1119
|
-
...input.error === void 0 ? {} : { error: input.error },
|
|
1120
|
-
...input.metadata === void 0 ? {} : { metadata: input.metadata },
|
|
1121
|
-
startedAt: input.startedAt,
|
|
1122
|
-
...input.endedAt === void 0 ? {} : { endedAt: input.endedAt },
|
|
1123
|
-
...input.durationMs === void 0 ? {} : { durationMs: input.durationMs }
|
|
1124
|
-
};
|
|
1125
|
-
this.pipelineRuns.set(input.runId, record);
|
|
1126
|
-
return record;
|
|
1015
|
+
if (!isObject(body)) {
|
|
1016
|
+
return { error: errorResponse(c, 400, "bad_request", "Request body must be an object") };
|
|
1127
1017
|
}
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
return run?.pipelineId === options.pipelineId ? run : void 0;
|
|
1018
|
+
if (typeof body.approved !== "boolean") {
|
|
1019
|
+
return { error: errorResponse(c, 400, "bad_request", "approved must be a boolean") };
|
|
1131
1020
|
}
|
|
1132
|
-
|
|
1133
|
-
return
|
|
1021
|
+
if ("reason" in body && typeof body.reason !== "string") {
|
|
1022
|
+
return { error: errorResponse(c, 400, "bad_request", "reason must be a string") };
|
|
1134
1023
|
}
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
agentId: session.agentId,
|
|
1140
|
-
...session.title === void 0 ? {} : { title: session.title },
|
|
1141
|
-
createdAt: session.createdAt,
|
|
1142
|
-
updatedAt: session.updatedAt,
|
|
1143
|
-
messageCount: session.messages.length,
|
|
1144
|
-
...session.metadata === void 0 ? {} : { metadata: session.metadata }
|
|
1145
|
-
};
|
|
1024
|
+
return compact({
|
|
1025
|
+
approved: body.approved,
|
|
1026
|
+
reason: typeof body.reason === "string" && body.reason.trim().length > 0 ? body.reason.trim() : void 0
|
|
1027
|
+
});
|
|
1146
1028
|
}
|
|
1147
|
-
function
|
|
1029
|
+
function createApprovalRuntime() {
|
|
1030
|
+
const approvals = /* @__PURE__ */ new Map();
|
|
1148
1031
|
return {
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1032
|
+
approvals,
|
|
1033
|
+
createApprovals(context) {
|
|
1034
|
+
return {
|
|
1035
|
+
async handler(request) {
|
|
1036
|
+
const decision = await requestApproval(
|
|
1037
|
+
approvals,
|
|
1038
|
+
context,
|
|
1039
|
+
compact({
|
|
1040
|
+
toolName: request.toolName,
|
|
1041
|
+
toolCallId: request.toolCallId,
|
|
1042
|
+
internalCallId: request.internalCallId,
|
|
1043
|
+
args: request.rawArgs,
|
|
1044
|
+
reason: request.reason,
|
|
1045
|
+
rejectMessage: request.rejectMessage
|
|
1046
|
+
})
|
|
1047
|
+
);
|
|
1048
|
+
return decision.approved ? compact({ approved: true, reason: decision.reason }) : compact({ approved: false, reason: decision.reason });
|
|
1049
|
+
}
|
|
1050
|
+
};
|
|
1051
|
+
},
|
|
1052
|
+
list(options) {
|
|
1053
|
+
return [...approvals.values()].filter((approval) => {
|
|
1054
|
+
if (options.status === "pending" && approval.status !== "pending") {
|
|
1055
|
+
return false;
|
|
1056
|
+
}
|
|
1057
|
+
if (options.status === "resolved" && approval.status === "pending") {
|
|
1058
|
+
return false;
|
|
1059
|
+
}
|
|
1060
|
+
if (options.runId !== void 0 && approval.runId !== options.runId) {
|
|
1061
|
+
return false;
|
|
1062
|
+
}
|
|
1063
|
+
if (options.agentId !== void 0 && approval.agentId !== options.agentId) {
|
|
1064
|
+
return false;
|
|
1065
|
+
}
|
|
1066
|
+
if (options.sessionId !== void 0 && approval.sessionId !== options.sessionId) {
|
|
1067
|
+
return false;
|
|
1068
|
+
}
|
|
1069
|
+
return true;
|
|
1070
|
+
}).map(publicApproval);
|
|
1071
|
+
},
|
|
1072
|
+
decide(id, decision) {
|
|
1073
|
+
const approval = approvals.get(id);
|
|
1074
|
+
if (approval === void 0) {
|
|
1075
|
+
return "missing";
|
|
1076
|
+
}
|
|
1077
|
+
if (!isPendingApproval(approval)) {
|
|
1078
|
+
return "resolved";
|
|
1079
|
+
}
|
|
1080
|
+
const reason = decision.approved ? decision.reason : decision.reason ?? approval.rejectMessage ?? "Rejected in Anvia Studio.";
|
|
1081
|
+
const resolved = resolveApproval(
|
|
1082
|
+
approval,
|
|
1083
|
+
decision.approved ? "approved" : "rejected",
|
|
1084
|
+
compact({ reason })
|
|
1085
|
+
);
|
|
1086
|
+
approvals.set(id, resolved);
|
|
1087
|
+
approval.emit?.({ type: "tool_approval_result", approval: resolved });
|
|
1088
|
+
approval.resolve(
|
|
1089
|
+
compact({
|
|
1090
|
+
approved: decision.approved,
|
|
1091
|
+
reason
|
|
1092
|
+
})
|
|
1093
|
+
);
|
|
1094
|
+
return publicApproval(resolved);
|
|
1095
|
+
}
|
|
1152
1096
|
};
|
|
1153
1097
|
}
|
|
1154
|
-
function
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1098
|
+
async function requestApproval(approvals, context, request) {
|
|
1099
|
+
const id = globalThis.crypto.randomUUID();
|
|
1100
|
+
const approval = {
|
|
1101
|
+
...compact({
|
|
1102
|
+
id,
|
|
1103
|
+
runId: context.runId,
|
|
1104
|
+
agentId: context.agentId,
|
|
1105
|
+
sessionId: context.sessionId,
|
|
1106
|
+
toolName: request.toolName,
|
|
1107
|
+
callId: request.toolCallId,
|
|
1108
|
+
internalCallId: request.internalCallId,
|
|
1109
|
+
args: request.args,
|
|
1110
|
+
status: "pending",
|
|
1111
|
+
requestedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1112
|
+
reason: request.reason,
|
|
1113
|
+
rejectMessage: request.rejectMessage,
|
|
1114
|
+
emit: context.emit
|
|
1115
|
+
}),
|
|
1116
|
+
resolve: () => {
|
|
1117
|
+
}
|
|
1168
1118
|
};
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1119
|
+
const decision = new Promise((resolve2) => {
|
|
1120
|
+
approval.resolve = (decision2) => {
|
|
1121
|
+
const current = approvals.get(id);
|
|
1122
|
+
if (!isPendingApproval(current)) {
|
|
1123
|
+
if (current !== void 0) {
|
|
1124
|
+
resolve2(
|
|
1125
|
+
compact({
|
|
1126
|
+
approved: current.status === "approved",
|
|
1127
|
+
reason: current.reason
|
|
1128
|
+
})
|
|
1129
|
+
);
|
|
1130
|
+
}
|
|
1131
|
+
return;
|
|
1132
|
+
}
|
|
1133
|
+
const reason = decision2.approved ? decision2.reason : decision2.reason ?? request.rejectMessage ?? "Rejected in Anvia Studio.";
|
|
1134
|
+
const resolved = resolveApproval(
|
|
1135
|
+
current,
|
|
1136
|
+
decision2.approved ? "approved" : "rejected",
|
|
1137
|
+
compact({ reason })
|
|
1138
|
+
);
|
|
1139
|
+
approvals.set(id, resolved);
|
|
1140
|
+
context.emit?.({ type: "tool_approval_result", approval: resolved });
|
|
1141
|
+
resolve2(
|
|
1142
|
+
compact({
|
|
1143
|
+
approved: decision2.approved,
|
|
1144
|
+
reason
|
|
1145
|
+
})
|
|
1146
|
+
);
|
|
1183
1147
|
};
|
|
1184
|
-
}
|
|
1185
|
-
|
|
1148
|
+
});
|
|
1149
|
+
approvals.set(id, approval);
|
|
1150
|
+
context.emit?.({ type: "tool_approval_request", approval: publicApproval(approval) });
|
|
1151
|
+
return decision;
|
|
1186
1152
|
}
|
|
1187
|
-
function
|
|
1188
|
-
return
|
|
1153
|
+
function isPendingApproval(approval) {
|
|
1154
|
+
return approval !== void 0 && approval.status === "pending" && "resolve" in approval;
|
|
1189
1155
|
}
|
|
1190
|
-
function
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1156
|
+
function resolveApproval(approval, status, options = {}) {
|
|
1157
|
+
return publicApproval({
|
|
1158
|
+
...approval,
|
|
1159
|
+
...compact({
|
|
1160
|
+
status,
|
|
1161
|
+
resolvedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1162
|
+
reason: options.reason
|
|
1163
|
+
})
|
|
1164
|
+
});
|
|
1165
|
+
}
|
|
1166
|
+
function publicApproval(approval) {
|
|
1167
|
+
const { emit, rejectMessage, resolve: resolve2, ...rest } = approval;
|
|
1168
|
+
void emit;
|
|
1169
|
+
void rejectMessage;
|
|
1170
|
+
void resolve2;
|
|
1171
|
+
return rest;
|
|
1198
1172
|
}
|
|
1199
1173
|
|
|
1200
1174
|
// src/runtime/models.ts
|
|
@@ -1220,12 +1194,12 @@ function createStudioModelRegistry(config) {
|
|
|
1220
1194
|
providers.set(id, {
|
|
1221
1195
|
...provider,
|
|
1222
1196
|
id,
|
|
1223
|
-
...provider.defaultModel
|
|
1197
|
+
...compact({ defaultModel: provider.defaultModel !== void 0 ? normalizeModelId(provider.defaultModel) : void 0 }),
|
|
1224
1198
|
staticModels
|
|
1225
1199
|
});
|
|
1226
1200
|
}
|
|
1227
1201
|
return {
|
|
1228
|
-
...config.default
|
|
1202
|
+
...compact({ defaultModel: config.default !== void 0 ? normalizeModelRef(config.default) : void 0 }),
|
|
1229
1203
|
providers,
|
|
1230
1204
|
agentPolicies: normalizeAgentPolicies(config.agents ?? {}),
|
|
1231
1205
|
modelCache: /* @__PURE__ */ new Map()
|
|
@@ -1241,10 +1215,8 @@ function studioModelsConfig(registry, agents) {
|
|
|
1241
1215
|
);
|
|
1242
1216
|
return {
|
|
1243
1217
|
id: provider.id,
|
|
1244
|
-
...provider.name
|
|
1245
|
-
|
|
1246
|
-
models,
|
|
1247
|
-
...provider.metadata === void 0 ? {} : { metadata: provider.metadata }
|
|
1218
|
+
...compact({ name: provider.name, defaultModel: provider.defaultModel, metadata: provider.metadata }),
|
|
1219
|
+
models
|
|
1248
1220
|
};
|
|
1249
1221
|
});
|
|
1250
1222
|
const agentIds = new Set(agents.map((agent) => agent.id));
|
|
@@ -1253,7 +1225,7 @@ function studioModelsConfig(registry, agents) {
|
|
|
1253
1225
|
);
|
|
1254
1226
|
return {
|
|
1255
1227
|
providers,
|
|
1256
|
-
...
|
|
1228
|
+
...compact({ default: registry.defaultModel }),
|
|
1257
1229
|
agents: agentsConfig
|
|
1258
1230
|
};
|
|
1259
1231
|
}
|
|
@@ -1267,7 +1239,7 @@ function registerModelRoutes(app, props) {
|
|
|
1267
1239
|
);
|
|
1268
1240
|
return c.json({
|
|
1269
1241
|
providers,
|
|
1270
|
-
...
|
|
1242
|
+
...compact({ defaultModel: props.registry.defaultModel })
|
|
1271
1243
|
});
|
|
1272
1244
|
});
|
|
1273
1245
|
app.get("/models/:providerId", async (c) => {
|
|
@@ -1380,9 +1352,9 @@ async function agentModelsCatalog(registry, agent) {
|
|
|
1380
1352
|
const defaultModel = policy?.default ?? registry.defaultModel;
|
|
1381
1353
|
return {
|
|
1382
1354
|
agentId: agent.id,
|
|
1383
|
-
...
|
|
1355
|
+
...compact({ defaultModel }),
|
|
1384
1356
|
models: [...models, ...exactPolicyModels],
|
|
1385
|
-
...warnings.length === 0 ?
|
|
1357
|
+
...compact({ warnings: warnings.length === 0 ? void 0 : warnings })
|
|
1386
1358
|
};
|
|
1387
1359
|
}
|
|
1388
1360
|
async function providerCatalog(provider) {
|
|
@@ -1400,14 +1372,15 @@ async function providerCatalog(provider) {
|
|
|
1400
1372
|
model.id,
|
|
1401
1373
|
modelSummary(provider, model.id, {
|
|
1402
1374
|
id: model.id,
|
|
1403
|
-
...
|
|
1404
|
-
...model.description === void 0 ? {} : { description: model.description },
|
|
1375
|
+
...compact({ name: model.name, description: model.description }),
|
|
1405
1376
|
...staticModel ?? {},
|
|
1406
1377
|
metadata: {
|
|
1407
|
-
...
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1378
|
+
...compact({
|
|
1379
|
+
type: model.type,
|
|
1380
|
+
createdAt: model.createdAt,
|
|
1381
|
+
ownedBy: model.ownedBy,
|
|
1382
|
+
contextLength: model.contextLength
|
|
1383
|
+
}),
|
|
1411
1384
|
...staticModel?.metadata ?? {}
|
|
1412
1385
|
}
|
|
1413
1386
|
})
|
|
@@ -1420,11 +1393,8 @@ async function providerCatalog(provider) {
|
|
|
1420
1393
|
}
|
|
1421
1394
|
return {
|
|
1422
1395
|
id: provider.id,
|
|
1423
|
-
...provider.name
|
|
1424
|
-
...
|
|
1425
|
-
models: [...models.values()].sort((left, right) => left.ref.localeCompare(right.ref)),
|
|
1426
|
-
...provider.metadata === void 0 ? {} : { metadata: provider.metadata },
|
|
1427
|
-
...warning === void 0 ? {} : { warning }
|
|
1396
|
+
...compact({ name: provider.name, defaultModel: provider.defaultModel, metadata: provider.metadata, warning }),
|
|
1397
|
+
models: [...models.values()].sort((left, right) => left.ref.localeCompare(right.ref))
|
|
1428
1398
|
};
|
|
1429
1399
|
}
|
|
1430
1400
|
function modelSummary(provider, modelId, model) {
|
|
@@ -1433,7 +1403,7 @@ function modelSummary(provider, modelId, model) {
|
|
|
1433
1403
|
id: modelId,
|
|
1434
1404
|
ref: `${provider.id}:${modelId}`,
|
|
1435
1405
|
providerId: provider.id,
|
|
1436
|
-
...
|
|
1406
|
+
...compact({ providerName: provider.name })
|
|
1437
1407
|
};
|
|
1438
1408
|
}
|
|
1439
1409
|
function ensureModelAllowed(registry, agentId, ref) {
|
|
@@ -1456,21 +1426,18 @@ function normalizeAgentPolicies(policies) {
|
|
|
1456
1426
|
Object.entries(policies).map(([agentId, policy]) => [
|
|
1457
1427
|
agentId.trim(),
|
|
1458
1428
|
{
|
|
1459
|
-
...
|
|
1460
|
-
|
|
1461
|
-
allowed: policy.allowed
|
|
1429
|
+
...compact({
|
|
1430
|
+
default: policy.default !== void 0 ? normalizeModelRef(policy.default) : void 0,
|
|
1431
|
+
allowed: policy.allowed?.map(
|
|
1462
1432
|
(entry) => typeof entry === "string" && entry.trim().endsWith(":*") ? `${normalizeProviderId(entry.trim().slice(0, -2))}:*` : normalizeModelRef(entry)
|
|
1463
1433
|
)
|
|
1464
|
-
}
|
|
1434
|
+
})
|
|
1465
1435
|
}
|
|
1466
1436
|
])
|
|
1467
1437
|
);
|
|
1468
1438
|
}
|
|
1469
1439
|
function publicPolicy(policy) {
|
|
1470
|
-
return {
|
|
1471
|
-
...policy.default === void 0 ? {} : { default: policy.default },
|
|
1472
|
-
...policy.allowed === void 0 ? {} : { allowed: policy.allowed }
|
|
1473
|
-
};
|
|
1440
|
+
return compact({ default: policy.default, allowed: policy.allowed });
|
|
1474
1441
|
}
|
|
1475
1442
|
function modelWarnings(ref, model, request) {
|
|
1476
1443
|
const warnings = [];
|
|
@@ -1572,158 +1539,30 @@ function agentHasMcpTools(agent) {
|
|
|
1572
1539
|
return agentToolItems(agent).some(({ tool }) => mcpServerName(tool) !== void 0);
|
|
1573
1540
|
}
|
|
1574
1541
|
|
|
1575
|
-
// src/runtime/
|
|
1576
|
-
function resolveStores(options) {
|
|
1577
|
-
const defaultStore = defaultStudioStore();
|
|
1578
|
-
const sessions = resolveSessionStore(options, defaultStore);
|
|
1579
|
-
const traces = resolveTraceStore(options, sessions, defaultStore);
|
|
1580
|
-
const pipelineLogs = resolvePipelineLogStore(options, sessions, defaultStore);
|
|
1581
|
-
const pipelineRuns = resolvePipelineRunStore(options, sessions, pipelineLogs, defaultStore);
|
|
1582
|
-
return {
|
|
1583
|
-
...sessions === void 0 ? {} : { sessions },
|
|
1584
|
-
...traces === void 0 ? {} : { traces },
|
|
1585
|
-
...pipelineLogs === void 0 ? {} : { pipelineLogs },
|
|
1586
|
-
...pipelineRuns === void 0 ? {} : { pipelineRuns }
|
|
1587
|
-
};
|
|
1588
|
-
}
|
|
1589
|
-
function defaultStudioStore() {
|
|
1590
|
-
return createInMemoryStudioStore();
|
|
1591
|
-
}
|
|
1592
|
-
function resolveSessionStore(options, defaultStore) {
|
|
1593
|
-
if (options.stores?.sessions === false) {
|
|
1594
|
-
return void 0;
|
|
1595
|
-
}
|
|
1596
|
-
if (options.stores?.sessions !== void 0) {
|
|
1597
|
-
return options.stores.sessions;
|
|
1598
|
-
}
|
|
1599
|
-
return defaultStore;
|
|
1600
|
-
}
|
|
1601
|
-
function resolveTraceStore(options, sessionStore, defaultStore) {
|
|
1602
|
-
if (options.stores?.traces !== void 0) {
|
|
1603
|
-
return options.stores.traces;
|
|
1604
|
-
}
|
|
1605
|
-
if (sessionStore === void 0) {
|
|
1606
|
-
return void 0;
|
|
1607
|
-
}
|
|
1608
|
-
if (isTraceStore(sessionStore)) {
|
|
1609
|
-
return sessionStore;
|
|
1610
|
-
}
|
|
1611
|
-
return defaultStore;
|
|
1612
|
-
}
|
|
1613
|
-
function resolvePipelineLogStore(options, sessionStore, defaultStore) {
|
|
1614
|
-
if (options.stores?.pipelineLogs === false) {
|
|
1615
|
-
return void 0;
|
|
1616
|
-
}
|
|
1617
|
-
if (options.stores?.pipelineLogs !== void 0) {
|
|
1618
|
-
return options.stores.pipelineLogs;
|
|
1619
|
-
}
|
|
1620
|
-
if (sessionStore !== void 0 && isPipelineLogStore(sessionStore)) {
|
|
1621
|
-
return sessionStore;
|
|
1622
|
-
}
|
|
1623
|
-
return defaultStore;
|
|
1624
|
-
}
|
|
1625
|
-
function resolvePipelineRunStore(options, sessionStore, pipelineLogStore, defaultStore) {
|
|
1626
|
-
if (options.stores?.pipelineRuns === false) {
|
|
1627
|
-
return void 0;
|
|
1628
|
-
}
|
|
1629
|
-
if (options.stores?.pipelineRuns !== void 0) {
|
|
1630
|
-
return options.stores.pipelineRuns;
|
|
1631
|
-
}
|
|
1632
|
-
if (sessionStore !== void 0 && isPipelineRunStore(sessionStore)) {
|
|
1633
|
-
return sessionStore;
|
|
1634
|
-
}
|
|
1635
|
-
if (pipelineLogStore !== void 0 && isPipelineRunStore(pipelineLogStore)) {
|
|
1636
|
-
return pipelineLogStore;
|
|
1637
|
-
}
|
|
1638
|
-
return defaultStore;
|
|
1639
|
-
}
|
|
1640
|
-
function isTraceStore(store) {
|
|
1641
|
-
const candidate = store;
|
|
1642
|
-
return typeof candidate.listSessionTraces === "function" && typeof candidate.getTrace === "function" && typeof candidate.saveTrace === "function";
|
|
1643
|
-
}
|
|
1644
|
-
function isPipelineLogStore(store) {
|
|
1645
|
-
const candidate = store;
|
|
1646
|
-
return typeof candidate.appendPipelineLog === "function" && typeof candidate.listPipelineLogs === "function";
|
|
1647
|
-
}
|
|
1648
|
-
function isPipelineRunStore(store) {
|
|
1649
|
-
const candidate = store;
|
|
1650
|
-
return typeof candidate.savePipelineRun === "function" && typeof candidate.getPipelineRun === "function" && typeof candidate.listPipelineRuns === "function";
|
|
1651
|
-
}
|
|
1652
|
-
function unsupportedCapabilities(stores) {
|
|
1653
|
-
return [
|
|
1654
|
-
...stores.sessions === void 0 ? ["sessions"] : [],
|
|
1655
|
-
...stores.traces === void 0 ? ["traces"] : []
|
|
1656
|
-
];
|
|
1657
|
-
}
|
|
1658
|
-
function normalizeAgents(agents) {
|
|
1659
|
-
const ids = /* @__PURE__ */ new Set();
|
|
1660
|
-
return agents.map((agent) => {
|
|
1661
|
-
const id = agent.id.trim();
|
|
1662
|
-
if (id.length === 0) {
|
|
1663
|
-
throw new Error("Studio agent id cannot be empty");
|
|
1664
|
-
}
|
|
1665
|
-
if (ids.has(id)) {
|
|
1666
|
-
throw new Error(`Duplicate runner agent id: ${id}`);
|
|
1667
|
-
}
|
|
1668
|
-
ids.add(id);
|
|
1669
|
-
return { ...agent, id };
|
|
1670
|
-
});
|
|
1671
|
-
}
|
|
1672
|
-
function normalizePipelines(pipelines) {
|
|
1673
|
-
const ids = /* @__PURE__ */ new Set();
|
|
1674
|
-
return pipelines.map((pipeline) => {
|
|
1675
|
-
const id = pipeline.id.trim();
|
|
1676
|
-
if (id.length === 0) {
|
|
1677
|
-
throw new Error("Studio pipeline id cannot be empty");
|
|
1678
|
-
}
|
|
1679
|
-
if (ids.has(id)) {
|
|
1680
|
-
throw new Error(`Duplicate Studio pipeline id: ${id}`);
|
|
1681
|
-
}
|
|
1682
|
-
ids.add(id);
|
|
1683
|
-
return { ...pipeline, id };
|
|
1684
|
-
});
|
|
1685
|
-
}
|
|
1686
|
-
function buildConfig(options, agents, pipelines, stores) {
|
|
1687
|
-
const models = options.models === void 0 ? void 0 : studioModelsConfig(createStudioModelRegistry(options.models), agents);
|
|
1688
|
-
return {
|
|
1689
|
-
id: runnerId(options),
|
|
1690
|
-
...options.name === void 0 ? {} : { name: options.name },
|
|
1691
|
-
...options.description === void 0 ? {} : { description: options.description },
|
|
1692
|
-
...options.version === void 0 ? {} : { version: options.version },
|
|
1693
|
-
agents: agents.map(agentConfig),
|
|
1694
|
-
...models === void 0 ? {} : { models },
|
|
1695
|
-
pipelines: pipelines.map(pipelineConfig),
|
|
1696
|
-
evals: options.evals.map(evalConfig),
|
|
1697
|
-
chat: {
|
|
1698
|
-
quickPrompts: Object.fromEntries(agents.map((agent) => [agent.id, agent.quickPrompts ?? []]))
|
|
1699
|
-
},
|
|
1700
|
-
capabilities: capabilityConfig(options, agents, pipelines, stores),
|
|
1701
|
-
unsupportedCapabilities: unsupportedCapabilities(stores)
|
|
1702
|
-
};
|
|
1703
|
-
}
|
|
1542
|
+
// src/runtime/config.ts
|
|
1704
1543
|
function runnerId(options) {
|
|
1705
1544
|
return options.id ?? "anvia-studio";
|
|
1706
1545
|
}
|
|
1707
1546
|
function agentConfig(agent) {
|
|
1708
1547
|
const name = agent.name ?? agent.agent.name;
|
|
1709
1548
|
const description = agent.description ?? agent.agent.description;
|
|
1710
|
-
return {
|
|
1549
|
+
return compact({
|
|
1711
1550
|
id: agent.id,
|
|
1712
|
-
|
|
1713
|
-
|
|
1551
|
+
name,
|
|
1552
|
+
description,
|
|
1714
1553
|
quickPrompts: agent.quickPrompts ?? [],
|
|
1715
|
-
|
|
1716
|
-
};
|
|
1554
|
+
metadata: agent.metadata
|
|
1555
|
+
});
|
|
1717
1556
|
}
|
|
1718
1557
|
function agentRuntimeSummary(agent) {
|
|
1719
1558
|
const tools = agentToolItems(agent);
|
|
1720
1559
|
const name = agent.name ?? agent.agent.name;
|
|
1721
1560
|
const description = agent.description ?? agent.agent.description;
|
|
1722
|
-
return {
|
|
1561
|
+
return compact({
|
|
1723
1562
|
id: agent.id,
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
model:
|
|
1563
|
+
name,
|
|
1564
|
+
description,
|
|
1565
|
+
model: toJsonValue2(agent.agent.model),
|
|
1727
1566
|
toolCount: tools.length,
|
|
1728
1567
|
staticToolCount: tools.filter((item) => item.source === "static").length,
|
|
1729
1568
|
dynamicToolCount: tools.filter((item) => item.source === "dynamic").length,
|
|
@@ -1735,24 +1574,42 @@ function agentRuntimeSummary(agent) {
|
|
|
1735
1574
|
hasMemory: agent.agent.memory !== void 0,
|
|
1736
1575
|
hasHook: agent.agent.hook !== void 0,
|
|
1737
1576
|
hasOutputSchema: agent.agent.outputSchema !== void 0,
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
};
|
|
1577
|
+
defaultMaxTurns: agent.agent.defaultMaxTurns,
|
|
1578
|
+
metadata: agent.metadata
|
|
1579
|
+
});
|
|
1741
1580
|
}
|
|
1742
1581
|
function pipelineConfig(pipeline) {
|
|
1743
1582
|
const graph = pipeline.pipeline.graph();
|
|
1744
1583
|
const stageNodes = graph.nodes.filter((node) => node.kind !== "input" && node.kind !== "output");
|
|
1745
|
-
return {
|
|
1584
|
+
return compact({
|
|
1746
1585
|
id: pipeline.id,
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1586
|
+
name: pipeline.name,
|
|
1587
|
+
description: pipeline.description,
|
|
1588
|
+
metadata: pipeline.metadata,
|
|
1750
1589
|
stageCount: stageNodes.length,
|
|
1751
1590
|
edgeCount: graph.edges.length,
|
|
1752
1591
|
hasParallelStages: graph.nodes.some((node) => node.kind === "parallel"),
|
|
1753
1592
|
agentCount: graph.nodes.filter((node) => node.kind === "agent").length,
|
|
1754
1593
|
extractorCount: graph.nodes.filter((node) => node.kind === "extractor").length
|
|
1755
|
-
};
|
|
1594
|
+
});
|
|
1595
|
+
}
|
|
1596
|
+
function buildConfig(options, agents, pipelines, stores) {
|
|
1597
|
+
const models = options.models === void 0 ? void 0 : studioModelsConfig(createStudioModelRegistry(options.models), agents);
|
|
1598
|
+
return compact({
|
|
1599
|
+
id: runnerId(options),
|
|
1600
|
+
name: options.name,
|
|
1601
|
+
description: options.description,
|
|
1602
|
+
version: options.version,
|
|
1603
|
+
agents: agents.map(agentConfig),
|
|
1604
|
+
models,
|
|
1605
|
+
pipelines: pipelines.map(pipelineConfig),
|
|
1606
|
+
evals: options.evals.map(evalConfig),
|
|
1607
|
+
chat: {
|
|
1608
|
+
quickPrompts: Object.fromEntries(agents.map((agent) => [agent.id, agent.quickPrompts ?? []]))
|
|
1609
|
+
},
|
|
1610
|
+
capabilities: capabilityConfig(options, agents, pipelines, stores),
|
|
1611
|
+
unsupportedCapabilities: unsupportedCapabilities(stores)
|
|
1612
|
+
});
|
|
1756
1613
|
}
|
|
1757
1614
|
function capabilityConfig(_options, agents, pipelines, stores) {
|
|
1758
1615
|
const capabilities = {
|
|
@@ -1794,357 +1651,24 @@ function capabilityConfig(_options, agents, pipelines, stores) {
|
|
|
1794
1651
|
return capabilities;
|
|
1795
1652
|
}
|
|
1796
1653
|
function evalConfig(suite) {
|
|
1797
|
-
return {
|
|
1654
|
+
return compact({
|
|
1798
1655
|
id: suite.id ?? suite.name,
|
|
1799
1656
|
name: suite.name,
|
|
1800
|
-
|
|
1657
|
+
description: suite.description,
|
|
1801
1658
|
caseCount: suite.cases.length,
|
|
1802
1659
|
metricNames: suite.metrics.map((metric) => metric.name),
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
};
|
|
1806
|
-
}
|
|
1807
|
-
function optionalQueryString(value) {
|
|
1808
|
-
const trimmed = value?.trim();
|
|
1809
|
-
return trimmed === void 0 || trimmed.length === 0 ? void 0 : trimmed;
|
|
1810
|
-
}
|
|
1811
|
-
function parseLimit(value) {
|
|
1812
|
-
if (value === void 0 || value.trim().length === 0) {
|
|
1813
|
-
return 50;
|
|
1814
|
-
}
|
|
1815
|
-
const limit = Number(value);
|
|
1816
|
-
if (!Number.isInteger(limit) || limit <= 0) {
|
|
1817
|
-
return void 0;
|
|
1818
|
-
}
|
|
1819
|
-
return Math.min(limit, 100);
|
|
1820
|
-
}
|
|
1821
|
-
function parseTraceStatus(value) {
|
|
1822
|
-
const status = optionalQueryString(value);
|
|
1823
|
-
if (status === void 0) {
|
|
1824
|
-
return void 0;
|
|
1825
|
-
}
|
|
1826
|
-
return status === "running" || status === "success" || status === "error" ? status : false;
|
|
1827
|
-
}
|
|
1828
|
-
function isMessageInput(value) {
|
|
1829
|
-
return typeof value === "string" || isMessage(value);
|
|
1830
|
-
}
|
|
1831
|
-
function isMessage(value) {
|
|
1832
|
-
if (!isObject(value) || typeof value.role !== "string") {
|
|
1833
|
-
return false;
|
|
1834
|
-
}
|
|
1835
|
-
if (value.role === "system") {
|
|
1836
|
-
return typeof value.content === "string";
|
|
1837
|
-
}
|
|
1838
|
-
if (value.role === "user" || value.role === "assistant" || value.role === "tool") {
|
|
1839
|
-
return Array.isArray(value.content);
|
|
1840
|
-
}
|
|
1841
|
-
return false;
|
|
1842
|
-
}
|
|
1843
|
-
function isObject(value) {
|
|
1844
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1845
|
-
}
|
|
1846
|
-
function isJsonObject2(value) {
|
|
1847
|
-
return isObject(value) && Object.values(value).every(isJsonValue2);
|
|
1848
|
-
}
|
|
1849
|
-
function isJsonValue2(value) {
|
|
1850
|
-
if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
1851
|
-
return true;
|
|
1852
|
-
}
|
|
1853
|
-
if (Array.isArray(value)) {
|
|
1854
|
-
return value.every(isJsonValue2);
|
|
1855
|
-
}
|
|
1856
|
-
return isJsonObject2(value);
|
|
1660
|
+
concurrency: suite.concurrency,
|
|
1661
|
+
metadata: suite.metadata
|
|
1662
|
+
});
|
|
1857
1663
|
}
|
|
1858
|
-
function
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1664
|
+
function unsupportedCapabilities(stores) {
|
|
1665
|
+
return [
|
|
1666
|
+
...stores.sessions === void 0 ? ["sessions"] : [],
|
|
1667
|
+
...stores.traces === void 0 ? ["traces"] : []
|
|
1668
|
+
];
|
|
1863
1669
|
}
|
|
1864
|
-
function
|
|
1865
|
-
return value
|
|
1866
|
-
}
|
|
1867
|
-
function optionalBoolean(value) {
|
|
1868
|
-
return value === void 0 || typeof value === "boolean";
|
|
1869
|
-
}
|
|
1870
|
-
function optionalStringArray(value) {
|
|
1871
|
-
return value === void 0 || Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
1872
|
-
}
|
|
1873
|
-
function optionalObject(value) {
|
|
1874
|
-
return value === void 0 || isObject(value);
|
|
1875
|
-
}
|
|
1876
|
-
function isNonNegativeInteger(value) {
|
|
1877
|
-
return Number.isInteger(value) && typeof value === "number" && value >= 0;
|
|
1878
|
-
}
|
|
1879
|
-
function isPositiveInteger(value) {
|
|
1880
|
-
return Number.isInteger(value) && typeof value === "number" && value > 0;
|
|
1881
|
-
}
|
|
1882
|
-
function unsupportedCapability(c, capability) {
|
|
1883
|
-
return errorResponse(
|
|
1884
|
-
c,
|
|
1885
|
-
501,
|
|
1886
|
-
"unsupported_capability",
|
|
1887
|
-
`Capability "${capability}" is not implemented by this runner`,
|
|
1888
|
-
{ capability }
|
|
1889
|
-
);
|
|
1890
|
-
}
|
|
1891
|
-
function errorResponse(c, status, code, message, details) {
|
|
1892
|
-
const body = {
|
|
1893
|
-
error: {
|
|
1894
|
-
code,
|
|
1895
|
-
message
|
|
1896
|
-
}
|
|
1897
|
-
};
|
|
1898
|
-
if (details !== void 0) {
|
|
1899
|
-
body.error.details = details;
|
|
1900
|
-
}
|
|
1901
|
-
return c.json(body, status);
|
|
1902
|
-
}
|
|
1903
|
-
function serializeError(error) {
|
|
1904
|
-
return serializeUnknown(error);
|
|
1905
|
-
}
|
|
1906
|
-
|
|
1907
|
-
// src/runtime/approvals.ts
|
|
1908
|
-
function registerApprovalRoutes(app, approvals) {
|
|
1909
|
-
app.get("/approvals", (c) => {
|
|
1910
|
-
const status = parseApprovalStatus(c.req.query("status"));
|
|
1911
|
-
if (status === false) {
|
|
1912
|
-
return errorResponse(c, 400, "bad_request", "status must be pending or resolved");
|
|
1913
|
-
}
|
|
1914
|
-
const options = {};
|
|
1915
|
-
const runId = optionalQueryString(c.req.query("runId"));
|
|
1916
|
-
const agentId = optionalQueryString(c.req.query("agentId"));
|
|
1917
|
-
const sessionId = optionalQueryString(c.req.query("sessionId"));
|
|
1918
|
-
if (status !== void 0) {
|
|
1919
|
-
options.status = status;
|
|
1920
|
-
}
|
|
1921
|
-
if (runId !== void 0) {
|
|
1922
|
-
options.runId = runId;
|
|
1923
|
-
}
|
|
1924
|
-
if (agentId !== void 0) {
|
|
1925
|
-
options.agentId = agentId;
|
|
1926
|
-
}
|
|
1927
|
-
if (sessionId !== void 0) {
|
|
1928
|
-
options.sessionId = sessionId;
|
|
1929
|
-
}
|
|
1930
|
-
return c.json({
|
|
1931
|
-
approvals: approvals.list(options)
|
|
1932
|
-
});
|
|
1933
|
-
});
|
|
1934
|
-
app.post("/approvals/:approvalId/decision", async (c) => {
|
|
1935
|
-
const body = await parseApprovalDecisionRequest(c);
|
|
1936
|
-
if ("error" in body) {
|
|
1937
|
-
return body.error;
|
|
1938
|
-
}
|
|
1939
|
-
const result = approvals.decide(c.req.param("approvalId"), body);
|
|
1940
|
-
if (result === "missing") {
|
|
1941
|
-
return errorResponse(c, 404, "not_found", "Approval not found");
|
|
1942
|
-
}
|
|
1943
|
-
if (result === "resolved") {
|
|
1944
|
-
return errorResponse(c, 409, "conflict", "Approval is already resolved");
|
|
1945
|
-
}
|
|
1946
|
-
return c.json(result);
|
|
1947
|
-
});
|
|
1948
|
-
}
|
|
1949
|
-
function parseApprovalStatus(value) {
|
|
1950
|
-
const status = optionalQueryString(value);
|
|
1951
|
-
if (status === void 0) {
|
|
1952
|
-
return void 0;
|
|
1953
|
-
}
|
|
1954
|
-
return status === "pending" || status === "resolved" ? status : false;
|
|
1955
|
-
}
|
|
1956
|
-
async function parseApprovalDecisionRequest(c) {
|
|
1957
|
-
let body;
|
|
1958
|
-
try {
|
|
1959
|
-
body = await c.req.json();
|
|
1960
|
-
} catch {
|
|
1961
|
-
return { error: errorResponse(c, 400, "bad_request", "Request body must be JSON") };
|
|
1962
|
-
}
|
|
1963
|
-
if (!isObject(body)) {
|
|
1964
|
-
return { error: errorResponse(c, 400, "bad_request", "Request body must be an object") };
|
|
1965
|
-
}
|
|
1966
|
-
if (typeof body.approved !== "boolean") {
|
|
1967
|
-
return { error: errorResponse(c, 400, "bad_request", "approved must be a boolean") };
|
|
1968
|
-
}
|
|
1969
|
-
if ("reason" in body && typeof body.reason !== "string") {
|
|
1970
|
-
return { error: errorResponse(c, 400, "bad_request", "reason must be a string") };
|
|
1971
|
-
}
|
|
1972
|
-
return {
|
|
1973
|
-
approved: body.approved,
|
|
1974
|
-
...typeof body.reason === "string" && body.reason.trim().length > 0 ? { reason: body.reason.trim() } : {}
|
|
1975
|
-
};
|
|
1976
|
-
}
|
|
1977
|
-
function createApprovalRuntime() {
|
|
1978
|
-
const approvals = /* @__PURE__ */ new Map();
|
|
1979
|
-
return {
|
|
1980
|
-
approvals,
|
|
1981
|
-
createHook(context) {
|
|
1982
|
-
const handleApprovalRequest = async ({ toolName, toolCallId, internalCallId, args, tool: control }, request) => {
|
|
1983
|
-
const decision = await requestApproval(approvals, context, {
|
|
1984
|
-
toolName,
|
|
1985
|
-
...toolCallId === void 0 ? {} : { toolCallId },
|
|
1986
|
-
internalCallId,
|
|
1987
|
-
args,
|
|
1988
|
-
...request.reason === void 0 ? {} : { reason: request.reason },
|
|
1989
|
-
...request.rejectMessage === void 0 ? {} : { rejectMessage: request.rejectMessage }
|
|
1990
|
-
});
|
|
1991
|
-
return decision.approved ? control.run() : control.skip(decision.reason ?? request.rejectMessage ?? "Rejected in Anvia Studio.");
|
|
1992
|
-
};
|
|
1993
|
-
return {
|
|
1994
|
-
...createHook({
|
|
1995
|
-
async onToolCall({ toolName, toolCallId, internalCallId, args, tool: control }) {
|
|
1996
|
-
const registeredTool = context.getTool(toolName);
|
|
1997
|
-
if (registeredTool?.approval === void 0) {
|
|
1998
|
-
return control.run();
|
|
1999
|
-
}
|
|
2000
|
-
const approval = registeredTool.approval;
|
|
2001
|
-
const rawParsedArgs = parseToolArgs(args);
|
|
2002
|
-
const parsedArgs = registeredTool.parseApprovalArgs?.(rawParsedArgs) ?? rawParsedArgs;
|
|
2003
|
-
const approvalContext = {
|
|
2004
|
-
toolName,
|
|
2005
|
-
args: parsedArgs,
|
|
2006
|
-
rawArgs: args,
|
|
2007
|
-
...toolCallId === void 0 ? {} : { toolCallId },
|
|
2008
|
-
internalCallId,
|
|
2009
|
-
run: {
|
|
2010
|
-
agentId: context.agentId,
|
|
2011
|
-
runId: context.runId,
|
|
2012
|
-
...context.sessionId === void 0 ? {} : { sessionId: context.sessionId },
|
|
2013
|
-
...context.metadata === void 0 ? {} : { metadata: context.metadata }
|
|
2014
|
-
}
|
|
2015
|
-
};
|
|
2016
|
-
const required = await approval.when(approvalContext);
|
|
2017
|
-
if (!required) {
|
|
2018
|
-
return control.run();
|
|
2019
|
-
}
|
|
2020
|
-
const reason = await resolveApprovalText(approval.reason, approvalContext);
|
|
2021
|
-
const rejectMessage = await resolveApprovalText(
|
|
2022
|
-
approval.rejectMessage,
|
|
2023
|
-
approvalContext
|
|
2024
|
-
);
|
|
2025
|
-
const decision = await requestApproval(approvals, context, {
|
|
2026
|
-
toolName,
|
|
2027
|
-
...toolCallId === void 0 ? {} : { toolCallId },
|
|
2028
|
-
internalCallId,
|
|
2029
|
-
args,
|
|
2030
|
-
...reason === void 0 ? {} : { reason },
|
|
2031
|
-
...rejectMessage === void 0 ? {} : { rejectMessage }
|
|
2032
|
-
});
|
|
2033
|
-
return decision.approved ? control.run() : control.skip(decision.reason ?? rejectMessage ?? "Rejected in Anvia Studio.");
|
|
2034
|
-
}
|
|
2035
|
-
}),
|
|
2036
|
-
handleApprovalRequest
|
|
2037
|
-
};
|
|
2038
|
-
},
|
|
2039
|
-
list(options) {
|
|
2040
|
-
return [...approvals.values()].filter((approval) => {
|
|
2041
|
-
if (options.status === "pending" && approval.status !== "pending") {
|
|
2042
|
-
return false;
|
|
2043
|
-
}
|
|
2044
|
-
if (options.status === "resolved" && approval.status === "pending") {
|
|
2045
|
-
return false;
|
|
2046
|
-
}
|
|
2047
|
-
if (options.runId !== void 0 && approval.runId !== options.runId) {
|
|
2048
|
-
return false;
|
|
2049
|
-
}
|
|
2050
|
-
if (options.agentId !== void 0 && approval.agentId !== options.agentId) {
|
|
2051
|
-
return false;
|
|
2052
|
-
}
|
|
2053
|
-
if (options.sessionId !== void 0 && approval.sessionId !== options.sessionId) {
|
|
2054
|
-
return false;
|
|
2055
|
-
}
|
|
2056
|
-
return true;
|
|
2057
|
-
}).map(publicApproval);
|
|
2058
|
-
},
|
|
2059
|
-
decide(id, decision) {
|
|
2060
|
-
const approval = approvals.get(id);
|
|
2061
|
-
if (approval === void 0) {
|
|
2062
|
-
return "missing";
|
|
2063
|
-
}
|
|
2064
|
-
if (!isPendingApproval(approval)) {
|
|
2065
|
-
return "resolved";
|
|
2066
|
-
}
|
|
2067
|
-
const reason = decision.approved ? decision.reason : decision.reason ?? approval.rejectMessage ?? "Rejected in Anvia Studio.";
|
|
2068
|
-
const resolved = resolveApproval(approval, decision.approved ? "approved" : "rejected", {
|
|
2069
|
-
...reason === void 0 ? {} : { reason }
|
|
2070
|
-
});
|
|
2071
|
-
approvals.set(id, resolved);
|
|
2072
|
-
approval.emit?.({ type: "tool_approval_result", approval: resolved });
|
|
2073
|
-
approval.resolve({
|
|
2074
|
-
approved: decision.approved,
|
|
2075
|
-
...reason === void 0 ? {} : { reason }
|
|
2076
|
-
});
|
|
2077
|
-
return publicApproval(resolved);
|
|
2078
|
-
}
|
|
2079
|
-
};
|
|
2080
|
-
}
|
|
2081
|
-
async function requestApproval(approvals, context, request) {
|
|
2082
|
-
const id = globalThis.crypto.randomUUID();
|
|
2083
|
-
const approval = {
|
|
2084
|
-
id,
|
|
2085
|
-
runId: context.runId,
|
|
2086
|
-
agentId: context.agentId,
|
|
2087
|
-
...context.sessionId === void 0 ? {} : { sessionId: context.sessionId },
|
|
2088
|
-
toolName: request.toolName,
|
|
2089
|
-
...request.toolCallId === void 0 ? {} : { callId: request.toolCallId },
|
|
2090
|
-
internalCallId: request.internalCallId,
|
|
2091
|
-
args: request.args,
|
|
2092
|
-
status: "pending",
|
|
2093
|
-
requestedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2094
|
-
...request.reason === void 0 ? {} : { reason: request.reason },
|
|
2095
|
-
...request.rejectMessage === void 0 ? {} : { rejectMessage: request.rejectMessage },
|
|
2096
|
-
...context.emit === void 0 ? {} : { emit: context.emit },
|
|
2097
|
-
resolve: () => {
|
|
2098
|
-
}
|
|
2099
|
-
};
|
|
2100
|
-
const decision = new Promise((resolve2) => {
|
|
2101
|
-
approval.resolve = (decision2) => {
|
|
2102
|
-
const current = approvals.get(id);
|
|
2103
|
-
if (!isPendingApproval(current)) {
|
|
2104
|
-
if (current !== void 0) {
|
|
2105
|
-
resolve2({
|
|
2106
|
-
approved: current.status === "approved",
|
|
2107
|
-
...current.reason === void 0 ? {} : { reason: current.reason }
|
|
2108
|
-
});
|
|
2109
|
-
}
|
|
2110
|
-
return;
|
|
2111
|
-
}
|
|
2112
|
-
const reason = decision2.approved ? decision2.reason : decision2.reason ?? request.rejectMessage ?? "Rejected in Anvia Studio.";
|
|
2113
|
-
const resolved = resolveApproval(current, decision2.approved ? "approved" : "rejected", {
|
|
2114
|
-
...reason === void 0 ? {} : { reason }
|
|
2115
|
-
});
|
|
2116
|
-
approvals.set(id, resolved);
|
|
2117
|
-
context.emit?.({ type: "tool_approval_result", approval: resolved });
|
|
2118
|
-
resolve2({
|
|
2119
|
-
approved: decision2.approved,
|
|
2120
|
-
...reason === void 0 ? {} : { reason }
|
|
2121
|
-
});
|
|
2122
|
-
};
|
|
2123
|
-
});
|
|
2124
|
-
approvals.set(id, approval);
|
|
2125
|
-
context.emit?.({ type: "tool_approval_request", approval: publicApproval(approval) });
|
|
2126
|
-
return decision;
|
|
2127
|
-
}
|
|
2128
|
-
async function resolveApprovalText(value, context) {
|
|
2129
|
-
return typeof value === "function" ? value(context) : value;
|
|
2130
|
-
}
|
|
2131
|
-
function isPendingApproval(approval) {
|
|
2132
|
-
return approval !== void 0 && approval.status === "pending" && "resolve" in approval;
|
|
2133
|
-
}
|
|
2134
|
-
function resolveApproval(approval, status, options = {}) {
|
|
2135
|
-
return publicApproval({
|
|
2136
|
-
...approval,
|
|
2137
|
-
status,
|
|
2138
|
-
resolvedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2139
|
-
...options.reason === void 0 ? {} : { reason: options.reason }
|
|
2140
|
-
});
|
|
2141
|
-
}
|
|
2142
|
-
function publicApproval(approval) {
|
|
2143
|
-
const { emit, rejectMessage, resolve: resolve2, ...rest } = approval;
|
|
2144
|
-
void emit;
|
|
2145
|
-
void rejectMessage;
|
|
2146
|
-
void resolve2;
|
|
2147
|
-
return rest;
|
|
1670
|
+
function toJsonValue2(value) {
|
|
1671
|
+
return serializeUnknown(value);
|
|
2148
1672
|
}
|
|
2149
1673
|
|
|
2150
1674
|
// src/runtime/evals.ts
|
|
@@ -2176,7 +1700,7 @@ function registerEvalRoutes(app, props) {
|
|
|
2176
1700
|
const startedAt = Date.now();
|
|
2177
1701
|
const result = await runEvalSuite({
|
|
2178
1702
|
...suite,
|
|
2179
|
-
...
|
|
1703
|
+
...compact({ concurrency: body.concurrency })
|
|
2180
1704
|
});
|
|
2181
1705
|
const endedAt = Date.now();
|
|
2182
1706
|
const jsonResult = toJsonValue(result);
|
|
@@ -2186,7 +1710,7 @@ function registerEvalRoutes(app, props) {
|
|
|
2186
1710
|
startedAt: new Date(startedAt).toISOString(),
|
|
2187
1711
|
endedAt: new Date(endedAt).toISOString(),
|
|
2188
1712
|
durationMs: endedAt - startedAt,
|
|
2189
|
-
result:
|
|
1713
|
+
result: isJsonObject(jsonResult) ? jsonResult : { value: jsonResult }
|
|
2190
1714
|
};
|
|
2191
1715
|
return c.json(response);
|
|
2192
1716
|
});
|
|
@@ -2254,12 +1778,12 @@ async function agentKnowledgeConfig(agent) {
|
|
|
2254
1778
|
const agentName = agent.name ?? agent.agent.name;
|
|
2255
1779
|
return {
|
|
2256
1780
|
agentId: agent.id,
|
|
2257
|
-
...
|
|
1781
|
+
...compact({ agentName }),
|
|
2258
1782
|
sources: await knowledgeSources(agent),
|
|
2259
1783
|
staticContext: agent.agent.staticContext.map((document) => ({
|
|
2260
1784
|
id: document.id,
|
|
2261
1785
|
text: document.text,
|
|
2262
|
-
...document.additionalProps
|
|
1786
|
+
...compact({ additionalProps: document.additionalProps !== void 0 ? jsonObjectFromRecord(document.additionalProps) : void 0 })
|
|
2263
1787
|
}))
|
|
2264
1788
|
};
|
|
2265
1789
|
}
|
|
@@ -2285,9 +1809,9 @@ async function knowledgeSources(agent) {
|
|
|
2285
1809
|
count: 1,
|
|
2286
1810
|
registrationIndex: index,
|
|
2287
1811
|
topK: registration.options.topK,
|
|
2288
|
-
...
|
|
1812
|
+
...compact({ threshold: registration.options.threshold }),
|
|
2289
1813
|
inspectable: inspect !== void 0,
|
|
2290
|
-
...
|
|
1814
|
+
...compact({ itemCount: count })
|
|
2291
1815
|
};
|
|
2292
1816
|
})
|
|
2293
1817
|
);
|
|
@@ -2302,9 +1826,9 @@ async function knowledgeSources(agent) {
|
|
|
2302
1826
|
count: 1,
|
|
2303
1827
|
registrationIndex: index,
|
|
2304
1828
|
topK: registration.options.topK,
|
|
2305
|
-
...
|
|
1829
|
+
...compact({ threshold: registration.options.threshold }),
|
|
2306
1830
|
inspectable: inspect !== void 0,
|
|
2307
|
-
...
|
|
1831
|
+
...compact({ itemCount: count })
|
|
2308
1832
|
};
|
|
2309
1833
|
})
|
|
2310
1834
|
);
|
|
@@ -2342,8 +1866,7 @@ async function knowledgeItemsPage(agent, sourceId, request) {
|
|
|
2342
1866
|
kind: "dynamic_context",
|
|
2343
1867
|
inspectable: true,
|
|
2344
1868
|
items: page.items.map((item) => dynamicContextItem(item)),
|
|
2345
|
-
...
|
|
2346
|
-
...page.totalCount === void 0 ? {} : { totalCount: page.totalCount }
|
|
1869
|
+
...compact({ nextCursor: page.nextCursor, totalCount: page.totalCount })
|
|
2347
1870
|
};
|
|
2348
1871
|
}
|
|
2349
1872
|
const dynamicToolsIndex = dynamicSourceIndex(sourceId, "dynamic_tools");
|
|
@@ -2367,8 +1890,7 @@ async function knowledgeItemsPage(agent, sourceId, request) {
|
|
|
2367
1890
|
kind: "dynamic_tools",
|
|
2368
1891
|
inspectable: true,
|
|
2369
1892
|
items: page.items.map((item) => dynamicToolItem(item)),
|
|
2370
|
-
...
|
|
2371
|
-
...page.totalCount === void 0 ? {} : { totalCount: page.totalCount }
|
|
1893
|
+
...compact({ nextCursor: page.nextCursor, totalCount: page.totalCount })
|
|
2372
1894
|
};
|
|
2373
1895
|
}
|
|
2374
1896
|
return void 0;
|
|
@@ -2393,9 +1915,9 @@ function staticKnowledgeItemsPage(agent, request) {
|
|
|
2393
1915
|
id: document.id,
|
|
2394
1916
|
kind: "static_context",
|
|
2395
1917
|
text: document.text,
|
|
2396
|
-
...document.additionalProps
|
|
1918
|
+
...compact({ metadata: document.additionalProps !== void 0 ? jsonObjectFromRecord(document.additionalProps) : void 0 })
|
|
2397
1919
|
})),
|
|
2398
|
-
...nextOffset < agent.agent.staticContext.length ?
|
|
1920
|
+
...compact({ nextCursor: nextOffset < agent.agent.staticContext.length ? String(nextOffset) : void 0 }),
|
|
2399
1921
|
totalCount: agent.agent.staticContext.length
|
|
2400
1922
|
};
|
|
2401
1923
|
}
|
|
@@ -2415,7 +1937,7 @@ function dynamicContextItem(item) {
|
|
|
2415
1937
|
id: item.id,
|
|
2416
1938
|
kind: "dynamic_context",
|
|
2417
1939
|
...text === void 0 ? { document: toJsonValue(item.document) } : { text },
|
|
2418
|
-
...item.metadata
|
|
1940
|
+
...compact({ metadata: item.metadata !== void 0 ? jsonObjectFromRecord(item.metadata) : void 0 })
|
|
2419
1941
|
};
|
|
2420
1942
|
}
|
|
2421
1943
|
function dynamicToolItem(item) {
|
|
@@ -2430,7 +1952,7 @@ function dynamicToolItem(item) {
|
|
|
2430
1952
|
description,
|
|
2431
1953
|
parameterKeys: parameterKeys(definition.parameters),
|
|
2432
1954
|
document: toJsonValue(item.document),
|
|
2433
|
-
...item.metadata
|
|
1955
|
+
...compact({ metadata: item.metadata !== void 0 ? jsonObjectFromRecord(item.metadata) : void 0 })
|
|
2434
1956
|
};
|
|
2435
1957
|
}
|
|
2436
1958
|
function parameterKeys(parameters) {
|
|
@@ -2492,7 +2014,7 @@ function evidenceFromTrace(trace) {
|
|
|
2492
2014
|
observationName: observation.name,
|
|
2493
2015
|
turn: observation.turn,
|
|
2494
2016
|
startedAt: observation.startedAt,
|
|
2495
|
-
...
|
|
2017
|
+
...compact({ query }),
|
|
2496
2018
|
documentCount: documents.length,
|
|
2497
2019
|
toolCount: tools.length,
|
|
2498
2020
|
documents,
|
|
@@ -2565,11 +2087,7 @@ function evidenceDocument(value) {
|
|
|
2565
2087
|
return [];
|
|
2566
2088
|
}
|
|
2567
2089
|
return [
|
|
2568
|
-
{
|
|
2569
|
-
...id === void 0 ? {} : { id },
|
|
2570
|
-
...text === void 0 ? {} : { text },
|
|
2571
|
-
...additionalProps === void 0 ? {} : { additionalProps }
|
|
2572
|
-
}
|
|
2090
|
+
compact({ id, text, additionalProps })
|
|
2573
2091
|
];
|
|
2574
2092
|
}
|
|
2575
2093
|
function evidenceToolName(value) {
|
|
@@ -2681,7 +2199,7 @@ function registerMemoryRoutes(app, props) {
|
|
|
2681
2199
|
const agentId = optionalQueryString(c.req.query("agentId"));
|
|
2682
2200
|
const userId = optionalQueryString(c.req.query("userId"));
|
|
2683
2201
|
const sessions = await props.sessionStore.listSessions({
|
|
2684
|
-
...
|
|
2202
|
+
...compact({ agentId }),
|
|
2685
2203
|
limit: 100
|
|
2686
2204
|
});
|
|
2687
2205
|
const conversations = sessions.map(memoryConversationSummary).filter((session) => userId === void 0 || session.userId === userId).slice(0, limit);
|
|
@@ -2713,16 +2231,16 @@ function registerMemoryRoutes(app, props) {
|
|
|
2713
2231
|
});
|
|
2714
2232
|
}
|
|
2715
2233
|
function memoryConversationSummary(session) {
|
|
2716
|
-
return {
|
|
2234
|
+
return compact({
|
|
2717
2235
|
id: session.id,
|
|
2718
2236
|
userId: sessionUserId(session),
|
|
2719
2237
|
agentId: session.agentId,
|
|
2720
|
-
|
|
2238
|
+
title: session.title,
|
|
2721
2239
|
createdAt: session.createdAt,
|
|
2722
2240
|
updatedAt: session.updatedAt,
|
|
2723
2241
|
messageCount: session.messageCount,
|
|
2724
|
-
|
|
2725
|
-
};
|
|
2242
|
+
metadata: session.metadata
|
|
2243
|
+
});
|
|
2726
2244
|
}
|
|
2727
2245
|
function sessionUserId(session) {
|
|
2728
2246
|
const userId = session.metadata?.userId;
|
|
@@ -2809,9 +2327,11 @@ var StudioObservabilityHub = class {
|
|
|
2809
2327
|
function observeStores(stores, hub) {
|
|
2810
2328
|
return {
|
|
2811
2329
|
...stores,
|
|
2812
|
-
...
|
|
2813
|
-
|
|
2814
|
-
|
|
2330
|
+
...compact({
|
|
2331
|
+
sessions: stores.sessions !== void 0 ? observeSessionStore(stores.sessions, hub) : void 0,
|
|
2332
|
+
traces: stores.traces !== void 0 ? observeTraceStore(stores.traces, hub) : void 0,
|
|
2333
|
+
pipelineLogs: stores.pipelineLogs !== void 0 ? observePipelineLogStore(stores.pipelineLogs, hub) : void 0
|
|
2334
|
+
})
|
|
2815
2335
|
};
|
|
2816
2336
|
}
|
|
2817
2337
|
function registerObservabilityRoutes(app, hub) {
|
|
@@ -2832,7 +2352,7 @@ function registerObservabilityRoutes(app, hub) {
|
|
|
2832
2352
|
});
|
|
2833
2353
|
}
|
|
2834
2354
|
function observabilityEvents(hub, types) {
|
|
2835
|
-
const subscription = hub.subscribe(
|
|
2355
|
+
const subscription = hub.subscribe(compact({ types }));
|
|
2836
2356
|
return {
|
|
2837
2357
|
[Symbol.asyncIterator]() {
|
|
2838
2358
|
return {
|
|
@@ -2924,7 +2444,7 @@ function observeTraceStore(store, hub) {
|
|
|
2924
2444
|
const saveTrace = target.saveTrace.bind(target);
|
|
2925
2445
|
return async (...args) => {
|
|
2926
2446
|
const trace = await saveTrace(...args);
|
|
2927
|
-
hub.emit({ type: "trace", trace:
|
|
2447
|
+
hub.emit({ type: "trace", trace: traceSummary(trace) });
|
|
2928
2448
|
return trace;
|
|
2929
2449
|
};
|
|
2930
2450
|
}
|
|
@@ -2951,20 +2471,22 @@ function parseEventTypes(value) {
|
|
|
2951
2471
|
function isEventType(value) {
|
|
2952
2472
|
return value === "session_log" || value === "pipeline_log" || value === "trace";
|
|
2953
2473
|
}
|
|
2954
|
-
function
|
|
2474
|
+
function traceSummary(trace) {
|
|
2955
2475
|
return {
|
|
2956
2476
|
id: trace.id,
|
|
2957
2477
|
sessionId: trace.sessionId,
|
|
2958
|
-
...trace.name === void 0 ? {} : { name: trace.name },
|
|
2959
2478
|
status: trace.status,
|
|
2960
2479
|
startedAt: trace.startedAt,
|
|
2961
|
-
|
|
2962
|
-
...
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2480
|
+
observationCount: trace.observations.length,
|
|
2481
|
+
...compact({
|
|
2482
|
+
name: trace.name,
|
|
2483
|
+
endedAt: trace.endedAt,
|
|
2484
|
+
durationMs: trace.durationMs,
|
|
2485
|
+
output: trace.output,
|
|
2486
|
+
error: trace.error,
|
|
2487
|
+
usage: trace.usage,
|
|
2488
|
+
metadata: trace.metadata
|
|
2489
|
+
})
|
|
2968
2490
|
};
|
|
2969
2491
|
}
|
|
2970
2492
|
|
|
@@ -2986,7 +2508,7 @@ function pipelineRunReceivedLog(props) {
|
|
|
2986
2508
|
category: "api",
|
|
2987
2509
|
event: "pipeline.run_received",
|
|
2988
2510
|
message: "Pipeline run request received",
|
|
2989
|
-
metadata:
|
|
2511
|
+
metadata: compact({
|
|
2990
2512
|
stream: props.stream,
|
|
2991
2513
|
inputBytes: byteLength2(formatUnknown(props.input)),
|
|
2992
2514
|
metadataKeys: Object.keys(props.metadata ?? {})
|
|
@@ -3002,7 +2524,7 @@ function pipelineRunStartedLog(pipeline, runId) {
|
|
|
3002
2524
|
category: "run",
|
|
3003
2525
|
event: "pipeline.run_started",
|
|
3004
2526
|
message: "Pipeline run started",
|
|
3005
|
-
metadata:
|
|
2527
|
+
metadata: compact({
|
|
3006
2528
|
stageCount: graph.nodes.filter((node) => node.kind !== "input" && node.kind !== "output").length,
|
|
3007
2529
|
edgeCount: graph.edges.length
|
|
3008
2530
|
})
|
|
@@ -3016,7 +2538,7 @@ function pipelineRunCompletedLog(props) {
|
|
|
3016
2538
|
category: "run",
|
|
3017
2539
|
event: "pipeline.run_completed",
|
|
3018
2540
|
message: "Pipeline run completed",
|
|
3019
|
-
metadata:
|
|
2541
|
+
metadata: compact({
|
|
3020
2542
|
durationMs: props.durationMs,
|
|
3021
2543
|
outputBytes: byteLength2(formatUnknown(props.output))
|
|
3022
2544
|
})
|
|
@@ -3030,7 +2552,7 @@ function pipelineRunFailedLog(pipelineId, runId, error, startedAt) {
|
|
|
3030
2552
|
category: "run",
|
|
3031
2553
|
event: "pipeline.run_failed",
|
|
3032
2554
|
message: "Pipeline run failed",
|
|
3033
|
-
metadata:
|
|
2555
|
+
metadata: compact({
|
|
3034
2556
|
durationMs: Date.now() - startedAt,
|
|
3035
2557
|
error: serializeError(error)
|
|
3036
2558
|
})
|
|
@@ -3057,7 +2579,7 @@ function pipelineStageLog(pipelineId, runId, event) {
|
|
|
3057
2579
|
category,
|
|
3058
2580
|
event: `${event.node.kind}.completed`,
|
|
3059
2581
|
message: `${event.node.label} completed`,
|
|
3060
|
-
metadata:
|
|
2582
|
+
metadata: compact({
|
|
3061
2583
|
...nodeMetadata(event.node),
|
|
3062
2584
|
durationMs: event.durationMs
|
|
3063
2585
|
})
|
|
@@ -3070,7 +2592,7 @@ function pipelineStageLog(pipelineId, runId, event) {
|
|
|
3070
2592
|
category,
|
|
3071
2593
|
event: `${event.node.kind}.failed`,
|
|
3072
2594
|
message: `${event.node.label} failed`,
|
|
3073
|
-
metadata:
|
|
2595
|
+
metadata: compact({
|
|
3074
2596
|
...nodeMetadata(event.node),
|
|
3075
2597
|
durationMs: event.durationMs,
|
|
3076
2598
|
error: serializeError(event.error)
|
|
@@ -3090,7 +2612,7 @@ function stageCategory(node) {
|
|
|
3090
2612
|
return "stage";
|
|
3091
2613
|
}
|
|
3092
2614
|
function nodeMetadata(node) {
|
|
3093
|
-
return
|
|
2615
|
+
return compact({
|
|
3094
2616
|
nodeId: node.id,
|
|
3095
2617
|
kind: node.kind,
|
|
3096
2618
|
label: node.label,
|
|
@@ -3099,48 +2621,151 @@ function nodeMetadata(node) {
|
|
|
3099
2621
|
branchKey: node.branchKey
|
|
3100
2622
|
});
|
|
3101
2623
|
}
|
|
3102
|
-
function cleanMetadata(value) {
|
|
3103
|
-
return Object.fromEntries(
|
|
3104
|
-
Object.entries(value).filter(([, item]) => item !== void 0)
|
|
3105
|
-
);
|
|
3106
|
-
}
|
|
3107
2624
|
function byteLength2(value) {
|
|
3108
2625
|
return value === void 0 ? void 0 : new TextEncoder().encode(value).length;
|
|
3109
2626
|
}
|
|
3110
|
-
function formatUnknown(value) {
|
|
3111
|
-
try {
|
|
3112
|
-
return JSON.stringify(value);
|
|
3113
|
-
} catch {
|
|
3114
|
-
return void 0;
|
|
3115
|
-
}
|
|
3116
|
-
}
|
|
3117
2627
|
|
|
3118
|
-
// src/runtime/
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
const resolver = this.resolvers.shift();
|
|
3128
|
-
if (resolver !== void 0) {
|
|
3129
|
-
resolver({ done: false, value });
|
|
3130
|
-
return;
|
|
3131
|
-
}
|
|
3132
|
-
this.values.push(value);
|
|
3133
|
-
}
|
|
3134
|
-
close() {
|
|
3135
|
-
this.closed = true;
|
|
3136
|
-
for (const resolver of this.resolvers.splice(0)) {
|
|
3137
|
-
resolver({ done: true, value: void 0 });
|
|
2628
|
+
// src/runtime/transcript.ts
|
|
2629
|
+
function renumberTranscript(entries) {
|
|
2630
|
+
return entries.map((entry, entryId) => ({ ...entry, entryId }));
|
|
2631
|
+
}
|
|
2632
|
+
function transcriptFromMessages(messages) {
|
|
2633
|
+
const transcript = [];
|
|
2634
|
+
for (const message of messages) {
|
|
2635
|
+
if (message.role === "system") {
|
|
2636
|
+
continue;
|
|
3138
2637
|
}
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
2638
|
+
if (message.role === "user") {
|
|
2639
|
+
const attachments = attachmentsFromMessage(message);
|
|
2640
|
+
let textEntryAdded = false;
|
|
2641
|
+
for (const content of message.content) {
|
|
2642
|
+
if (content.type === "text") {
|
|
2643
|
+
transcript.push(compact({
|
|
2644
|
+
entryId: transcript.length,
|
|
2645
|
+
kind: "message",
|
|
2646
|
+
role: "user",
|
|
2647
|
+
text: content.text,
|
|
2648
|
+
attachments: attachments.length === 0 ? void 0 : attachments
|
|
2649
|
+
}));
|
|
2650
|
+
textEntryAdded = true;
|
|
2651
|
+
}
|
|
2652
|
+
}
|
|
2653
|
+
if (!textEntryAdded && attachments.length > 0) {
|
|
2654
|
+
transcript.push({
|
|
2655
|
+
entryId: transcript.length,
|
|
2656
|
+
kind: "message",
|
|
2657
|
+
role: "user",
|
|
2658
|
+
text: "",
|
|
2659
|
+
attachments
|
|
2660
|
+
});
|
|
2661
|
+
}
|
|
2662
|
+
continue;
|
|
2663
|
+
}
|
|
2664
|
+
if (message.role === "tool") {
|
|
2665
|
+
for (const content of message.content) {
|
|
2666
|
+
transcript.push({
|
|
2667
|
+
entryId: transcript.length,
|
|
2668
|
+
kind: "tool",
|
|
2669
|
+
toolName: "tool_result",
|
|
2670
|
+
callId: content.callId ?? content.id,
|
|
2671
|
+
result: content.content.map(
|
|
2672
|
+
(item) => "text" in item ? item.text : `[image:${item.mediaType ?? "image/png"}]`
|
|
2673
|
+
).join("\n"),
|
|
2674
|
+
structuredResult: content.content
|
|
2675
|
+
});
|
|
2676
|
+
}
|
|
2677
|
+
continue;
|
|
2678
|
+
}
|
|
2679
|
+
for (const content of message.content) {
|
|
2680
|
+
if (content.type === "text") {
|
|
2681
|
+
appendAssistantTranscriptText(transcript, content.text);
|
|
2682
|
+
} else if (content.type === "reasoning") {
|
|
2683
|
+
transcript.push(compact({
|
|
2684
|
+
entryId: transcript.length,
|
|
2685
|
+
kind: "reasoning",
|
|
2686
|
+
reasoningId: content.id,
|
|
2687
|
+
text: content.text
|
|
2688
|
+
}));
|
|
2689
|
+
} else if (content.type === "tool_call") {
|
|
2690
|
+
transcript.push({
|
|
2691
|
+
entryId: transcript.length,
|
|
2692
|
+
kind: "tool",
|
|
2693
|
+
toolName: content.function.name,
|
|
2694
|
+
callId: content.callId ?? content.id,
|
|
2695
|
+
args: formatJson(content.function.arguments)
|
|
2696
|
+
});
|
|
2697
|
+
}
|
|
2698
|
+
}
|
|
2699
|
+
}
|
|
2700
|
+
return transcript;
|
|
2701
|
+
}
|
|
2702
|
+
function attachmentsFromMessage(message) {
|
|
2703
|
+
if (message.role !== "user" && message.role !== "assistant") {
|
|
2704
|
+
return [];
|
|
2705
|
+
}
|
|
2706
|
+
return message.content.flatMap((content) => {
|
|
2707
|
+
if (content.type === "image") {
|
|
2708
|
+
return [
|
|
2709
|
+
{
|
|
2710
|
+
kind: "image",
|
|
2711
|
+
...content.source.type === "base64" ? { data: content.source.data, mediaType: content.source.mediaType } : { url: content.source.url }
|
|
2712
|
+
}
|
|
2713
|
+
];
|
|
2714
|
+
}
|
|
2715
|
+
if (content.type === "document") {
|
|
2716
|
+
return [
|
|
2717
|
+
compact({
|
|
2718
|
+
kind: "document",
|
|
2719
|
+
name: content.source.filename,
|
|
2720
|
+
mediaType: content.source.mediaType,
|
|
2721
|
+
data: content.source.type === "base64" ? content.source.data : void 0,
|
|
2722
|
+
url: content.source.type === "url" ? content.source.url : void 0
|
|
2723
|
+
})
|
|
2724
|
+
];
|
|
2725
|
+
}
|
|
2726
|
+
return [];
|
|
2727
|
+
});
|
|
2728
|
+
}
|
|
2729
|
+
function appendAssistantTranscriptText(transcript, text) {
|
|
2730
|
+
const last = transcript.at(-1);
|
|
2731
|
+
if (last?.kind === "message" && last.role === "assistant") {
|
|
2732
|
+
last.text = `${last.text}${text}`;
|
|
2733
|
+
return;
|
|
2734
|
+
}
|
|
2735
|
+
transcript.push({
|
|
2736
|
+
entryId: transcript.length,
|
|
2737
|
+
kind: "message",
|
|
2738
|
+
role: "assistant",
|
|
2739
|
+
text
|
|
2740
|
+
});
|
|
2741
|
+
}
|
|
2742
|
+
|
|
2743
|
+
// src/runtime/runs.ts
|
|
2744
|
+
var AsyncEventQueue = class {
|
|
2745
|
+
values = [];
|
|
2746
|
+
resolvers = [];
|
|
2747
|
+
closed = false;
|
|
2748
|
+
push(value) {
|
|
2749
|
+
if (this.closed) {
|
|
2750
|
+
return;
|
|
2751
|
+
}
|
|
2752
|
+
const resolver = this.resolvers.shift();
|
|
2753
|
+
if (resolver !== void 0) {
|
|
2754
|
+
resolver({ done: false, value });
|
|
2755
|
+
return;
|
|
2756
|
+
}
|
|
2757
|
+
this.values.push(value);
|
|
2758
|
+
}
|
|
2759
|
+
close() {
|
|
2760
|
+
this.closed = true;
|
|
2761
|
+
for (const resolver of this.resolvers.splice(0)) {
|
|
2762
|
+
resolver({ done: true, value: void 0 });
|
|
2763
|
+
}
|
|
2764
|
+
}
|
|
2765
|
+
next() {
|
|
2766
|
+
const value = this.values.shift();
|
|
2767
|
+
if (value !== void 0) {
|
|
2768
|
+
return Promise.resolve({ done: false, value });
|
|
3144
2769
|
}
|
|
3145
2770
|
if (this.closed) {
|
|
3146
2771
|
return Promise.resolve({ done: true, value: void 0 });
|
|
@@ -3263,21 +2888,21 @@ function acceptTranscriptStreamEvent(transcript, event) {
|
|
|
3263
2888
|
kind: "tool",
|
|
3264
2889
|
toolName: event.toolCall.function.name,
|
|
3265
2890
|
callId: event.toolCall.callId ?? event.toolCall.id,
|
|
3266
|
-
args:
|
|
2891
|
+
args: formatJson(event.toolCall.function.arguments)
|
|
3267
2892
|
});
|
|
3268
2893
|
}
|
|
3269
2894
|
if (event.type === "tool_result") {
|
|
3270
2895
|
const matched = findTranscriptToolEntry(transcript, event.toolName, event.toolCallId);
|
|
3271
2896
|
if (matched === void 0) {
|
|
3272
|
-
transcript.push({
|
|
2897
|
+
transcript.push(compact({
|
|
3273
2898
|
entryId: transcript.length,
|
|
3274
2899
|
kind: "tool",
|
|
3275
2900
|
toolName: event.toolName,
|
|
3276
|
-
|
|
2901
|
+
callId: event.toolCallId,
|
|
3277
2902
|
args: event.args,
|
|
3278
2903
|
result: event.result,
|
|
3279
|
-
|
|
3280
|
-
});
|
|
2904
|
+
structuredResult: event.structuredResult
|
|
2905
|
+
}));
|
|
3281
2906
|
return;
|
|
3282
2907
|
}
|
|
3283
2908
|
matched.args = matched.args ?? event.args;
|
|
@@ -3289,15 +2914,15 @@ function acceptTranscriptStreamEvent(transcript, event) {
|
|
|
3289
2914
|
if (event.type === "agent_tool_event") {
|
|
3290
2915
|
const matched = findTranscriptToolEntry(transcript, event.toolName, event.toolCallId);
|
|
3291
2916
|
if (matched === void 0) {
|
|
3292
|
-
transcript.push({
|
|
2917
|
+
transcript.push(compact({
|
|
3293
2918
|
entryId: transcript.length,
|
|
3294
2919
|
kind: "tool",
|
|
3295
2920
|
toolName: event.toolName,
|
|
3296
|
-
|
|
2921
|
+
callId: event.toolCallId,
|
|
3297
2922
|
childEvents: [childAgentTranscriptEvent(event)].filter(
|
|
3298
2923
|
(childEvent) => childEvent !== void 0
|
|
3299
2924
|
)
|
|
3300
|
-
});
|
|
2925
|
+
}));
|
|
3301
2926
|
return;
|
|
3302
2927
|
}
|
|
3303
2928
|
appendChildAgentTranscriptEvent(matched, event);
|
|
@@ -3323,13 +2948,13 @@ function acceptTranscriptStreamEvent(transcript, event) {
|
|
|
3323
2948
|
approvalCallId(event.approval)
|
|
3324
2949
|
);
|
|
3325
2950
|
if (matched !== void 0) {
|
|
3326
|
-
matched.approval = {
|
|
2951
|
+
matched.approval = compact({
|
|
3327
2952
|
id: event.approval.id,
|
|
3328
2953
|
status: event.approval.status,
|
|
3329
2954
|
requestedAt: event.approval.requestedAt,
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
};
|
|
2955
|
+
resolvedAt: event.approval.resolvedAt,
|
|
2956
|
+
reason: event.approval.reason
|
|
2957
|
+
});
|
|
3333
2958
|
}
|
|
3334
2959
|
}
|
|
3335
2960
|
if (event.type === "tool_question_request") {
|
|
@@ -3354,14 +2979,14 @@ function acceptTranscriptStreamEvent(transcript, event) {
|
|
|
3354
2979
|
questionCallId(event.question)
|
|
3355
2980
|
);
|
|
3356
2981
|
if (matched !== void 0) {
|
|
3357
|
-
matched.question = {
|
|
2982
|
+
matched.question = compact({
|
|
3358
2983
|
id: event.question.id,
|
|
3359
2984
|
status: event.question.status,
|
|
3360
2985
|
requestedAt: event.question.requestedAt,
|
|
3361
|
-
|
|
2986
|
+
answeredAt: event.question.answeredAt,
|
|
3362
2987
|
questions: event.question.questions,
|
|
3363
|
-
|
|
3364
|
-
};
|
|
2988
|
+
answers: event.question.answers
|
|
2989
|
+
});
|
|
3365
2990
|
}
|
|
3366
2991
|
}
|
|
3367
2992
|
if (event.type === "final" && event.trace?.traceId !== void 0) {
|
|
@@ -3415,51 +3040,51 @@ function appendChildAgentTranscriptEvent(entry, event) {
|
|
|
3415
3040
|
function childAgentTranscriptEvent(event) {
|
|
3416
3041
|
const child = event.event;
|
|
3417
3042
|
if (child.type === "text_delta") {
|
|
3418
|
-
return {
|
|
3043
|
+
return compact({
|
|
3419
3044
|
kind: "message",
|
|
3420
3045
|
agentId: event.agentId,
|
|
3421
|
-
|
|
3046
|
+
agentName: event.agentName,
|
|
3422
3047
|
text: child.delta
|
|
3423
|
-
};
|
|
3048
|
+
});
|
|
3424
3049
|
}
|
|
3425
3050
|
if (child.type === "reasoning_delta") {
|
|
3426
|
-
return {
|
|
3051
|
+
return compact({
|
|
3427
3052
|
kind: "reasoning",
|
|
3428
3053
|
agentId: event.agentId,
|
|
3429
|
-
|
|
3430
|
-
|
|
3054
|
+
agentName: event.agentName,
|
|
3055
|
+
reasoningId: child.id,
|
|
3431
3056
|
text: child.delta
|
|
3432
|
-
};
|
|
3057
|
+
});
|
|
3433
3058
|
}
|
|
3434
3059
|
if (child.type === "tool_call") {
|
|
3435
|
-
return {
|
|
3060
|
+
return compact({
|
|
3436
3061
|
kind: "tool",
|
|
3437
3062
|
agentId: event.agentId,
|
|
3438
|
-
|
|
3063
|
+
agentName: event.agentName,
|
|
3439
3064
|
toolName: child.toolCall.function.name,
|
|
3440
|
-
|
|
3441
|
-
args:
|
|
3442
|
-
};
|
|
3065
|
+
callId: child.toolCall.callId ?? child.toolCall.id,
|
|
3066
|
+
args: formatJson(child.toolCall.function.arguments)
|
|
3067
|
+
});
|
|
3443
3068
|
}
|
|
3444
3069
|
if (child.type === "tool_result") {
|
|
3445
|
-
return {
|
|
3070
|
+
return compact({
|
|
3446
3071
|
kind: "tool",
|
|
3447
3072
|
agentId: event.agentId,
|
|
3448
|
-
|
|
3073
|
+
agentName: event.agentName,
|
|
3449
3074
|
toolName: child.toolName,
|
|
3450
|
-
|
|
3075
|
+
callId: child.toolCallId,
|
|
3451
3076
|
args: child.args,
|
|
3452
3077
|
result: child.result,
|
|
3453
|
-
|
|
3454
|
-
};
|
|
3078
|
+
structuredResult: child.structuredResult
|
|
3079
|
+
});
|
|
3455
3080
|
}
|
|
3456
3081
|
if (child.type === "error") {
|
|
3457
|
-
return {
|
|
3082
|
+
return compact({
|
|
3458
3083
|
kind: "message",
|
|
3459
3084
|
agentId: event.agentId,
|
|
3460
|
-
|
|
3085
|
+
agentName: event.agentName,
|
|
3461
3086
|
text: `Error: ${errorText(child.error)}`
|
|
3462
|
-
};
|
|
3087
|
+
});
|
|
3463
3088
|
}
|
|
3464
3089
|
return void 0;
|
|
3465
3090
|
}
|
|
@@ -3532,12 +3157,12 @@ function appendTranscriptReasoningText(transcript, delta, reasoningId) {
|
|
|
3532
3157
|
last.text = `${last.text}${delta}`;
|
|
3533
3158
|
return;
|
|
3534
3159
|
}
|
|
3535
|
-
transcript.push({
|
|
3160
|
+
transcript.push(compact({
|
|
3536
3161
|
entryId: transcript.length,
|
|
3537
3162
|
kind: "reasoning",
|
|
3538
|
-
|
|
3163
|
+
reasoningId,
|
|
3539
3164
|
text: delta
|
|
3540
|
-
});
|
|
3165
|
+
}));
|
|
3541
3166
|
}
|
|
3542
3167
|
function findTranscriptToolEntry(transcript, toolName, callId) {
|
|
3543
3168
|
for (let index = transcript.length - 1; index >= 0; index -= 1) {
|
|
@@ -3574,7 +3199,7 @@ function extractMessageText(message) {
|
|
|
3574
3199
|
return [item.text];
|
|
3575
3200
|
}
|
|
3576
3201
|
if (item.type === "tool_call") {
|
|
3577
|
-
return [`${item.function.name}(${
|
|
3202
|
+
return [`${item.function.name}(${formatJson(item.function.arguments)})`];
|
|
3578
3203
|
}
|
|
3579
3204
|
if (item.type === "tool_result") {
|
|
3580
3205
|
return item.content.map(
|
|
@@ -3599,25 +3224,19 @@ function optionalTranscriptAttachments(message) {
|
|
|
3599
3224
|
}
|
|
3600
3225
|
if (content.type === "document") {
|
|
3601
3226
|
return [
|
|
3602
|
-
{
|
|
3227
|
+
compact({
|
|
3603
3228
|
kind: "document",
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3229
|
+
name: content.source.filename,
|
|
3230
|
+
mediaType: content.source.mediaType,
|
|
3231
|
+
data: content.source.type === "base64" ? content.source.data : void 0,
|
|
3232
|
+
url: content.source.type === "url" ? content.source.url : void 0
|
|
3233
|
+
})
|
|
3608
3234
|
];
|
|
3609
3235
|
}
|
|
3610
3236
|
return [];
|
|
3611
3237
|
});
|
|
3612
3238
|
return attachments.length === 0 ? {} : { attachments };
|
|
3613
3239
|
}
|
|
3614
|
-
function formatJson2(value) {
|
|
3615
|
-
try {
|
|
3616
|
-
return JSON.stringify(value, null, 2);
|
|
3617
|
-
} catch {
|
|
3618
|
-
return String(value);
|
|
3619
|
-
}
|
|
3620
|
-
}
|
|
3621
3240
|
async function parseRunRequest(c) {
|
|
3622
3241
|
let body;
|
|
3623
3242
|
try {
|
|
@@ -3695,7 +3314,7 @@ async function parseRunRequest(c) {
|
|
|
3695
3314
|
}
|
|
3696
3315
|
}
|
|
3697
3316
|
if ("metadata" in body) {
|
|
3698
|
-
if (!
|
|
3317
|
+
if (!isJsonObject(body.metadata)) {
|
|
3699
3318
|
return { error: errorResponse(c, 400, "bad_request", "metadata must be an object") };
|
|
3700
3319
|
}
|
|
3701
3320
|
request.metadata = body.metadata;
|
|
@@ -3751,7 +3370,7 @@ function registerPipelineRoutes(app, props) {
|
|
|
3751
3370
|
const logs = await props.logStore.listPipelineLogs({
|
|
3752
3371
|
pipelineId,
|
|
3753
3372
|
limit,
|
|
3754
|
-
...
|
|
3373
|
+
...compact({ after })
|
|
3755
3374
|
});
|
|
3756
3375
|
const last = logs.at(-1);
|
|
3757
3376
|
return c.json({
|
|
@@ -3822,7 +3441,7 @@ function registerPipelineRoutes(app, props) {
|
|
|
3822
3441
|
}
|
|
3823
3442
|
return executePipelineRun(c, props, pipeline, {
|
|
3824
3443
|
input: sourceRun.input,
|
|
3825
|
-
...
|
|
3444
|
+
...compact({ stream: body.stream }),
|
|
3826
3445
|
metadata: replayMetadata(sourceRun.metadata, body.metadata, sourceRun.runId)
|
|
3827
3446
|
});
|
|
3828
3447
|
});
|
|
@@ -3838,7 +3457,7 @@ async function executePipelineRun(c, props, pipeline, body) {
|
|
|
3838
3457
|
runId,
|
|
3839
3458
|
stream: body.stream === true,
|
|
3840
3459
|
input: body.input,
|
|
3841
|
-
...
|
|
3460
|
+
...compact({ metadata: body.metadata })
|
|
3842
3461
|
})
|
|
3843
3462
|
);
|
|
3844
3463
|
await savePipelineRun(props.runStore, {
|
|
@@ -3846,7 +3465,7 @@ async function executePipelineRun(c, props, pipeline, body) {
|
|
|
3846
3465
|
pipelineId: pipeline.id,
|
|
3847
3466
|
status: "running",
|
|
3848
3467
|
input: body.input,
|
|
3849
|
-
...
|
|
3468
|
+
...compact({ metadata: body.metadata }),
|
|
3850
3469
|
startedAt: startedAtIso
|
|
3851
3470
|
});
|
|
3852
3471
|
if (body.stream === true) {
|
|
@@ -3856,9 +3475,8 @@ async function executePipelineRun(c, props, pipeline, body) {
|
|
|
3856
3475
|
input: body.input,
|
|
3857
3476
|
startedAt,
|
|
3858
3477
|
startedAtIso,
|
|
3859
|
-
...
|
|
3860
|
-
...
|
|
3861
|
-
...props.runStore === void 0 ? {} : { runStore: props.runStore }
|
|
3478
|
+
...compact({ metadata: body.metadata }),
|
|
3479
|
+
...compact({ logStore: props.logStore, runStore: props.runStore })
|
|
3862
3480
|
});
|
|
3863
3481
|
}
|
|
3864
3482
|
try {
|
|
@@ -3878,7 +3496,7 @@ async function executePipelineRun(c, props, pipeline, body) {
|
|
|
3878
3496
|
status: "success",
|
|
3879
3497
|
input: body.input,
|
|
3880
3498
|
output: jsonOutput,
|
|
3881
|
-
...
|
|
3499
|
+
...compact({ metadata: body.metadata }),
|
|
3882
3500
|
startedAt: startedAtIso,
|
|
3883
3501
|
endedAt: new Date(endedAt).toISOString(),
|
|
3884
3502
|
durationMs: endedAt - startedAt
|
|
@@ -3906,7 +3524,7 @@ async function executePipelineRun(c, props, pipeline, body) {
|
|
|
3906
3524
|
status: "error",
|
|
3907
3525
|
input: body.input,
|
|
3908
3526
|
error: serializeError(error),
|
|
3909
|
-
...
|
|
3527
|
+
...compact({ metadata: body.metadata }),
|
|
3910
3528
|
startedAt: startedAtIso,
|
|
3911
3529
|
endedAt: new Date(endedAt).toISOString(),
|
|
3912
3530
|
durationMs: endedAt - startedAt
|
|
@@ -3953,7 +3571,7 @@ async function* pipelineRunEvents(props) {
|
|
|
3953
3571
|
status: "success",
|
|
3954
3572
|
input: props.input,
|
|
3955
3573
|
output: jsonOutput,
|
|
3956
|
-
...
|
|
3574
|
+
...compact({ metadata: props.metadata }),
|
|
3957
3575
|
startedAt: props.startedAtIso,
|
|
3958
3576
|
endedAt: new Date(endedAt).toISOString(),
|
|
3959
3577
|
durationMs: endedAt - props.startedAt
|
|
@@ -3984,7 +3602,7 @@ async function* pipelineRunEvents(props) {
|
|
|
3984
3602
|
status: "error",
|
|
3985
3603
|
input: props.input,
|
|
3986
3604
|
error: serializeError(error),
|
|
3987
|
-
...
|
|
3605
|
+
...compact({ metadata: props.metadata }),
|
|
3988
3606
|
startedAt: props.startedAtIso,
|
|
3989
3607
|
endedAt: new Date(endedAt).toISOString(),
|
|
3990
3608
|
durationMs: endedAt - props.startedAt
|
|
@@ -4023,7 +3641,7 @@ async function parsePipelineRunRequest(c) {
|
|
|
4023
3641
|
if (!isObject(body)) {
|
|
4024
3642
|
return { error: errorResponse(c, 400, "bad_request", "Request body must be an object") };
|
|
4025
3643
|
}
|
|
4026
|
-
if (!("input" in body) || !
|
|
3644
|
+
if (!("input" in body) || !isJsonValue2(body.input)) {
|
|
4027
3645
|
return { error: errorResponse(c, 400, "bad_request", "input must be JSON-compatible") };
|
|
4028
3646
|
}
|
|
4029
3647
|
const request = {
|
|
@@ -4036,7 +3654,7 @@ async function parsePipelineRunRequest(c) {
|
|
|
4036
3654
|
request.stream = body.stream;
|
|
4037
3655
|
}
|
|
4038
3656
|
if ("metadata" in body) {
|
|
4039
|
-
if (!
|
|
3657
|
+
if (!isJsonObject(body.metadata)) {
|
|
4040
3658
|
return { error: errorResponse(c, 400, "bad_request", "metadata must be an object") };
|
|
4041
3659
|
}
|
|
4042
3660
|
request.metadata = body.metadata;
|
|
@@ -4061,7 +3679,7 @@ async function parsePipelineReplayRequest(c) {
|
|
|
4061
3679
|
request.stream = body.stream;
|
|
4062
3680
|
}
|
|
4063
3681
|
if ("metadata" in body) {
|
|
4064
|
-
if (!
|
|
3682
|
+
if (!isJsonObject(body.metadata)) {
|
|
4065
3683
|
return { error: errorResponse(c, 400, "bad_request", "metadata must be an object") };
|
|
4066
3684
|
}
|
|
4067
3685
|
request.metadata = body.metadata;
|
|
@@ -4095,22 +3713,22 @@ function parsePipelineLogAfter(value) {
|
|
|
4095
3713
|
}
|
|
4096
3714
|
return after;
|
|
4097
3715
|
}
|
|
4098
|
-
function
|
|
3716
|
+
function isJsonValue2(value) {
|
|
4099
3717
|
if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
4100
3718
|
return Number.isFinite(value) || typeof value !== "number";
|
|
4101
3719
|
}
|
|
4102
3720
|
if (Array.isArray(value)) {
|
|
4103
|
-
return value.every(
|
|
3721
|
+
return value.every(isJsonValue2);
|
|
4104
3722
|
}
|
|
4105
3723
|
if (isObject(value)) {
|
|
4106
|
-
return Object.values(value).every((item) => item === void 0 ||
|
|
3724
|
+
return Object.values(value).every((item) => item === void 0 || isJsonValue2(item));
|
|
4107
3725
|
}
|
|
4108
3726
|
return false;
|
|
4109
3727
|
}
|
|
4110
3728
|
|
|
4111
3729
|
// src/runtime/questions.ts
|
|
4112
|
-
import { createHook
|
|
4113
|
-
import { parseToolArgs
|
|
3730
|
+
import { createHook } from "@anvia/core/agent";
|
|
3731
|
+
import { parseToolArgs } from "@anvia/core/tool";
|
|
4114
3732
|
function registerQuestionRoutes(app, questions) {
|
|
4115
3733
|
app.get("/questions", (c) => {
|
|
4116
3734
|
const status = parseQuestionStatus(c.req.query("status"));
|
|
@@ -4187,12 +3805,12 @@ async function parseQuestionAnswerRequest(c) {
|
|
|
4187
3805
|
if ("custom" in answer && typeof answer.custom !== "boolean") {
|
|
4188
3806
|
return { error: errorResponse(c, 400, "bad_request", "custom must be a boolean") };
|
|
4189
3807
|
}
|
|
4190
|
-
answers.push({
|
|
3808
|
+
answers.push(compact({
|
|
4191
3809
|
questionId: answer.questionId.trim(),
|
|
4192
3810
|
answer: answer.answer.trim(),
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
});
|
|
3811
|
+
choice: typeof answer.choice === "string" ? answer.choice : void 0,
|
|
3812
|
+
custom: typeof answer.custom === "boolean" ? answer.custom : void 0
|
|
3813
|
+
}));
|
|
4196
3814
|
}
|
|
4197
3815
|
return { answers };
|
|
4198
3816
|
}
|
|
@@ -4201,22 +3819,22 @@ function createQuestionRuntime() {
|
|
|
4201
3819
|
return {
|
|
4202
3820
|
questions,
|
|
4203
3821
|
createHook(context) {
|
|
4204
|
-
return
|
|
3822
|
+
return createHook({
|
|
4205
3823
|
async onToolCall({ toolName, toolCallId, internalCallId, args, tool: control }) {
|
|
4206
3824
|
if (toolName !== "ask_question") {
|
|
4207
3825
|
return control.run();
|
|
4208
3826
|
}
|
|
4209
|
-
const prompts = normalizeQuestionPrompts(
|
|
3827
|
+
const prompts = normalizeQuestionPrompts(parseToolArgs(args));
|
|
4210
3828
|
if ("error" in prompts) {
|
|
4211
3829
|
return control.skip(prompts.error);
|
|
4212
3830
|
}
|
|
4213
|
-
const answers = await requestQuestion(questions, context, {
|
|
3831
|
+
const answers = await requestQuestion(questions, context, compact({
|
|
4214
3832
|
toolName,
|
|
4215
|
-
|
|
3833
|
+
toolCallId,
|
|
4216
3834
|
internalCallId,
|
|
4217
3835
|
args,
|
|
4218
3836
|
questions: prompts.questions
|
|
4219
|
-
});
|
|
3837
|
+
}));
|
|
4220
3838
|
return control.skip(JSON.stringify({ answers }));
|
|
4221
3839
|
}
|
|
4222
3840
|
});
|
|
@@ -4260,18 +3878,20 @@ function createQuestionRuntime() {
|
|
|
4260
3878
|
async function requestQuestion(questions, context, request) {
|
|
4261
3879
|
const id = globalThis.crypto.randomUUID();
|
|
4262
3880
|
const question = {
|
|
4263
|
-
|
|
4264
|
-
|
|
4265
|
-
|
|
4266
|
-
|
|
4267
|
-
|
|
4268
|
-
|
|
4269
|
-
|
|
4270
|
-
|
|
4271
|
-
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
3881
|
+
...compact({
|
|
3882
|
+
id,
|
|
3883
|
+
runId: context.runId,
|
|
3884
|
+
agentId: context.agentId,
|
|
3885
|
+
sessionId: context.sessionId,
|
|
3886
|
+
toolName: request.toolName,
|
|
3887
|
+
callId: request.toolCallId,
|
|
3888
|
+
internalCallId: request.internalCallId,
|
|
3889
|
+
args: request.args,
|
|
3890
|
+
questions: request.questions,
|
|
3891
|
+
status: "pending",
|
|
3892
|
+
requestedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3893
|
+
emit: context.emit
|
|
3894
|
+
}),
|
|
4275
3895
|
resolve: () => {
|
|
4276
3896
|
}
|
|
4277
3897
|
};
|
|
@@ -4382,7 +4002,7 @@ function sessionCreatedLog(session) {
|
|
|
4382
4002
|
category: "session",
|
|
4383
4003
|
event: "session.created",
|
|
4384
4004
|
message: "Session created",
|
|
4385
|
-
metadata:
|
|
4005
|
+
metadata: compact({
|
|
4386
4006
|
agentId: session.agentId,
|
|
4387
4007
|
hasTitle: session.title !== void 0,
|
|
4388
4008
|
titleLength: session.title?.length ?? 0
|
|
@@ -4397,7 +4017,7 @@ function runReceivedLog(props) {
|
|
|
4397
4017
|
category: "api",
|
|
4398
4018
|
event: "run.received",
|
|
4399
4019
|
message: "Run request received",
|
|
4400
|
-
metadata:
|
|
4020
|
+
metadata: compact({
|
|
4401
4021
|
agentId: props.agentId,
|
|
4402
4022
|
stream: props.stream,
|
|
4403
4023
|
message: messageSummary(props.message),
|
|
@@ -4416,7 +4036,7 @@ function runStartedLog(session, runId) {
|
|
|
4416
4036
|
category: "run",
|
|
4417
4037
|
event: "run.started",
|
|
4418
4038
|
message: "Run started",
|
|
4419
|
-
metadata:
|
|
4039
|
+
metadata: compact({
|
|
4420
4040
|
agentId: session.agentId,
|
|
4421
4041
|
existingMessageCount: session.messageCount
|
|
4422
4042
|
})
|
|
@@ -4430,7 +4050,7 @@ function memoryLoadedLog(session, runId) {
|
|
|
4430
4050
|
category: "memory",
|
|
4431
4051
|
event: "memory.loaded",
|
|
4432
4052
|
message: "Session memory loaded",
|
|
4433
|
-
metadata:
|
|
4053
|
+
metadata: compact({
|
|
4434
4054
|
messageCount: session.messageCount,
|
|
4435
4055
|
transcriptEntries: session.transcript.length
|
|
4436
4056
|
})
|
|
@@ -4444,7 +4064,7 @@ function runCompletedLog(props) {
|
|
|
4444
4064
|
category: "run",
|
|
4445
4065
|
event: "run.completed",
|
|
4446
4066
|
message: "Run completed",
|
|
4447
|
-
metadata:
|
|
4067
|
+
metadata: compact({
|
|
4448
4068
|
durationMs: props.durationMs,
|
|
4449
4069
|
usage: usageSummary(props.usage),
|
|
4450
4070
|
outputBytes: byteLength3(props.output),
|
|
@@ -4460,7 +4080,7 @@ function memorySavedLog(props) {
|
|
|
4460
4080
|
category: "memory",
|
|
4461
4081
|
event: "memory.saved",
|
|
4462
4082
|
message: "Session memory saved",
|
|
4463
|
-
metadata:
|
|
4083
|
+
metadata: compact({
|
|
4464
4084
|
messageCount: props.messageCount
|
|
4465
4085
|
})
|
|
4466
4086
|
};
|
|
@@ -4473,7 +4093,7 @@ function runFailedLog(sessionId, runId, error, startedAt) {
|
|
|
4473
4093
|
category: "run",
|
|
4474
4094
|
event: "run.failed",
|
|
4475
4095
|
message: "Run failed",
|
|
4476
|
-
metadata:
|
|
4096
|
+
metadata: compact({
|
|
4477
4097
|
durationMs: Date.now() - startedAt,
|
|
4478
4098
|
error: serializeError(error)
|
|
4479
4099
|
})
|
|
@@ -4490,7 +4110,7 @@ function logsFromStreamEvent(props) {
|
|
|
4490
4110
|
category: "prompt",
|
|
4491
4111
|
event: "prompt.prepared",
|
|
4492
4112
|
message: `Turn ${event.turn} prompt prepared`,
|
|
4493
|
-
metadata:
|
|
4113
|
+
metadata: compact({
|
|
4494
4114
|
turn: event.turn,
|
|
4495
4115
|
prompt: messageSummary(event.prompt),
|
|
4496
4116
|
historyCount: event.history.length
|
|
@@ -4507,11 +4127,11 @@ function logsFromStreamEvent(props) {
|
|
|
4507
4127
|
category: "tool",
|
|
4508
4128
|
event: "tool.called",
|
|
4509
4129
|
message: `Tool ${event.toolCall.function.name} called`,
|
|
4510
|
-
metadata:
|
|
4130
|
+
metadata: compact({
|
|
4511
4131
|
turn: event.turn,
|
|
4512
4132
|
toolName: event.toolCall.function.name,
|
|
4513
4133
|
callId: event.toolCall.callId ?? event.toolCall.id,
|
|
4514
|
-
argumentBytes: byteLength3(
|
|
4134
|
+
argumentBytes: byteLength3(formatUnknown(event.toolCall.function.arguments))
|
|
4515
4135
|
})
|
|
4516
4136
|
}
|
|
4517
4137
|
];
|
|
@@ -4525,7 +4145,7 @@ function logsFromStreamEvent(props) {
|
|
|
4525
4145
|
category: "tool",
|
|
4526
4146
|
event: "tool.completed",
|
|
4527
4147
|
message: `Tool ${event.toolName} completed`,
|
|
4528
|
-
metadata:
|
|
4148
|
+
metadata: compact({
|
|
4529
4149
|
turn: event.turn,
|
|
4530
4150
|
toolName: event.toolName,
|
|
4531
4151
|
callId: event.toolCallId,
|
|
@@ -4546,7 +4166,7 @@ function logsFromStreamEvent(props) {
|
|
|
4546
4166
|
category: "model",
|
|
4547
4167
|
event: "model.turn.completed",
|
|
4548
4168
|
message: `Model turn ${event.turn} completed`,
|
|
4549
|
-
metadata:
|
|
4169
|
+
metadata: compact({
|
|
4550
4170
|
turn: event.turn,
|
|
4551
4171
|
contentCount: event.response.choice.length,
|
|
4552
4172
|
usage: usageSummary(event.response.usage)
|
|
@@ -4579,7 +4199,7 @@ function logsFromStreamEvent(props) {
|
|
|
4579
4199
|
category: "approval",
|
|
4580
4200
|
event: "approval.requested",
|
|
4581
4201
|
message: `Approval requested for ${event.approval.toolName}`,
|
|
4582
|
-
metadata:
|
|
4202
|
+
metadata: compact({
|
|
4583
4203
|
approvalId: event.approval.id,
|
|
4584
4204
|
toolName: event.approval.toolName,
|
|
4585
4205
|
callId: event.approval.callId,
|
|
@@ -4599,7 +4219,7 @@ function logsFromStreamEvent(props) {
|
|
|
4599
4219
|
category: "approval",
|
|
4600
4220
|
event: "approval.resolved",
|
|
4601
4221
|
message: `Approval ${event.approval.status} for ${event.approval.toolName}`,
|
|
4602
|
-
metadata:
|
|
4222
|
+
metadata: compact({
|
|
4603
4223
|
approvalId: event.approval.id,
|
|
4604
4224
|
toolName: event.approval.toolName,
|
|
4605
4225
|
callId: event.approval.callId,
|
|
@@ -4609,392 +4229,696 @@ function logsFromStreamEvent(props) {
|
|
|
4609
4229
|
}
|
|
4610
4230
|
];
|
|
4611
4231
|
}
|
|
4612
|
-
if (event.type === "tool_question_request") {
|
|
4613
|
-
return [
|
|
4614
|
-
{
|
|
4615
|
-
sessionId,
|
|
4616
|
-
runId,
|
|
4617
|
-
level: "info",
|
|
4618
|
-
category: "question",
|
|
4619
|
-
event: "question.requested",
|
|
4620
|
-
message: `Question requested by ${event.question.toolName}`,
|
|
4621
|
-
metadata:
|
|
4622
|
-
questionId: event.question.id,
|
|
4623
|
-
toolName: event.question.toolName,
|
|
4624
|
-
callId: event.question.callId,
|
|
4625
|
-
status: event.question.status,
|
|
4626
|
-
questionCount: event.question.questions.length,
|
|
4627
|
-
argumentBytes: byteLength3(event.question.args)
|
|
4628
|
-
})
|
|
4629
|
-
}
|
|
4630
|
-
];
|
|
4232
|
+
if (event.type === "tool_question_request") {
|
|
4233
|
+
return [
|
|
4234
|
+
{
|
|
4235
|
+
sessionId,
|
|
4236
|
+
runId,
|
|
4237
|
+
level: "info",
|
|
4238
|
+
category: "question",
|
|
4239
|
+
event: "question.requested",
|
|
4240
|
+
message: `Question requested by ${event.question.toolName}`,
|
|
4241
|
+
metadata: compact({
|
|
4242
|
+
questionId: event.question.id,
|
|
4243
|
+
toolName: event.question.toolName,
|
|
4244
|
+
callId: event.question.callId,
|
|
4245
|
+
status: event.question.status,
|
|
4246
|
+
questionCount: event.question.questions.length,
|
|
4247
|
+
argumentBytes: byteLength3(event.question.args)
|
|
4248
|
+
})
|
|
4249
|
+
}
|
|
4250
|
+
];
|
|
4251
|
+
}
|
|
4252
|
+
if (event.type === "tool_question_result") {
|
|
4253
|
+
return [
|
|
4254
|
+
{
|
|
4255
|
+
sessionId,
|
|
4256
|
+
runId,
|
|
4257
|
+
level: "info",
|
|
4258
|
+
category: "question",
|
|
4259
|
+
event: "question.answered",
|
|
4260
|
+
message: `Question answered for ${event.question.toolName}`,
|
|
4261
|
+
metadata: compact({
|
|
4262
|
+
questionId: event.question.id,
|
|
4263
|
+
toolName: event.question.toolName,
|
|
4264
|
+
callId: event.question.callId,
|
|
4265
|
+
status: event.question.status,
|
|
4266
|
+
answerCount: event.question.answers?.length ?? 0
|
|
4267
|
+
})
|
|
4268
|
+
}
|
|
4269
|
+
];
|
|
4270
|
+
}
|
|
4271
|
+
if (event.type === "agent_tool_event") {
|
|
4272
|
+
return childAgentLog(event, sessionId, runId);
|
|
4273
|
+
}
|
|
4274
|
+
return [];
|
|
4275
|
+
}
|
|
4276
|
+
async function* emitLog(store, input) {
|
|
4277
|
+
const log = await appendSessionLog(store, input);
|
|
4278
|
+
if (log !== void 0) {
|
|
4279
|
+
yield { type: "session_log", log };
|
|
4280
|
+
}
|
|
4281
|
+
}
|
|
4282
|
+
function childAgentLog(event, sessionId, runId) {
|
|
4283
|
+
const child = event.event;
|
|
4284
|
+
if (child.type === "tool_call") {
|
|
4285
|
+
return [
|
|
4286
|
+
{
|
|
4287
|
+
sessionId,
|
|
4288
|
+
runId,
|
|
4289
|
+
level: "debug",
|
|
4290
|
+
category: "tool",
|
|
4291
|
+
event: "child_tool.called",
|
|
4292
|
+
message: `Child agent ${event.agentName ?? event.agentId} called ${child.toolCall.function.name}`,
|
|
4293
|
+
metadata: compact({
|
|
4294
|
+
parentToolName: event.toolName,
|
|
4295
|
+
agentId: event.agentId,
|
|
4296
|
+
hasAgentName: event.agentName !== void 0,
|
|
4297
|
+
turn: event.turn,
|
|
4298
|
+
childTurn: child.turn,
|
|
4299
|
+
toolName: child.toolCall.function.name,
|
|
4300
|
+
callId: child.toolCall.callId ?? child.toolCall.id,
|
|
4301
|
+
argumentBytes: byteLength3(formatUnknown(child.toolCall.function.arguments))
|
|
4302
|
+
})
|
|
4303
|
+
}
|
|
4304
|
+
];
|
|
4305
|
+
}
|
|
4306
|
+
if (child.type === "tool_result") {
|
|
4307
|
+
return [
|
|
4308
|
+
{
|
|
4309
|
+
sessionId,
|
|
4310
|
+
runId,
|
|
4311
|
+
level: "debug",
|
|
4312
|
+
category: "tool",
|
|
4313
|
+
event: "child_tool.completed",
|
|
4314
|
+
message: `Child agent ${event.agentName ?? event.agentId} completed ${child.toolName}`,
|
|
4315
|
+
metadata: compact({
|
|
4316
|
+
parentToolName: event.toolName,
|
|
4317
|
+
agentId: event.agentId,
|
|
4318
|
+
hasAgentName: event.agentName !== void 0,
|
|
4319
|
+
turn: event.turn,
|
|
4320
|
+
childTurn: child.turn,
|
|
4321
|
+
toolName: child.toolName,
|
|
4322
|
+
callId: child.toolCallId,
|
|
4323
|
+
resultBytes: byteLength3(child.result),
|
|
4324
|
+
structuredResultBytes: child.structuredResult === void 0 ? void 0 : byteLength3(JSON.stringify(child.structuredResult))
|
|
4325
|
+
})
|
|
4326
|
+
}
|
|
4327
|
+
];
|
|
4328
|
+
}
|
|
4329
|
+
if (child.type === "turn_start") {
|
|
4330
|
+
return [
|
|
4331
|
+
{
|
|
4332
|
+
sessionId,
|
|
4333
|
+
runId,
|
|
4334
|
+
level: "debug",
|
|
4335
|
+
category: "run",
|
|
4336
|
+
event: "child_agent.turn_started",
|
|
4337
|
+
message: `Child agent ${event.agentName ?? event.agentId} turn ${child.turn} started`,
|
|
4338
|
+
metadata: compact({
|
|
4339
|
+
parentToolName: event.toolName,
|
|
4340
|
+
agentId: event.agentId,
|
|
4341
|
+
hasAgentName: event.agentName !== void 0,
|
|
4342
|
+
childTurn: child.turn,
|
|
4343
|
+
historyCount: child.history.length
|
|
4344
|
+
})
|
|
4345
|
+
}
|
|
4346
|
+
];
|
|
4347
|
+
}
|
|
4348
|
+
if (child.type === "final") {
|
|
4349
|
+
return [
|
|
4350
|
+
{
|
|
4351
|
+
sessionId,
|
|
4352
|
+
runId,
|
|
4353
|
+
level: "debug",
|
|
4354
|
+
category: "run",
|
|
4355
|
+
event: "child_agent.completed",
|
|
4356
|
+
message: `Child agent ${event.agentName ?? event.agentId} completed`,
|
|
4357
|
+
metadata: compact({
|
|
4358
|
+
parentToolName: event.toolName,
|
|
4359
|
+
agentId: event.agentId,
|
|
4360
|
+
hasAgentName: event.agentName !== void 0,
|
|
4361
|
+
usage: usageSummary(child.usage),
|
|
4362
|
+
outputBytes: byteLength3(child.output),
|
|
4363
|
+
messageCount: child.messages.length
|
|
4364
|
+
})
|
|
4365
|
+
}
|
|
4366
|
+
];
|
|
4367
|
+
}
|
|
4368
|
+
if (child.type === "error") {
|
|
4369
|
+
return [
|
|
4370
|
+
{
|
|
4371
|
+
sessionId,
|
|
4372
|
+
runId,
|
|
4373
|
+
level: "error",
|
|
4374
|
+
category: "run",
|
|
4375
|
+
event: "child_agent.failed",
|
|
4376
|
+
message: `Child agent ${event.agentName ?? event.agentId} failed`,
|
|
4377
|
+
metadata: compact({
|
|
4378
|
+
parentToolName: event.toolName,
|
|
4379
|
+
agentId: event.agentId,
|
|
4380
|
+
hasAgentName: event.agentName !== void 0,
|
|
4381
|
+
error: serializeError(child.error)
|
|
4382
|
+
})
|
|
4383
|
+
}
|
|
4384
|
+
];
|
|
4385
|
+
}
|
|
4386
|
+
return [];
|
|
4387
|
+
}
|
|
4388
|
+
function messageSummary(message) {
|
|
4389
|
+
if (typeof message === "string") {
|
|
4390
|
+
return {
|
|
4391
|
+
role: "user",
|
|
4392
|
+
contentKind: "text",
|
|
4393
|
+
byteLength: byteLength3(message)
|
|
4394
|
+
};
|
|
4395
|
+
}
|
|
4396
|
+
return {
|
|
4397
|
+
role: message.role,
|
|
4398
|
+
contentKind: Array.isArray(message.content) ? "parts" : "text",
|
|
4399
|
+
partCount: Array.isArray(message.content) ? message.content.length : 1,
|
|
4400
|
+
byteLength: byteLength3(formatUnknown(message.content))
|
|
4401
|
+
};
|
|
4402
|
+
}
|
|
4403
|
+
function usageSummary(value) {
|
|
4404
|
+
if (value === void 0 || value === null || typeof value !== "object") {
|
|
4405
|
+
return void 0;
|
|
4406
|
+
}
|
|
4407
|
+
const record = value;
|
|
4408
|
+
return compact({
|
|
4409
|
+
inputTokens: numericValue(record.inputTokens),
|
|
4410
|
+
outputTokens: numericValue(record.outputTokens),
|
|
4411
|
+
totalTokens: numericValue(record.totalTokens),
|
|
4412
|
+
cachedInputTokens: numericValue(record.cachedInputTokens),
|
|
4413
|
+
cacheCreationInputTokens: numericValue(record.cacheCreationInputTokens)
|
|
4414
|
+
});
|
|
4415
|
+
}
|
|
4416
|
+
function numericValue(value) {
|
|
4417
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
4418
|
+
}
|
|
4419
|
+
function byteLength3(value) {
|
|
4420
|
+
return value === void 0 ? 0 : new TextEncoder().encode(value).byteLength;
|
|
4421
|
+
}
|
|
4422
|
+
|
|
4423
|
+
// src/runtime/sessions.ts
|
|
4424
|
+
function registerSessionRoutes(app, props) {
|
|
4425
|
+
app.get("/sessions", async (c) => {
|
|
4426
|
+
const agentId = optionalQueryString(c.req.query("agentId"));
|
|
4427
|
+
if (agentId !== void 0 && !props.agentMap.has(agentId)) {
|
|
4428
|
+
return errorResponse(c, 404, "not_found", "Agent not found");
|
|
4429
|
+
}
|
|
4430
|
+
const limit = parseLimit(c.req.query("limit"));
|
|
4431
|
+
if (limit === void 0) {
|
|
4432
|
+
return errorResponse(c, 400, "bad_request", "limit must be a positive integer");
|
|
4433
|
+
}
|
|
4434
|
+
const sessions = await props.sessionStore.listSessions({
|
|
4435
|
+
...compact({ agentId }),
|
|
4436
|
+
limit
|
|
4437
|
+
});
|
|
4438
|
+
return c.json({ sessions });
|
|
4439
|
+
});
|
|
4440
|
+
app.post("/sessions", async (c) => {
|
|
4441
|
+
const body = await parseCreateSessionRequest(c);
|
|
4442
|
+
if ("error" in body) {
|
|
4443
|
+
return body.error;
|
|
4444
|
+
}
|
|
4445
|
+
if (!props.agentMap.has(body.agentId)) {
|
|
4446
|
+
return errorResponse(c, 404, "not_found", "Agent not found");
|
|
4447
|
+
}
|
|
4448
|
+
const session = await props.sessionStore.createSession({
|
|
4449
|
+
id: globalThis.crypto.randomUUID(),
|
|
4450
|
+
agentId: body.agentId,
|
|
4451
|
+
...compact({ title: body.title, metadata: body.metadata })
|
|
4452
|
+
});
|
|
4453
|
+
await appendSessionLog(props.sessionStore, sessionCreatedLog(session));
|
|
4454
|
+
return c.json(session, 201);
|
|
4455
|
+
});
|
|
4456
|
+
app.get("/sessions/:sessionId", async (c) => {
|
|
4457
|
+
const session = await props.sessionStore.getSession(c.req.param("sessionId"));
|
|
4458
|
+
if (session === void 0) {
|
|
4459
|
+
return errorResponse(c, 404, "not_found", "Session not found");
|
|
4460
|
+
}
|
|
4461
|
+
return c.json(session);
|
|
4462
|
+
});
|
|
4463
|
+
app.get("/sessions/:sessionId/logs", async (c) => {
|
|
4464
|
+
const sessionId = c.req.param("sessionId");
|
|
4465
|
+
const session = await props.sessionStore.getSession(sessionId);
|
|
4466
|
+
if (session === void 0) {
|
|
4467
|
+
return errorResponse(c, 404, "not_found", "Session not found");
|
|
4468
|
+
}
|
|
4469
|
+
if (props.sessionStore.listSessionLogs === void 0) {
|
|
4470
|
+
return errorResponse(
|
|
4471
|
+
c,
|
|
4472
|
+
501,
|
|
4473
|
+
"unsupported_capability",
|
|
4474
|
+
'Capability "sessions.logs" is not implemented by this runner',
|
|
4475
|
+
{ capability: "sessions", operation: "logs" }
|
|
4476
|
+
);
|
|
4477
|
+
}
|
|
4478
|
+
const limit = parseLimit(c.req.query("limit"), 200, 1e3);
|
|
4479
|
+
if (limit === void 0) {
|
|
4480
|
+
return errorResponse(c, 400, "bad_request", "limit must be a positive integer");
|
|
4481
|
+
}
|
|
4482
|
+
const after = parseAfter(c.req.query("after"));
|
|
4483
|
+
if (after === false) {
|
|
4484
|
+
return errorResponse(c, 400, "bad_request", "after must be a non-negative integer");
|
|
4485
|
+
}
|
|
4486
|
+
const logs = await props.sessionStore.listSessionLogs({
|
|
4487
|
+
sessionId,
|
|
4488
|
+
limit,
|
|
4489
|
+
...compact({ after })
|
|
4490
|
+
});
|
|
4491
|
+
const last = logs.at(-1);
|
|
4492
|
+
return c.json({
|
|
4493
|
+
logs,
|
|
4494
|
+
...logs.length === limit && last !== void 0 ? { nextCursor: last.sequence } : {}
|
|
4495
|
+
});
|
|
4496
|
+
});
|
|
4497
|
+
app.delete("/sessions/:sessionId", async (c) => {
|
|
4498
|
+
if (props.sessionStore.deleteSession === void 0) {
|
|
4499
|
+
return errorResponse(
|
|
4500
|
+
c,
|
|
4501
|
+
501,
|
|
4502
|
+
"unsupported_capability",
|
|
4503
|
+
'Capability "sessions.delete" is not implemented by this runner',
|
|
4504
|
+
{ capability: "sessions", operation: "delete" }
|
|
4505
|
+
);
|
|
4506
|
+
}
|
|
4507
|
+
const deleted = await props.sessionStore.deleteSession(c.req.param("sessionId"));
|
|
4508
|
+
if (!deleted) {
|
|
4509
|
+
return errorResponse(c, 404, "not_found", "Session not found");
|
|
4510
|
+
}
|
|
4511
|
+
return c.body(null, 204);
|
|
4512
|
+
});
|
|
4513
|
+
app.get("/sessions/:sessionId/traces", async (c) => {
|
|
4514
|
+
if (props.traceStore === void 0) {
|
|
4515
|
+
return unsupportedCapability(c, "traces");
|
|
4516
|
+
}
|
|
4517
|
+
const sessionId = c.req.param("sessionId");
|
|
4518
|
+
const session = await props.sessionStore.getSession(sessionId);
|
|
4519
|
+
if (session === void 0) {
|
|
4520
|
+
return errorResponse(c, 404, "not_found", "Session not found");
|
|
4521
|
+
}
|
|
4522
|
+
const limit = parseLimit(c.req.query("limit"));
|
|
4523
|
+
if (limit === void 0) {
|
|
4524
|
+
return errorResponse(c, 400, "bad_request", "limit must be a positive integer");
|
|
4525
|
+
}
|
|
4526
|
+
const traces = await props.traceStore.listSessionTraces({ sessionId, limit });
|
|
4527
|
+
return c.json({ traces });
|
|
4528
|
+
});
|
|
4529
|
+
}
|
|
4530
|
+
async function parseCreateSessionRequest(c) {
|
|
4531
|
+
let body;
|
|
4532
|
+
try {
|
|
4533
|
+
body = await c.req.json();
|
|
4534
|
+
} catch {
|
|
4535
|
+
return { error: errorResponse(c, 400, "bad_request", "Request body must be JSON") };
|
|
4536
|
+
}
|
|
4537
|
+
if (!isObject(body)) {
|
|
4538
|
+
return { error: errorResponse(c, 400, "bad_request", "Request body must be an object") };
|
|
4539
|
+
}
|
|
4540
|
+
if (typeof body.agentId !== "string" || body.agentId.trim().length === 0) {
|
|
4541
|
+
return { error: errorResponse(c, 400, "bad_request", "agentId must be a string") };
|
|
4542
|
+
}
|
|
4543
|
+
const request = {
|
|
4544
|
+
agentId: body.agentId.trim()
|
|
4545
|
+
};
|
|
4546
|
+
if ("title" in body) {
|
|
4547
|
+
if (typeof body.title !== "string") {
|
|
4548
|
+
return { error: errorResponse(c, 400, "bad_request", "title must be a string") };
|
|
4549
|
+
}
|
|
4550
|
+
const title = body.title.trim();
|
|
4551
|
+
if (title.length > 0) {
|
|
4552
|
+
request.title = title;
|
|
4553
|
+
}
|
|
4554
|
+
}
|
|
4555
|
+
if ("metadata" in body) {
|
|
4556
|
+
if (!isJsonObject(body.metadata)) {
|
|
4557
|
+
return { error: errorResponse(c, 400, "bad_request", "metadata must be an object") };
|
|
4558
|
+
}
|
|
4559
|
+
request.metadata = body.metadata;
|
|
4560
|
+
}
|
|
4561
|
+
return request;
|
|
4562
|
+
}
|
|
4563
|
+
|
|
4564
|
+
// src/storage/memory-store.ts
|
|
4565
|
+
function createInMemoryStudioStore() {
|
|
4566
|
+
return new InMemoryStudioStore();
|
|
4567
|
+
}
|
|
4568
|
+
var InMemoryStudioStore = class {
|
|
4569
|
+
kind = "memory";
|
|
4570
|
+
sessions = /* @__PURE__ */ new Map();
|
|
4571
|
+
traces = /* @__PURE__ */ new Map();
|
|
4572
|
+
pipelineLogs = /* @__PURE__ */ new Map();
|
|
4573
|
+
pipelineRuns = /* @__PURE__ */ new Map();
|
|
4574
|
+
listSessions(options) {
|
|
4575
|
+
return [...this.sessions.values()].filter((session) => options.agentId === void 0 || session.agentId === options.agentId).sort((left, right) => Date.parse(right.updatedAt) - Date.parse(left.updatedAt)).slice(0, options.limit).map(sessionSummary);
|
|
4576
|
+
}
|
|
4577
|
+
createSession(input) {
|
|
4578
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
4579
|
+
const session = {
|
|
4580
|
+
...compact({
|
|
4581
|
+
id: input.id,
|
|
4582
|
+
agentId: input.agentId,
|
|
4583
|
+
title: input.title,
|
|
4584
|
+
createdAt: now,
|
|
4585
|
+
updatedAt: now,
|
|
4586
|
+
messageCount: 0,
|
|
4587
|
+
metadata: input.metadata
|
|
4588
|
+
}),
|
|
4589
|
+
messages: [],
|
|
4590
|
+
runs: [],
|
|
4591
|
+
logs: []
|
|
4592
|
+
};
|
|
4593
|
+
this.sessions.set(input.id, session);
|
|
4594
|
+
return sessionSummary(session);
|
|
4595
|
+
}
|
|
4596
|
+
getSession(id) {
|
|
4597
|
+
const session = this.sessions.get(id);
|
|
4598
|
+
return session === void 0 ? void 0 : materializeSession(session);
|
|
4599
|
+
}
|
|
4600
|
+
updateSessionMetadata(id, metadata) {
|
|
4601
|
+
const session = this.sessions.get(id);
|
|
4602
|
+
if (session === void 0) {
|
|
4603
|
+
return void 0;
|
|
4604
|
+
}
|
|
4605
|
+
if (metadata === void 0) {
|
|
4606
|
+
delete session.metadata;
|
|
4607
|
+
} else {
|
|
4608
|
+
session.metadata = metadata;
|
|
4609
|
+
}
|
|
4610
|
+
session.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
4611
|
+
return materializeSession(session);
|
|
4612
|
+
}
|
|
4613
|
+
load(context) {
|
|
4614
|
+
return Promise.resolve(this.sessions.get(context.sessionId)?.messages ?? []);
|
|
4615
|
+
}
|
|
4616
|
+
append(input) {
|
|
4617
|
+
const session = this.sessions.get(input.context.sessionId);
|
|
4618
|
+
if (session !== void 0) {
|
|
4619
|
+
session.messages.push(...input.messages);
|
|
4620
|
+
session.messageCount = session.messages.length;
|
|
4621
|
+
session.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
4622
|
+
}
|
|
4623
|
+
return Promise.resolve();
|
|
4624
|
+
}
|
|
4625
|
+
clear(context) {
|
|
4626
|
+
const session = this.sessions.get(context.sessionId);
|
|
4627
|
+
if (session !== void 0) {
|
|
4628
|
+
session.messages = [];
|
|
4629
|
+
session.runs = [];
|
|
4630
|
+
session.messageCount = 0;
|
|
4631
|
+
session.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
4632
|
+
}
|
|
4633
|
+
return Promise.resolve();
|
|
4634
|
+
}
|
|
4635
|
+
async recordError(input) {
|
|
4636
|
+
await this.saveSessionRunTranscript({
|
|
4637
|
+
id: input.context.sessionId,
|
|
4638
|
+
runId: studioRunId(input.context) ?? input.runId,
|
|
4639
|
+
transcript: transcriptFromMessages(input.messages),
|
|
4640
|
+
status: "error",
|
|
4641
|
+
error: serializeJsonError(input.error)
|
|
4642
|
+
});
|
|
4643
|
+
}
|
|
4644
|
+
saveSessionRunTranscript(input) {
|
|
4645
|
+
const session = this.sessions.get(input.id);
|
|
4646
|
+
if (session === void 0) {
|
|
4647
|
+
return void 0;
|
|
4648
|
+
}
|
|
4649
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
4650
|
+
const existingIndex = session.runs.findIndex((run2) => run2.runId === input.runId);
|
|
4651
|
+
const run = {
|
|
4652
|
+
...input,
|
|
4653
|
+
transcript: renumberTranscript(input.transcript),
|
|
4654
|
+
createdAt: existingIndex === -1 ? now : session.runs[existingIndex]?.createdAt ?? now,
|
|
4655
|
+
updatedAt: now
|
|
4656
|
+
};
|
|
4657
|
+
if (existingIndex === -1) {
|
|
4658
|
+
session.runs.push(run);
|
|
4659
|
+
} else {
|
|
4660
|
+
session.runs[existingIndex] = run;
|
|
4661
|
+
}
|
|
4662
|
+
session.updatedAt = now;
|
|
4663
|
+
return materializeSession(session);
|
|
4664
|
+
}
|
|
4665
|
+
appendSessionLog(input) {
|
|
4666
|
+
const session = this.sessions.get(input.sessionId);
|
|
4667
|
+
const logs = session?.logs ?? [];
|
|
4668
|
+
const entry = compact({
|
|
4669
|
+
id: globalThis.crypto.randomUUID(),
|
|
4670
|
+
sessionId: input.sessionId,
|
|
4671
|
+
runId: input.runId,
|
|
4672
|
+
sequence: logs.length,
|
|
4673
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4674
|
+
level: input.level,
|
|
4675
|
+
category: input.category,
|
|
4676
|
+
event: input.event,
|
|
4677
|
+
message: input.message,
|
|
4678
|
+
metadata: input.metadata
|
|
4679
|
+
});
|
|
4680
|
+
if (session !== void 0) {
|
|
4681
|
+
session.logs.push(entry);
|
|
4682
|
+
session.updatedAt = entry.timestamp;
|
|
4683
|
+
}
|
|
4684
|
+
return entry;
|
|
4685
|
+
}
|
|
4686
|
+
listSessionLogs(options) {
|
|
4687
|
+
return (this.sessions.get(options.sessionId)?.logs ?? []).filter((log) => options.after === void 0 || log.sequence > options.after).slice(0, options.limit);
|
|
4631
4688
|
}
|
|
4632
|
-
|
|
4633
|
-
|
|
4634
|
-
{
|
|
4635
|
-
|
|
4636
|
-
runId,
|
|
4637
|
-
level: "info",
|
|
4638
|
-
category: "question",
|
|
4639
|
-
event: "question.answered",
|
|
4640
|
-
message: `Question answered for ${event.question.toolName}`,
|
|
4641
|
-
metadata: cleanMetadata2({
|
|
4642
|
-
questionId: event.question.id,
|
|
4643
|
-
toolName: event.question.toolName,
|
|
4644
|
-
callId: event.question.callId,
|
|
4645
|
-
status: event.question.status,
|
|
4646
|
-
answerCount: event.question.answers?.length ?? 0
|
|
4647
|
-
})
|
|
4689
|
+
deleteSession(id) {
|
|
4690
|
+
for (const trace of this.traces.values()) {
|
|
4691
|
+
if (trace.sessionId === id) {
|
|
4692
|
+
this.traces.delete(trace.id);
|
|
4648
4693
|
}
|
|
4649
|
-
|
|
4694
|
+
}
|
|
4695
|
+
return this.sessions.delete(id);
|
|
4650
4696
|
}
|
|
4651
|
-
|
|
4652
|
-
return
|
|
4697
|
+
listTraces(options) {
|
|
4698
|
+
return [...this.traces.values()].filter((trace) => options.sessionId === void 0 || trace.sessionId === options.sessionId).filter((trace) => options.status === void 0 || trace.status === options.status).filter((trace) => options.agentId === void 0 || traceAgentId(trace) === options.agentId).sort((left, right) => Date.parse(right.startedAt) - Date.parse(left.startedAt)).slice(0, options.limit).map(traceSummary2);
|
|
4653
4699
|
}
|
|
4654
|
-
|
|
4655
|
-
}
|
|
4656
|
-
async function* emitLog(store, input) {
|
|
4657
|
-
const log = await appendSessionLog(store, input);
|
|
4658
|
-
if (log !== void 0) {
|
|
4659
|
-
yield { type: "session_log", log };
|
|
4700
|
+
listSessionTraces(options) {
|
|
4701
|
+
return this.listTraces({ sessionId: options.sessionId, limit: options.limit });
|
|
4660
4702
|
}
|
|
4661
|
-
|
|
4662
|
-
|
|
4663
|
-
const child = event.event;
|
|
4664
|
-
if (child.type === "tool_call") {
|
|
4665
|
-
return [
|
|
4666
|
-
{
|
|
4667
|
-
sessionId,
|
|
4668
|
-
runId,
|
|
4669
|
-
level: "debug",
|
|
4670
|
-
category: "tool",
|
|
4671
|
-
event: "child_tool.called",
|
|
4672
|
-
message: `Child agent ${event.agentName ?? event.agentId} called ${child.toolCall.function.name}`,
|
|
4673
|
-
metadata: cleanMetadata2({
|
|
4674
|
-
parentToolName: event.toolName,
|
|
4675
|
-
agentId: event.agentId,
|
|
4676
|
-
hasAgentName: event.agentName !== void 0,
|
|
4677
|
-
turn: event.turn,
|
|
4678
|
-
childTurn: child.turn,
|
|
4679
|
-
toolName: child.toolCall.function.name,
|
|
4680
|
-
callId: child.toolCall.callId ?? child.toolCall.id,
|
|
4681
|
-
argumentBytes: byteLength3(formatUnknown2(child.toolCall.function.arguments))
|
|
4682
|
-
})
|
|
4683
|
-
}
|
|
4684
|
-
];
|
|
4703
|
+
getTrace(id) {
|
|
4704
|
+
return this.traces.get(id);
|
|
4685
4705
|
}
|
|
4686
|
-
|
|
4687
|
-
|
|
4688
|
-
|
|
4689
|
-
sessionId,
|
|
4690
|
-
runId,
|
|
4691
|
-
level: "debug",
|
|
4692
|
-
category: "tool",
|
|
4693
|
-
event: "child_tool.completed",
|
|
4694
|
-
message: `Child agent ${event.agentName ?? event.agentId} completed ${child.toolName}`,
|
|
4695
|
-
metadata: cleanMetadata2({
|
|
4696
|
-
parentToolName: event.toolName,
|
|
4697
|
-
agentId: event.agentId,
|
|
4698
|
-
hasAgentName: event.agentName !== void 0,
|
|
4699
|
-
turn: event.turn,
|
|
4700
|
-
childTurn: child.turn,
|
|
4701
|
-
toolName: child.toolName,
|
|
4702
|
-
callId: child.toolCallId,
|
|
4703
|
-
resultBytes: byteLength3(child.result),
|
|
4704
|
-
structuredResultBytes: child.structuredResult === void 0 ? void 0 : byteLength3(JSON.stringify(child.structuredResult))
|
|
4705
|
-
})
|
|
4706
|
-
}
|
|
4707
|
-
];
|
|
4706
|
+
saveTrace(trace) {
|
|
4707
|
+
this.traces.set(trace.id, trace);
|
|
4708
|
+
return trace;
|
|
4708
4709
|
}
|
|
4709
|
-
|
|
4710
|
-
|
|
4711
|
-
|
|
4712
|
-
|
|
4713
|
-
|
|
4714
|
-
|
|
4715
|
-
|
|
4716
|
-
|
|
4717
|
-
|
|
4718
|
-
|
|
4719
|
-
|
|
4720
|
-
|
|
4721
|
-
|
|
4722
|
-
|
|
4723
|
-
|
|
4724
|
-
|
|
4725
|
-
}
|
|
4726
|
-
];
|
|
4710
|
+
appendPipelineLog(input) {
|
|
4711
|
+
const logs = this.pipelineLogs.get(input.pipelineId) ?? [];
|
|
4712
|
+
const entry = compact({
|
|
4713
|
+
id: globalThis.crypto.randomUUID(),
|
|
4714
|
+
pipelineId: input.pipelineId,
|
|
4715
|
+
runId: input.runId,
|
|
4716
|
+
sequence: logs.length,
|
|
4717
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4718
|
+
level: input.level,
|
|
4719
|
+
category: input.category,
|
|
4720
|
+
event: input.event,
|
|
4721
|
+
message: input.message,
|
|
4722
|
+
metadata: input.metadata
|
|
4723
|
+
});
|
|
4724
|
+
this.pipelineLogs.set(input.pipelineId, [...logs, entry]);
|
|
4725
|
+
return entry;
|
|
4727
4726
|
}
|
|
4728
|
-
|
|
4729
|
-
return [
|
|
4730
|
-
{
|
|
4731
|
-
sessionId,
|
|
4732
|
-
runId,
|
|
4733
|
-
level: "debug",
|
|
4734
|
-
category: "run",
|
|
4735
|
-
event: "child_agent.completed",
|
|
4736
|
-
message: `Child agent ${event.agentName ?? event.agentId} completed`,
|
|
4737
|
-
metadata: cleanMetadata2({
|
|
4738
|
-
parentToolName: event.toolName,
|
|
4739
|
-
agentId: event.agentId,
|
|
4740
|
-
hasAgentName: event.agentName !== void 0,
|
|
4741
|
-
usage: usageSummary(child.usage),
|
|
4742
|
-
outputBytes: byteLength3(child.output),
|
|
4743
|
-
messageCount: child.messages.length
|
|
4744
|
-
})
|
|
4745
|
-
}
|
|
4746
|
-
];
|
|
4727
|
+
listPipelineLogs(options) {
|
|
4728
|
+
return (this.pipelineLogs.get(options.pipelineId) ?? []).filter((log) => options.after === void 0 || log.sequence > options.after).slice(0, options.limit);
|
|
4747
4729
|
}
|
|
4748
|
-
|
|
4749
|
-
|
|
4750
|
-
|
|
4751
|
-
|
|
4752
|
-
|
|
4753
|
-
|
|
4754
|
-
|
|
4755
|
-
|
|
4756
|
-
|
|
4757
|
-
|
|
4758
|
-
|
|
4759
|
-
|
|
4760
|
-
|
|
4761
|
-
|
|
4762
|
-
|
|
4763
|
-
}
|
|
4764
|
-
];
|
|
4730
|
+
savePipelineRun(input) {
|
|
4731
|
+
const record = compact({
|
|
4732
|
+
runId: input.runId,
|
|
4733
|
+
pipelineId: input.pipelineId,
|
|
4734
|
+
status: input.status,
|
|
4735
|
+
input: input.input,
|
|
4736
|
+
output: input.output,
|
|
4737
|
+
error: input.error,
|
|
4738
|
+
metadata: input.metadata,
|
|
4739
|
+
startedAt: input.startedAt,
|
|
4740
|
+
endedAt: input.endedAt,
|
|
4741
|
+
durationMs: input.durationMs
|
|
4742
|
+
});
|
|
4743
|
+
this.pipelineRuns.set(input.runId, record);
|
|
4744
|
+
return record;
|
|
4765
4745
|
}
|
|
4766
|
-
|
|
4767
|
-
|
|
4768
|
-
|
|
4769
|
-
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
contentKind: "text",
|
|
4773
|
-
byteLength: byteLength3(message)
|
|
4774
|
-
};
|
|
4746
|
+
getPipelineRun(options) {
|
|
4747
|
+
const run = this.pipelineRuns.get(options.runId);
|
|
4748
|
+
return run?.pipelineId === options.pipelineId ? run : void 0;
|
|
4749
|
+
}
|
|
4750
|
+
listPipelineRuns(options) {
|
|
4751
|
+
return [...this.pipelineRuns.values()].filter((run) => run.pipelineId === options.pipelineId).sort((left, right) => Date.parse(right.startedAt) - Date.parse(left.startedAt)).slice(0, options.limit);
|
|
4775
4752
|
}
|
|
4753
|
+
};
|
|
4754
|
+
function sessionSummary(session) {
|
|
4755
|
+
return compact({
|
|
4756
|
+
id: session.id,
|
|
4757
|
+
agentId: session.agentId,
|
|
4758
|
+
title: session.title,
|
|
4759
|
+
createdAt: session.createdAt,
|
|
4760
|
+
updatedAt: session.updatedAt,
|
|
4761
|
+
messageCount: session.messages.length,
|
|
4762
|
+
metadata: session.metadata
|
|
4763
|
+
});
|
|
4764
|
+
}
|
|
4765
|
+
function materializeSession(session) {
|
|
4776
4766
|
return {
|
|
4777
|
-
|
|
4778
|
-
|
|
4779
|
-
|
|
4780
|
-
byteLength: byteLength3(formatUnknown2(message.content))
|
|
4767
|
+
...sessionSummary(session),
|
|
4768
|
+
messages: [...session.messages],
|
|
4769
|
+
transcript: renumberTranscript(session.runs.flatMap((run) => run.transcript))
|
|
4781
4770
|
};
|
|
4782
4771
|
}
|
|
4783
|
-
function
|
|
4784
|
-
|
|
4785
|
-
|
|
4786
|
-
|
|
4787
|
-
|
|
4788
|
-
|
|
4789
|
-
|
|
4790
|
-
|
|
4791
|
-
|
|
4792
|
-
|
|
4793
|
-
|
|
4772
|
+
function traceSummary2(trace) {
|
|
4773
|
+
return compact({
|
|
4774
|
+
id: trace.id,
|
|
4775
|
+
sessionId: trace.sessionId,
|
|
4776
|
+
name: trace.name,
|
|
4777
|
+
status: trace.status,
|
|
4778
|
+
startedAt: trace.startedAt,
|
|
4779
|
+
endedAt: trace.endedAt,
|
|
4780
|
+
durationMs: trace.durationMs,
|
|
4781
|
+
output: trace.output,
|
|
4782
|
+
error: trace.error,
|
|
4783
|
+
usage: trace.usage,
|
|
4784
|
+
metadata: trace.metadata,
|
|
4785
|
+
observationCount: trace.observations.length
|
|
4794
4786
|
});
|
|
4795
4787
|
}
|
|
4796
|
-
function
|
|
4797
|
-
const
|
|
4798
|
-
|
|
4799
|
-
if (item === void 0) {
|
|
4800
|
-
continue;
|
|
4801
|
-
}
|
|
4802
|
-
const jsonValue = cleanJsonValue(item);
|
|
4803
|
-
if (jsonValue !== void 0) {
|
|
4804
|
-
cleaned[key] = jsonValue;
|
|
4805
|
-
}
|
|
4806
|
-
}
|
|
4807
|
-
return cleaned;
|
|
4788
|
+
function traceAgentId(trace) {
|
|
4789
|
+
const nestedMetadata = trace.metadata?.metadata;
|
|
4790
|
+
return isJsonObject2(nestedMetadata) && typeof nestedMetadata.agentId === "string" ? nestedMetadata.agentId : void 0;
|
|
4808
4791
|
}
|
|
4809
|
-
function
|
|
4810
|
-
|
|
4811
|
-
|
|
4812
|
-
}
|
|
4813
|
-
if (Array.isArray(value)) {
|
|
4814
|
-
return value.map((item) => cleanJsonValue(item)).filter((item) => item !== void 0);
|
|
4815
|
-
}
|
|
4816
|
-
if (typeof value === "object" && value !== null) {
|
|
4817
|
-
return cleanMetadata2(value);
|
|
4818
|
-
}
|
|
4819
|
-
return void 0;
|
|
4792
|
+
function studioRunId(context) {
|
|
4793
|
+
const value = context.metadata?.studioRunId;
|
|
4794
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
4820
4795
|
}
|
|
4821
|
-
function
|
|
4822
|
-
|
|
4796
|
+
function serializeJsonError(error) {
|
|
4797
|
+
if (error instanceof Error) {
|
|
4798
|
+
return {
|
|
4799
|
+
name: error.name,
|
|
4800
|
+
message: error.message
|
|
4801
|
+
};
|
|
4802
|
+
}
|
|
4803
|
+
return isJsonValue3(error) ? error : String(error);
|
|
4823
4804
|
}
|
|
4824
|
-
function
|
|
4825
|
-
return value ===
|
|
4805
|
+
function isJsonObject2(value) {
|
|
4806
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4826
4807
|
}
|
|
4827
|
-
function
|
|
4828
|
-
if (typeof value === "string") {
|
|
4829
|
-
return
|
|
4808
|
+
function isJsonValue3(value) {
|
|
4809
|
+
if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
4810
|
+
return true;
|
|
4830
4811
|
}
|
|
4831
|
-
|
|
4832
|
-
return
|
|
4833
|
-
} catch {
|
|
4834
|
-
return String(value);
|
|
4812
|
+
if (Array.isArray(value)) {
|
|
4813
|
+
return value.every(isJsonValue3);
|
|
4835
4814
|
}
|
|
4815
|
+
return isJsonObject2(value) && Object.values(value).every(isJsonValue3);
|
|
4836
4816
|
}
|
|
4837
4817
|
|
|
4838
|
-
// src/runtime/
|
|
4839
|
-
function
|
|
4840
|
-
|
|
4841
|
-
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
|
|
4847
|
-
|
|
4848
|
-
|
|
4849
|
-
|
|
4850
|
-
...agentId === void 0 ? {} : { agentId },
|
|
4851
|
-
limit
|
|
4852
|
-
});
|
|
4853
|
-
return c.json({ sessions });
|
|
4854
|
-
});
|
|
4855
|
-
app.post("/sessions", async (c) => {
|
|
4856
|
-
const body = await parseCreateSessionRequest(c);
|
|
4857
|
-
if ("error" in body) {
|
|
4858
|
-
return body.error;
|
|
4859
|
-
}
|
|
4860
|
-
if (!props.agentMap.has(body.agentId)) {
|
|
4861
|
-
return errorResponse(c, 404, "not_found", "Agent not found");
|
|
4862
|
-
}
|
|
4863
|
-
const session = await props.sessionStore.createSession({
|
|
4864
|
-
id: globalThis.crypto.randomUUID(),
|
|
4865
|
-
agentId: body.agentId,
|
|
4866
|
-
...body.title === void 0 ? {} : { title: body.title },
|
|
4867
|
-
...body.metadata === void 0 ? {} : { metadata: body.metadata }
|
|
4868
|
-
});
|
|
4869
|
-
await appendSessionLog(props.sessionStore, sessionCreatedLog(session));
|
|
4870
|
-
return c.json(session, 201);
|
|
4871
|
-
});
|
|
4872
|
-
app.get("/sessions/:sessionId", async (c) => {
|
|
4873
|
-
const session = await props.sessionStore.getSession(c.req.param("sessionId"));
|
|
4874
|
-
if (session === void 0) {
|
|
4875
|
-
return errorResponse(c, 404, "not_found", "Session not found");
|
|
4876
|
-
}
|
|
4877
|
-
return c.json(session);
|
|
4878
|
-
});
|
|
4879
|
-
app.get("/sessions/:sessionId/logs", async (c) => {
|
|
4880
|
-
const sessionId = c.req.param("sessionId");
|
|
4881
|
-
const session = await props.sessionStore.getSession(sessionId);
|
|
4882
|
-
if (session === void 0) {
|
|
4883
|
-
return errorResponse(c, 404, "not_found", "Session not found");
|
|
4884
|
-
}
|
|
4885
|
-
if (props.sessionStore.listSessionLogs === void 0) {
|
|
4886
|
-
return errorResponse(
|
|
4887
|
-
c,
|
|
4888
|
-
501,
|
|
4889
|
-
"unsupported_capability",
|
|
4890
|
-
'Capability "sessions.logs" is not implemented by this runner',
|
|
4891
|
-
{ capability: "sessions", operation: "logs" }
|
|
4892
|
-
);
|
|
4893
|
-
}
|
|
4894
|
-
const limit = parseSessionLogLimit(c.req.query("limit"));
|
|
4895
|
-
if (limit === void 0) {
|
|
4896
|
-
return errorResponse(c, 400, "bad_request", "limit must be a positive integer");
|
|
4897
|
-
}
|
|
4898
|
-
const after = parseSessionLogAfter(c.req.query("after"));
|
|
4899
|
-
if (after === false) {
|
|
4900
|
-
return errorResponse(c, 400, "bad_request", "after must be a non-negative integer");
|
|
4901
|
-
}
|
|
4902
|
-
const logs = await props.sessionStore.listSessionLogs({
|
|
4903
|
-
sessionId,
|
|
4904
|
-
limit,
|
|
4905
|
-
...after === void 0 ? {} : { after }
|
|
4906
|
-
});
|
|
4907
|
-
const last = logs.at(-1);
|
|
4908
|
-
return c.json({
|
|
4909
|
-
logs,
|
|
4910
|
-
...logs.length === limit && last !== void 0 ? { nextCursor: last.sequence } : {}
|
|
4911
|
-
});
|
|
4912
|
-
});
|
|
4913
|
-
app.delete("/sessions/:sessionId", async (c) => {
|
|
4914
|
-
if (props.sessionStore.deleteSession === void 0) {
|
|
4915
|
-
return errorResponse(
|
|
4916
|
-
c,
|
|
4917
|
-
501,
|
|
4918
|
-
"unsupported_capability",
|
|
4919
|
-
'Capability "sessions.delete" is not implemented by this runner',
|
|
4920
|
-
{ capability: "sessions", operation: "delete" }
|
|
4921
|
-
);
|
|
4922
|
-
}
|
|
4923
|
-
const deleted = await props.sessionStore.deleteSession(c.req.param("sessionId"));
|
|
4924
|
-
if (!deleted) {
|
|
4925
|
-
return errorResponse(c, 404, "not_found", "Session not found");
|
|
4926
|
-
}
|
|
4927
|
-
return c.body(null, 204);
|
|
4928
|
-
});
|
|
4929
|
-
app.get("/sessions/:sessionId/traces", async (c) => {
|
|
4930
|
-
if (props.traceStore === void 0) {
|
|
4931
|
-
return unsupportedCapability(c, "traces");
|
|
4932
|
-
}
|
|
4933
|
-
const sessionId = c.req.param("sessionId");
|
|
4934
|
-
const session = await props.sessionStore.getSession(sessionId);
|
|
4935
|
-
if (session === void 0) {
|
|
4936
|
-
return errorResponse(c, 404, "not_found", "Session not found");
|
|
4937
|
-
}
|
|
4938
|
-
const limit = parseLimit(c.req.query("limit"));
|
|
4939
|
-
if (limit === void 0) {
|
|
4940
|
-
return errorResponse(c, 400, "bad_request", "limit must be a positive integer");
|
|
4941
|
-
}
|
|
4942
|
-
const traces = await props.traceStore.listSessionTraces({ sessionId, limit });
|
|
4943
|
-
return c.json({ traces });
|
|
4818
|
+
// src/runtime/shared.ts
|
|
4819
|
+
function resolveStores(options) {
|
|
4820
|
+
const defaultStore = defaultStudioStore();
|
|
4821
|
+
const sessions = resolveSessionStore(options, defaultStore);
|
|
4822
|
+
const traces = resolveTraceStore(options, sessions, defaultStore);
|
|
4823
|
+
const pipelineLogs = resolvePipelineLogStore(options, sessions, defaultStore);
|
|
4824
|
+
const pipelineRuns = resolvePipelineRunStore(options, sessions, pipelineLogs, defaultStore);
|
|
4825
|
+
return compact({
|
|
4826
|
+
sessions,
|
|
4827
|
+
traces,
|
|
4828
|
+
pipelineLogs,
|
|
4829
|
+
pipelineRuns
|
|
4944
4830
|
});
|
|
4945
4831
|
}
|
|
4946
|
-
function
|
|
4947
|
-
|
|
4948
|
-
|
|
4832
|
+
function defaultStudioStore() {
|
|
4833
|
+
return createInMemoryStudioStore();
|
|
4834
|
+
}
|
|
4835
|
+
function resolveSessionStore(options, defaultStore) {
|
|
4836
|
+
if (options.stores?.sessions === false) {
|
|
4837
|
+
return void 0;
|
|
4949
4838
|
}
|
|
4950
|
-
|
|
4951
|
-
|
|
4839
|
+
if (options.stores?.sessions !== void 0) {
|
|
4840
|
+
return options.stores.sessions;
|
|
4841
|
+
}
|
|
4842
|
+
return defaultStore;
|
|
4843
|
+
}
|
|
4844
|
+
function resolveTraceStore(options, sessionStore, defaultStore) {
|
|
4845
|
+
if (options.stores?.traces !== void 0) {
|
|
4846
|
+
return options.stores.traces;
|
|
4847
|
+
}
|
|
4848
|
+
if (sessionStore === void 0) {
|
|
4952
4849
|
return void 0;
|
|
4953
4850
|
}
|
|
4954
|
-
|
|
4851
|
+
if (isTraceStore(sessionStore)) {
|
|
4852
|
+
return sessionStore;
|
|
4853
|
+
}
|
|
4854
|
+
return defaultStore;
|
|
4955
4855
|
}
|
|
4956
|
-
function
|
|
4957
|
-
if (
|
|
4856
|
+
function resolvePipelineLogStore(options, sessionStore, defaultStore) {
|
|
4857
|
+
if (options.stores?.pipelineLogs === false) {
|
|
4958
4858
|
return void 0;
|
|
4959
4859
|
}
|
|
4960
|
-
|
|
4961
|
-
|
|
4962
|
-
return false;
|
|
4860
|
+
if (options.stores?.pipelineLogs !== void 0) {
|
|
4861
|
+
return options.stores.pipelineLogs;
|
|
4963
4862
|
}
|
|
4964
|
-
|
|
4863
|
+
if (sessionStore !== void 0 && isPipelineLogStore(sessionStore)) {
|
|
4864
|
+
return sessionStore;
|
|
4865
|
+
}
|
|
4866
|
+
return defaultStore;
|
|
4965
4867
|
}
|
|
4966
|
-
|
|
4967
|
-
|
|
4968
|
-
|
|
4969
|
-
body = await c.req.json();
|
|
4970
|
-
} catch {
|
|
4971
|
-
return { error: errorResponse(c, 400, "bad_request", "Request body must be JSON") };
|
|
4868
|
+
function resolvePipelineRunStore(options, sessionStore, pipelineLogStore, defaultStore) {
|
|
4869
|
+
if (options.stores?.pipelineRuns === false) {
|
|
4870
|
+
return void 0;
|
|
4972
4871
|
}
|
|
4973
|
-
if (
|
|
4974
|
-
return
|
|
4872
|
+
if (options.stores?.pipelineRuns !== void 0) {
|
|
4873
|
+
return options.stores.pipelineRuns;
|
|
4975
4874
|
}
|
|
4976
|
-
if (
|
|
4977
|
-
return
|
|
4875
|
+
if (sessionStore !== void 0 && isPipelineRunStore(sessionStore)) {
|
|
4876
|
+
return sessionStore;
|
|
4978
4877
|
}
|
|
4979
|
-
|
|
4980
|
-
|
|
4981
|
-
}
|
|
4982
|
-
|
|
4983
|
-
|
|
4984
|
-
|
|
4878
|
+
if (pipelineLogStore !== void 0 && isPipelineRunStore(pipelineLogStore)) {
|
|
4879
|
+
return pipelineLogStore;
|
|
4880
|
+
}
|
|
4881
|
+
return defaultStore;
|
|
4882
|
+
}
|
|
4883
|
+
function isTraceStore(store) {
|
|
4884
|
+
const candidate = store;
|
|
4885
|
+
return typeof candidate.listSessionTraces === "function" && typeof candidate.getTrace === "function" && typeof candidate.saveTrace === "function";
|
|
4886
|
+
}
|
|
4887
|
+
function isPipelineLogStore(store) {
|
|
4888
|
+
const candidate = store;
|
|
4889
|
+
return typeof candidate.appendPipelineLog === "function" && typeof candidate.listPipelineLogs === "function";
|
|
4890
|
+
}
|
|
4891
|
+
function isPipelineRunStore(store) {
|
|
4892
|
+
const candidate = store;
|
|
4893
|
+
return typeof candidate.savePipelineRun === "function" && typeof candidate.getPipelineRun === "function" && typeof candidate.listPipelineRuns === "function";
|
|
4894
|
+
}
|
|
4895
|
+
function normalizeAgents(agents) {
|
|
4896
|
+
const ids = /* @__PURE__ */ new Set();
|
|
4897
|
+
return agents.map((agent) => {
|
|
4898
|
+
const id = agent.id.trim();
|
|
4899
|
+
if (id.length === 0) {
|
|
4900
|
+
throw new Error("Studio agent id cannot be empty");
|
|
4985
4901
|
}
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
request.title = title;
|
|
4902
|
+
if (ids.has(id)) {
|
|
4903
|
+
throw new Error(`Duplicate runner agent id: ${id}`);
|
|
4989
4904
|
}
|
|
4990
|
-
|
|
4991
|
-
|
|
4992
|
-
|
|
4993
|
-
|
|
4905
|
+
ids.add(id);
|
|
4906
|
+
return { ...agent, id };
|
|
4907
|
+
});
|
|
4908
|
+
}
|
|
4909
|
+
function normalizePipelines(pipelines) {
|
|
4910
|
+
const ids = /* @__PURE__ */ new Set();
|
|
4911
|
+
return pipelines.map((pipeline) => {
|
|
4912
|
+
const id = pipeline.id.trim();
|
|
4913
|
+
if (id.length === 0) {
|
|
4914
|
+
throw new Error("Studio pipeline id cannot be empty");
|
|
4994
4915
|
}
|
|
4995
|
-
|
|
4996
|
-
|
|
4997
|
-
|
|
4916
|
+
if (ids.has(id)) {
|
|
4917
|
+
throw new Error(`Duplicate Studio pipeline id: ${id}`);
|
|
4918
|
+
}
|
|
4919
|
+
ids.add(id);
|
|
4920
|
+
return { ...pipeline, id };
|
|
4921
|
+
});
|
|
4998
4922
|
}
|
|
4999
4923
|
|
|
5000
4924
|
// src/runtime/status.ts
|
|
@@ -5003,30 +4927,31 @@ function registerStatusRoutes(app, props) {
|
|
|
5003
4927
|
const summary = {
|
|
5004
4928
|
runner: {
|
|
5005
4929
|
id: runnerId(props.options),
|
|
5006
|
-
...props.options.name
|
|
5007
|
-
...props.options.version === void 0 ? {} : { version: props.options.version }
|
|
4930
|
+
...compact({ name: props.options.name, version: props.options.version })
|
|
5008
4931
|
},
|
|
5009
4932
|
storage: {
|
|
5010
|
-
...
|
|
5011
|
-
|
|
5012
|
-
|
|
5013
|
-
|
|
4933
|
+
...compact({
|
|
4934
|
+
sessions: props.stores.sessions?.kind,
|
|
4935
|
+
traces: props.stores.traces?.kind,
|
|
4936
|
+
pipelineLogs: props.stores.pipelineLogs !== void 0 ? "available" : void 0,
|
|
4937
|
+
pipelineRuns: props.stores.pipelineRuns !== void 0 ? "available" : void 0
|
|
4938
|
+
})
|
|
5014
4939
|
},
|
|
5015
4940
|
counts: {
|
|
5016
4941
|
agents: props.agents.length,
|
|
5017
4942
|
pipelines: props.pipelines.length,
|
|
5018
|
-
...
|
|
5019
|
-
|
|
5020
|
-
|
|
5021
|
-
pipelineRuns: (await Promise.all(
|
|
4943
|
+
...compact({
|
|
4944
|
+
sessions: props.stores.sessions !== void 0 ? (await props.stores.sessions.listSessions({ limit: 100 })).length : void 0,
|
|
4945
|
+
traces: props.stores.traces?.listTraces !== void 0 ? (await props.stores.traces.listTraces({ limit: 100 })).length : void 0,
|
|
4946
|
+
pipelineRuns: props.stores.pipelineRuns !== void 0 && props.pipelines.length > 0 ? (await Promise.all(
|
|
5022
4947
|
props.pipelines.map(
|
|
5023
4948
|
(pipeline) => props.stores.pipelineRuns?.listPipelineRuns({
|
|
5024
4949
|
pipelineId: pipeline.id,
|
|
5025
4950
|
limit: 100
|
|
5026
4951
|
})
|
|
5027
4952
|
)
|
|
5028
|
-
)).reduce((sum, runs) => sum + (runs?.length ?? 0), 0)
|
|
5029
|
-
}
|
|
4953
|
+
)).reduce((sum, runs) => sum + (runs?.length ?? 0), 0) : void 0
|
|
4954
|
+
})
|
|
5030
4955
|
},
|
|
5031
4956
|
capabilities: capabilityConfig(props.options, props.agents, props.pipelines, props.stores),
|
|
5032
4957
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -5110,16 +5035,16 @@ async function parseToolRunRequest(c) {
|
|
|
5110
5035
|
if (body === void 0 || body === null) {
|
|
5111
5036
|
return { args: {} };
|
|
5112
5037
|
}
|
|
5113
|
-
if (!
|
|
5038
|
+
if (!isJsonObject(body)) {
|
|
5114
5039
|
return { error: errorResponse(c, 400, "bad_request", "Request body must be an object") };
|
|
5115
5040
|
}
|
|
5116
5041
|
const args = Object.hasOwn(body, "args") ? body.args : {};
|
|
5117
|
-
if (!
|
|
5042
|
+
if (!isJsonValue(args)) {
|
|
5118
5043
|
return { error: errorResponse(c, 400, "bad_request", "args must be JSON-compatible") };
|
|
5119
5044
|
}
|
|
5120
5045
|
const request = { args };
|
|
5121
5046
|
if (Object.hasOwn(body, "context")) {
|
|
5122
|
-
if (!
|
|
5047
|
+
if (!isJsonObject(body.context)) {
|
|
5123
5048
|
return { error: errorResponse(c, 400, "bad_request", "context must be an object") };
|
|
5124
5049
|
}
|
|
5125
5050
|
request.context = body.context;
|
|
@@ -5177,9 +5102,7 @@ function registerTraceRoutes(app, traceStore) {
|
|
|
5177
5102
|
const sessionId = optionalQueryString(c.req.query("sessionId"));
|
|
5178
5103
|
const traces = await traceStore.listTraces({
|
|
5179
5104
|
limit,
|
|
5180
|
-
...
|
|
5181
|
-
...sessionId === void 0 ? {} : { sessionId },
|
|
5182
|
-
...status === void 0 ? {} : { status }
|
|
5105
|
+
...compact({ agentId, sessionId, status })
|
|
5183
5106
|
});
|
|
5184
5107
|
return c.json({ traces });
|
|
5185
5108
|
});
|
|
@@ -5222,7 +5145,7 @@ var Studio = class {
|
|
|
5222
5145
|
const port = serveOptions.port ?? Number(process.env.RUNNER_PORT ?? 4021);
|
|
5223
5146
|
this.server = serve({
|
|
5224
5147
|
fetch: (request) => this.fetch(request),
|
|
5225
|
-
...
|
|
5148
|
+
...compact({ hostname: serveOptions.hostname }),
|
|
5226
5149
|
port
|
|
5227
5150
|
});
|
|
5228
5151
|
const log = serveOptions.log ?? true;
|
|
@@ -5262,9 +5185,9 @@ function studioOptionsFromTargets(targets, options) {
|
|
|
5262
5185
|
agents: inferStudioAgents(agents, options.quickPrompts ?? {}),
|
|
5263
5186
|
pipelines: inferStudioPipelines(pipelines),
|
|
5264
5187
|
evals: options.evals ?? [],
|
|
5265
|
-
...
|
|
5266
|
-
...
|
|
5267
|
-
...
|
|
5188
|
+
...compact({ models: options.models }),
|
|
5189
|
+
...compact({ stores: options.stores }),
|
|
5190
|
+
...compact({ ui: options.ui })
|
|
5268
5191
|
};
|
|
5269
5192
|
}
|
|
5270
5193
|
function inferStudioAgents(agents, quickPrompts) {
|
|
@@ -5286,9 +5209,9 @@ function inferStudioPipelines(pipelines) {
|
|
|
5286
5209
|
return {
|
|
5287
5210
|
id,
|
|
5288
5211
|
pipeline,
|
|
5289
|
-
...
|
|
5290
|
-
...
|
|
5291
|
-
...
|
|
5212
|
+
...compact({ name: pipeline.name }),
|
|
5213
|
+
...compact({ description: pipeline.description }),
|
|
5214
|
+
...compact({ metadata: pipeline.metadata })
|
|
5292
5215
|
};
|
|
5293
5216
|
});
|
|
5294
5217
|
}
|
|
@@ -5304,7 +5227,7 @@ function uniqueAgentId(baseId, ids) {
|
|
|
5304
5227
|
}
|
|
5305
5228
|
function agentMetadata(agent) {
|
|
5306
5229
|
return {
|
|
5307
|
-
...
|
|
5230
|
+
...compact({ defaultMaxTurns: agent.defaultMaxTurns }),
|
|
5308
5231
|
staticContextCount: agent.staticContext.length,
|
|
5309
5232
|
dynamicContextCount: agent.dynamicContexts.length,
|
|
5310
5233
|
dynamicToolCount: agent.dynamicTools.length,
|
|
@@ -5375,13 +5298,13 @@ function createStudioApp(options) {
|
|
|
5375
5298
|
});
|
|
5376
5299
|
registerKnowledgeRoutes(app, {
|
|
5377
5300
|
agents,
|
|
5378
|
-
...
|
|
5301
|
+
...compact({ traceStore: stores.traces })
|
|
5379
5302
|
});
|
|
5380
5303
|
registerPipelineRoutes(app, {
|
|
5381
5304
|
pipelines,
|
|
5382
5305
|
pipelineMap,
|
|
5383
|
-
...
|
|
5384
|
-
...
|
|
5306
|
+
...compact({ logStore: stores.pipelineLogs }),
|
|
5307
|
+
...compact({ runStore: stores.pipelineRuns })
|
|
5385
5308
|
});
|
|
5386
5309
|
app.post("/agents/:agentId/runs", async (c) => {
|
|
5387
5310
|
const agentId = c.req.param("agentId");
|
|
@@ -5428,8 +5351,8 @@ function createStudioApp(options) {
|
|
|
5428
5351
|
agentId,
|
|
5429
5352
|
message: body.message,
|
|
5430
5353
|
stream: body.stream === true,
|
|
5431
|
-
...
|
|
5432
|
-
...
|
|
5354
|
+
...compact({ maxTurns: body.maxTurns }),
|
|
5355
|
+
...compact({ toolConcurrency: body.toolConcurrency }),
|
|
5433
5356
|
hasTrace: body.trace !== void 0,
|
|
5434
5357
|
...body.metadata === void 0 && selectedModel.ref === void 0 ? {} : {
|
|
5435
5358
|
metadata: {
|
|
@@ -5492,23 +5415,22 @@ function createStudioApp(options) {
|
|
|
5492
5415
|
}
|
|
5493
5416
|
if (body.stream === true) {
|
|
5494
5417
|
const runtimeEvents = new AsyncEventQueue();
|
|
5418
|
+
request.approvals(
|
|
5419
|
+
approvalRuntime.createApprovals({
|
|
5420
|
+
runId,
|
|
5421
|
+
agentId,
|
|
5422
|
+
...compact({ sessionId: session?.id }),
|
|
5423
|
+
...compact({ metadata: body.metadata }),
|
|
5424
|
+
emit: (event) => runtimeEvents.push(event)
|
|
5425
|
+
})
|
|
5426
|
+
);
|
|
5495
5427
|
const effectiveHook = composeHooks(
|
|
5496
|
-
|
|
5497
|
-
runAgent.hook,
|
|
5498
|
-
approvalRuntime.createHook({
|
|
5499
|
-
runId,
|
|
5500
|
-
agentId,
|
|
5501
|
-
...session?.id === void 0 ? {} : { sessionId: session.id },
|
|
5502
|
-
...body.metadata === void 0 ? {} : { metadata: body.metadata },
|
|
5503
|
-
getTool: (toolName) => runAgent.getTool(toolName),
|
|
5504
|
-
emit: (event) => runtimeEvents.push(event)
|
|
5505
|
-
})
|
|
5506
|
-
),
|
|
5428
|
+
runAgent.hook,
|
|
5507
5429
|
questionRuntime.createHook({
|
|
5508
5430
|
runId,
|
|
5509
5431
|
agentId,
|
|
5510
|
-
...
|
|
5511
|
-
...
|
|
5432
|
+
...compact({ sessionId: session?.id }),
|
|
5433
|
+
...compact({ metadata: body.metadata }),
|
|
5512
5434
|
emit: (event) => runtimeEvents.push(event)
|
|
5513
5435
|
})
|
|
5514
5436
|
);
|
|
@@ -5538,21 +5460,20 @@ function createStudioApp(options) {
|
|
|
5538
5460
|
await appendSessionLog(sessionStore, memoryLoadedLog(session, runId));
|
|
5539
5461
|
}
|
|
5540
5462
|
const effectiveHook = composeHooks(
|
|
5541
|
-
|
|
5542
|
-
runAgent.hook,
|
|
5543
|
-
approvalRuntime.createHook({
|
|
5544
|
-
runId,
|
|
5545
|
-
agentId,
|
|
5546
|
-
...session?.id === void 0 ? {} : { sessionId: session.id },
|
|
5547
|
-
...body.metadata === void 0 ? {} : { metadata: body.metadata },
|
|
5548
|
-
getTool: (toolName) => runAgent.getTool(toolName)
|
|
5549
|
-
})
|
|
5550
|
-
),
|
|
5463
|
+
runAgent.hook,
|
|
5551
5464
|
questionRuntime.createHook({
|
|
5552
5465
|
runId,
|
|
5553
5466
|
agentId,
|
|
5554
|
-
...
|
|
5555
|
-
...
|
|
5467
|
+
...compact({ sessionId: session?.id }),
|
|
5468
|
+
...compact({ metadata: body.metadata })
|
|
5469
|
+
})
|
|
5470
|
+
);
|
|
5471
|
+
request.approvals(
|
|
5472
|
+
approvalRuntime.createApprovals({
|
|
5473
|
+
runId,
|
|
5474
|
+
agentId,
|
|
5475
|
+
...compact({ sessionId: session?.id }),
|
|
5476
|
+
...compact({ metadata: body.metadata })
|
|
5556
5477
|
})
|
|
5557
5478
|
);
|
|
5558
5479
|
if (effectiveHook !== void 0) {
|
|
@@ -5625,7 +5546,7 @@ function createStudioApp(options) {
|
|
|
5625
5546
|
registerSessionRoutes(app, {
|
|
5626
5547
|
agentMap,
|
|
5627
5548
|
sessionStore: stores.sessions,
|
|
5628
|
-
...
|
|
5549
|
+
...compact({ traceStore: stores.traces })
|
|
5629
5550
|
});
|
|
5630
5551
|
}
|
|
5631
5552
|
if (stores.traces !== void 0) {
|
|
@@ -5645,8 +5566,8 @@ function createStudioApp(options) {
|
|
|
5645
5566
|
},
|
|
5646
5567
|
close() {
|
|
5647
5568
|
},
|
|
5648
|
-
...
|
|
5649
|
-
...
|
|
5569
|
+
...compact({ sessionStore: stores.sessions }),
|
|
5570
|
+
...compact({ traceStore: stores.traces })
|
|
5650
5571
|
};
|
|
5651
5572
|
}
|
|
5652
5573
|
function normalizePromptMessage(message) {
|
|
@@ -5704,7 +5625,7 @@ function composeHooks(first, second) {
|
|
|
5704
5625
|
if (second === void 0) {
|
|
5705
5626
|
return first;
|
|
5706
5627
|
}
|
|
5707
|
-
return
|
|
5628
|
+
return createHook2({
|
|
5708
5629
|
async onCompletionCall(args) {
|
|
5709
5630
|
const firstAction = await first.onCompletionCall?.(args);
|
|
5710
5631
|
return firstAction?.type === "terminate" ? firstAction : await second.onCompletionCall?.(args) ?? void 0;
|
|
@@ -5715,12 +5636,9 @@ function composeHooks(first, second) {
|
|
|
5715
5636
|
},
|
|
5716
5637
|
async onToolCall(args) {
|
|
5717
5638
|
const firstAction = await first.onToolCall?.(args);
|
|
5718
|
-
if (firstAction?.type === "skip" || firstAction?.type === "terminate") {
|
|
5639
|
+
if (firstAction?.type === "skip" || firstAction?.type === "terminate" || firstAction?.type === "approval_request") {
|
|
5719
5640
|
return firstAction;
|
|
5720
5641
|
}
|
|
5721
|
-
if (firstAction?.type === "approval_request") {
|
|
5722
|
-
return await approvalRequestHandler(second)?.(args, firstAction) ?? firstAction;
|
|
5723
|
-
}
|
|
5724
5642
|
const secondAction = await second.onToolCall?.(args);
|
|
5725
5643
|
return secondAction ?? firstAction ?? void 0;
|
|
5726
5644
|
},
|
|
@@ -5730,10 +5648,6 @@ function composeHooks(first, second) {
|
|
|
5730
5648
|
}
|
|
5731
5649
|
});
|
|
5732
5650
|
}
|
|
5733
|
-
function approvalRequestHandler(hook) {
|
|
5734
|
-
const candidate = hook;
|
|
5735
|
-
return typeof candidate.handleApprovalRequest === "function" ? candidate.handleApprovalRequest : void 0;
|
|
5736
|
-
}
|
|
5737
5651
|
|
|
5738
5652
|
// src/storage/sqlite-store.ts
|
|
5739
5653
|
import { mkdirSync } from "fs";
|
|
@@ -5790,11 +5704,11 @@ var SqliteSessionStore = class {
|
|
|
5790
5704
|
return {
|
|
5791
5705
|
id: input.id,
|
|
5792
5706
|
agentId: input.agentId,
|
|
5793
|
-
...
|
|
5707
|
+
...compact({ title: input.title }),
|
|
5794
5708
|
createdAt: now,
|
|
5795
5709
|
updatedAt: now,
|
|
5796
5710
|
messageCount: 0,
|
|
5797
|
-
...
|
|
5711
|
+
...compact({ metadata: input.metadata })
|
|
5798
5712
|
};
|
|
5799
5713
|
}
|
|
5800
5714
|
getSession(id) {
|
|
@@ -5980,14 +5894,14 @@ var SqliteSessionStore = class {
|
|
|
5980
5894
|
const entry = {
|
|
5981
5895
|
id: globalThis.crypto.randomUUID(),
|
|
5982
5896
|
sessionId: input.sessionId,
|
|
5983
|
-
...
|
|
5897
|
+
...compact({ runId: input.runId }),
|
|
5984
5898
|
sequence,
|
|
5985
5899
|
timestamp: now,
|
|
5986
5900
|
level: input.level,
|
|
5987
5901
|
category: input.category,
|
|
5988
5902
|
event: input.event,
|
|
5989
5903
|
message: input.message,
|
|
5990
|
-
...
|
|
5904
|
+
...compact({ metadata: input.metadata })
|
|
5991
5905
|
};
|
|
5992
5906
|
db.prepare(
|
|
5993
5907
|
`INSERT INTO anvia_studio_session_logs (
|
|
@@ -6061,14 +5975,14 @@ var SqliteSessionStore = class {
|
|
|
6061
5975
|
const entry = {
|
|
6062
5976
|
id: globalThis.crypto.randomUUID(),
|
|
6063
5977
|
pipelineId: input.pipelineId,
|
|
6064
|
-
...
|
|
5978
|
+
...compact({ runId: input.runId }),
|
|
6065
5979
|
sequence,
|
|
6066
5980
|
timestamp: now,
|
|
6067
5981
|
level: input.level,
|
|
6068
5982
|
category: input.category,
|
|
6069
5983
|
event: input.event,
|
|
6070
5984
|
message: input.message,
|
|
6071
|
-
...
|
|
5985
|
+
...compact({ metadata: input.metadata })
|
|
6072
5986
|
};
|
|
6073
5987
|
db.prepare(
|
|
6074
5988
|
`INSERT INTO anvia_studio_pipeline_logs (
|
|
@@ -6186,12 +6100,12 @@ var SqliteSessionStore = class {
|
|
|
6186
6100
|
pipelineId: input.pipelineId,
|
|
6187
6101
|
status: input.status,
|
|
6188
6102
|
input: input.input,
|
|
6189
|
-
...
|
|
6190
|
-
...
|
|
6191
|
-
...
|
|
6103
|
+
...compact({ output: input.output }),
|
|
6104
|
+
...compact({ error: input.error }),
|
|
6105
|
+
...compact({ metadata: input.metadata }),
|
|
6192
6106
|
startedAt: input.startedAt,
|
|
6193
|
-
...
|
|
6194
|
-
...
|
|
6107
|
+
...compact({ endedAt: input.endedAt }),
|
|
6108
|
+
...compact({ durationMs: input.durationMs })
|
|
6195
6109
|
};
|
|
6196
6110
|
}
|
|
6197
6111
|
getPipelineRun(options) {
|
|
@@ -6622,11 +6536,11 @@ function toSessionSummary(row) {
|
|
|
6622
6536
|
return {
|
|
6623
6537
|
id: row.id,
|
|
6624
6538
|
agentId: row.agent_id,
|
|
6625
|
-
...
|
|
6539
|
+
...compact({ title: row.title ?? void 0 }),
|
|
6626
6540
|
createdAt: row.created_at,
|
|
6627
6541
|
updatedAt: row.updated_at,
|
|
6628
6542
|
messageCount: row.message_count,
|
|
6629
|
-
...
|
|
6543
|
+
...compact({ metadata })
|
|
6630
6544
|
};
|
|
6631
6545
|
}
|
|
6632
6546
|
function toSessionLog(row) {
|
|
@@ -6634,14 +6548,14 @@ function toSessionLog(row) {
|
|
|
6634
6548
|
return {
|
|
6635
6549
|
id: row.id,
|
|
6636
6550
|
sessionId: row.session_id,
|
|
6637
|
-
...
|
|
6551
|
+
...compact({ runId: row.run_id ?? void 0 }),
|
|
6638
6552
|
sequence: row.sequence,
|
|
6639
6553
|
timestamp: row.timestamp,
|
|
6640
6554
|
level: row.level,
|
|
6641
6555
|
category: row.category,
|
|
6642
6556
|
event: row.event,
|
|
6643
6557
|
message: row.message,
|
|
6644
|
-
...
|
|
6558
|
+
...compact({ metadata })
|
|
6645
6559
|
};
|
|
6646
6560
|
}
|
|
6647
6561
|
function toPipelineLog(row) {
|
|
@@ -6649,14 +6563,14 @@ function toPipelineLog(row) {
|
|
|
6649
6563
|
return {
|
|
6650
6564
|
id: row.id,
|
|
6651
6565
|
pipelineId: row.pipeline_id,
|
|
6652
|
-
...
|
|
6566
|
+
...compact({ runId: row.run_id ?? void 0 }),
|
|
6653
6567
|
sequence: row.sequence,
|
|
6654
6568
|
timestamp: row.timestamp,
|
|
6655
6569
|
level: row.level,
|
|
6656
6570
|
category: row.category,
|
|
6657
6571
|
event: row.event,
|
|
6658
6572
|
message: row.message,
|
|
6659
|
-
...
|
|
6573
|
+
...compact({ metadata })
|
|
6660
6574
|
};
|
|
6661
6575
|
}
|
|
6662
6576
|
function toPipelineRun(row) {
|
|
@@ -6668,12 +6582,12 @@ function toPipelineRun(row) {
|
|
|
6668
6582
|
pipelineId: row.pipeline_id,
|
|
6669
6583
|
status: row.status,
|
|
6670
6584
|
input: JSON.parse(row.input_json),
|
|
6671
|
-
...
|
|
6672
|
-
...
|
|
6673
|
-
...
|
|
6585
|
+
...compact({ output }),
|
|
6586
|
+
...compact({ error }),
|
|
6587
|
+
...compact({ metadata }),
|
|
6674
6588
|
startedAt: row.started_at,
|
|
6675
|
-
...
|
|
6676
|
-
...
|
|
6589
|
+
...compact({ endedAt: row.ended_at ?? void 0 }),
|
|
6590
|
+
...compact({ durationMs: row.duration_ms ?? void 0 })
|
|
6677
6591
|
};
|
|
6678
6592
|
}
|
|
6679
6593
|
function messageParts(message) {
|
|
@@ -6699,7 +6613,7 @@ function messageFromRows(row, partRows) {
|
|
|
6699
6613
|
if (row.role === "assistant") {
|
|
6700
6614
|
return {
|
|
6701
6615
|
role: "assistant",
|
|
6702
|
-
...
|
|
6616
|
+
...compact({ id: row.message_id ?? void 0 }),
|
|
6703
6617
|
content: parts
|
|
6704
6618
|
};
|
|
6705
6619
|
}
|
|
@@ -6747,8 +6661,8 @@ function toTrace(row) {
|
|
|
6747
6661
|
const input = parseJsonValue(row.input_json);
|
|
6748
6662
|
return {
|
|
6749
6663
|
...toTraceSummary(row),
|
|
6750
|
-
...
|
|
6751
|
-
...
|
|
6664
|
+
...compact({ trace }),
|
|
6665
|
+
...compact({ input }),
|
|
6752
6666
|
observations: parseJsonArray(row.observations_json)
|
|
6753
6667
|
};
|
|
6754
6668
|
}
|
|
@@ -6760,15 +6674,15 @@ function toTraceSummary(row) {
|
|
|
6760
6674
|
return {
|
|
6761
6675
|
id: row.id,
|
|
6762
6676
|
sessionId: row.session_id,
|
|
6763
|
-
...
|
|
6677
|
+
...compact({ name: row.name ?? void 0 }),
|
|
6764
6678
|
status: row.status,
|
|
6765
6679
|
startedAt: row.started_at,
|
|
6766
|
-
...
|
|
6767
|
-
...
|
|
6768
|
-
...
|
|
6769
|
-
...
|
|
6770
|
-
...
|
|
6771
|
-
...
|
|
6680
|
+
...compact({ endedAt: row.ended_at ?? void 0 }),
|
|
6681
|
+
...compact({ durationMs: row.duration_ms ?? void 0 }),
|
|
6682
|
+
...compact({ output: row.output ?? void 0 }),
|
|
6683
|
+
...compact({ error }),
|
|
6684
|
+
...compact({ usage }),
|
|
6685
|
+
...compact({ metadata }),
|
|
6772
6686
|
observationCount: observations.length
|
|
6773
6687
|
};
|
|
6774
6688
|
}
|
|
@@ -6798,10 +6712,29 @@ function serializeJsonError2(error) {
|
|
|
6798
6712
|
}
|
|
6799
6713
|
return String(error);
|
|
6800
6714
|
}
|
|
6715
|
+
|
|
6716
|
+
// src/types.ts
|
|
6717
|
+
function traceSummary3(trace) {
|
|
6718
|
+
return compact({
|
|
6719
|
+
id: trace.id,
|
|
6720
|
+
sessionId: trace.sessionId,
|
|
6721
|
+
name: trace.name,
|
|
6722
|
+
status: trace.status,
|
|
6723
|
+
startedAt: trace.startedAt,
|
|
6724
|
+
endedAt: trace.endedAt,
|
|
6725
|
+
durationMs: trace.durationMs,
|
|
6726
|
+
output: trace.output,
|
|
6727
|
+
error: trace.error,
|
|
6728
|
+
usage: trace.usage,
|
|
6729
|
+
metadata: trace.metadata,
|
|
6730
|
+
observationCount: trace.observations.length
|
|
6731
|
+
});
|
|
6732
|
+
}
|
|
6801
6733
|
export {
|
|
6802
6734
|
Studio,
|
|
6803
6735
|
StudioTraceObserver,
|
|
6804
6736
|
createInMemoryStudioStore,
|
|
6805
|
-
createSqliteSessionStore
|
|
6737
|
+
createSqliteSessionStore,
|
|
6738
|
+
traceSummary3 as traceSummary
|
|
6806
6739
|
};
|
|
6807
6740
|
//# sourceMappingURL=index.js.map
|