@anvia/studio 0.6.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1956 -1974
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -2,6 +2,19 @@
|
|
|
2
2
|
import {
|
|
3
3
|
createHook as createHook3
|
|
4
4
|
} from "@anvia/core/agent";
|
|
5
|
+
|
|
6
|
+
// src/runtime/compact.ts
|
|
7
|
+
function compact(obj) {
|
|
8
|
+
const result = {};
|
|
9
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
10
|
+
if (value !== void 0) {
|
|
11
|
+
result[key] = value;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return result;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// src/runtime/studio.ts
|
|
5
18
|
import { Message } from "@anvia/core/completion";
|
|
6
19
|
import { Agent } from "@anvia/core/internal/agent";
|
|
7
20
|
import { Pipeline } from "@anvia/core/pipeline";
|
|
@@ -65,6 +78,20 @@ function serializeUnknown(error) {
|
|
|
65
78
|
}
|
|
66
79
|
return toJsonValue(error);
|
|
67
80
|
}
|
|
81
|
+
function formatJson(value) {
|
|
82
|
+
try {
|
|
83
|
+
return JSON.stringify(value, null, 2);
|
|
84
|
+
} catch {
|
|
85
|
+
return String(value);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function formatUnknown(value) {
|
|
89
|
+
try {
|
|
90
|
+
return JSON.stringify(value);
|
|
91
|
+
} catch {
|
|
92
|
+
return void 0;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
68
95
|
|
|
69
96
|
// src/traces/trace-observer.ts
|
|
70
97
|
var StudioTraceObserver = class {
|
|
@@ -191,7 +218,7 @@ var StudioRunTraceObserver = class {
|
|
|
191
218
|
const trace = {
|
|
192
219
|
id: this.props.id,
|
|
193
220
|
sessionId,
|
|
194
|
-
...
|
|
221
|
+
...compact({ name: this.props.args.trace?.name }),
|
|
195
222
|
status,
|
|
196
223
|
trace: this.trace,
|
|
197
224
|
startedAt: this.startedAt.toISOString(),
|
|
@@ -202,9 +229,9 @@ var StudioRunTraceObserver = class {
|
|
|
202
229
|
prompt: this.props.args.prompt,
|
|
203
230
|
history: this.props.args.history
|
|
204
231
|
}),
|
|
205
|
-
...
|
|
206
|
-
...
|
|
207
|
-
...
|
|
232
|
+
...compact({ output: result.output }),
|
|
233
|
+
...compact({ error: result.error }),
|
|
234
|
+
...compact({ usage: result.usage }),
|
|
208
235
|
metadata,
|
|
209
236
|
observations: this.observations,
|
|
210
237
|
observationCount: this.observations.length
|
|
@@ -234,7 +261,7 @@ var ChildAgentToolTraceAccumulator = class {
|
|
|
234
261
|
this.agentStarts.set(agentId, {
|
|
235
262
|
startedAt: /* @__PURE__ */ new Date(),
|
|
236
263
|
agentId,
|
|
237
|
-
...
|
|
264
|
+
...compact({ agentName })
|
|
238
265
|
});
|
|
239
266
|
}
|
|
240
267
|
if (child.type === "turn_start") {
|
|
@@ -245,7 +272,7 @@ var ChildAgentToolTraceAccumulator = class {
|
|
|
245
272
|
history: child.history
|
|
246
273
|
}),
|
|
247
274
|
agentId,
|
|
248
|
-
...
|
|
275
|
+
...compact({ agentName }),
|
|
249
276
|
childTurn
|
|
250
277
|
});
|
|
251
278
|
return;
|
|
@@ -261,7 +288,7 @@ var ChildAgentToolTraceAccumulator = class {
|
|
|
261
288
|
status: "success",
|
|
262
289
|
turn: this.parent.turn,
|
|
263
290
|
startedAt: start?.startedAt ?? /* @__PURE__ */ new Date(),
|
|
264
|
-
...
|
|
291
|
+
...compact({ input: start?.input }),
|
|
265
292
|
output: toJsonValue(child.response),
|
|
266
293
|
metadata: this.childMetadata(agentId, agentName, childTurn)
|
|
267
294
|
})
|
|
@@ -276,10 +303,10 @@ var ChildAgentToolTraceAccumulator = class {
|
|
|
276
303
|
this.toolStarts.push({
|
|
277
304
|
startedAt: /* @__PURE__ */ new Date(),
|
|
278
305
|
agentId,
|
|
279
|
-
...
|
|
306
|
+
...compact({ agentName }),
|
|
280
307
|
childTurn,
|
|
281
308
|
toolName,
|
|
282
|
-
...
|
|
309
|
+
...compact({ toolCallId: callId }),
|
|
283
310
|
input: toJsonValue(toolCallFunction?.arguments ?? {}),
|
|
284
311
|
completed: false
|
|
285
312
|
});
|
|
@@ -301,12 +328,12 @@ var ChildAgentToolTraceAccumulator = class {
|
|
|
301
328
|
status: "success",
|
|
302
329
|
turn: this.parent.turn,
|
|
303
330
|
startedAt: start?.startedAt ?? /* @__PURE__ */ new Date(),
|
|
304
|
-
...
|
|
331
|
+
...compact({ input }),
|
|
305
332
|
...typeof child.result === "string" ? { output: parseOrString(child.result) } : {},
|
|
306
333
|
metadata: {
|
|
307
334
|
...this.childMetadata(agentId, agentName, childTurn),
|
|
308
|
-
...
|
|
309
|
-
...
|
|
335
|
+
...compact({ toolCallId }),
|
|
336
|
+
...compact({ internalCallId })
|
|
310
337
|
}
|
|
311
338
|
})
|
|
312
339
|
);
|
|
@@ -404,10 +431,10 @@ function traceObservation(props) {
|
|
|
404
431
|
startedAt: props.startedAt.toISOString(),
|
|
405
432
|
endedAt: endedAt.toISOString(),
|
|
406
433
|
durationMs: durationMs(props.startedAt, endedAt),
|
|
407
|
-
...
|
|
408
|
-
...
|
|
409
|
-
...
|
|
410
|
-
...
|
|
434
|
+
...compact({ input: props.input }),
|
|
435
|
+
...compact({ output: props.output }),
|
|
436
|
+
...compact({ error: props.error }),
|
|
437
|
+
...compact({ metadata: props.metadata })
|
|
411
438
|
};
|
|
412
439
|
}
|
|
413
440
|
function traceMetadata(args, messages) {
|
|
@@ -824,427 +851,413 @@ import {
|
|
|
824
851
|
parseToolArgs
|
|
825
852
|
} from "@anvia/core/tool";
|
|
826
853
|
|
|
827
|
-
// src/runtime/
|
|
828
|
-
function
|
|
829
|
-
return
|
|
854
|
+
// src/runtime/type-guards.ts
|
|
855
|
+
function isObject(value) {
|
|
856
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
830
857
|
}
|
|
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
|
-
}
|
|
858
|
+
function isJsonObject(value) {
|
|
859
|
+
return isObject(value) && Object.values(value).every(isJsonValue);
|
|
860
|
+
}
|
|
861
|
+
function isJsonValue(value) {
|
|
862
|
+
if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
863
|
+
return true;
|
|
898
864
|
}
|
|
899
|
-
|
|
865
|
+
if (Array.isArray(value)) {
|
|
866
|
+
return value.every(isJsonValue);
|
|
867
|
+
}
|
|
868
|
+
return isJsonObject(value);
|
|
900
869
|
}
|
|
901
|
-
function
|
|
902
|
-
|
|
903
|
-
|
|
870
|
+
function isMessageInput(value) {
|
|
871
|
+
return typeof value === "string" || isMessage(value);
|
|
872
|
+
}
|
|
873
|
+
function isMessage(value) {
|
|
874
|
+
if (!isObject(value) || typeof value.role !== "string") {
|
|
875
|
+
return false;
|
|
904
876
|
}
|
|
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
|
-
});
|
|
877
|
+
if (value.role === "system") {
|
|
878
|
+
return typeof value.content === "string";
|
|
879
|
+
}
|
|
880
|
+
if (value.role === "user" || value.role === "assistant" || value.role === "tool") {
|
|
881
|
+
return Array.isArray(value.content);
|
|
882
|
+
}
|
|
883
|
+
return false;
|
|
926
884
|
}
|
|
927
|
-
function
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
last.text = `${last.text}${text}`;
|
|
931
|
-
return;
|
|
885
|
+
function isAgentTraceOptions(value) {
|
|
886
|
+
if (!isObject(value)) {
|
|
887
|
+
return false;
|
|
932
888
|
}
|
|
933
|
-
|
|
934
|
-
entryId: transcript.length,
|
|
935
|
-
kind: "message",
|
|
936
|
-
role: "assistant",
|
|
937
|
-
text
|
|
938
|
-
});
|
|
889
|
+
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
890
|
}
|
|
940
|
-
function
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
891
|
+
function isNonNegativeInteger(value) {
|
|
892
|
+
return Number.isInteger(value) && typeof value === "number" && value >= 0;
|
|
893
|
+
}
|
|
894
|
+
function isPositiveInteger(value) {
|
|
895
|
+
return Number.isInteger(value) && typeof value === "number" && value > 0;
|
|
896
|
+
}
|
|
897
|
+
function optionalString(value) {
|
|
898
|
+
return value === void 0 || typeof value === "string";
|
|
899
|
+
}
|
|
900
|
+
function optionalBoolean(value) {
|
|
901
|
+
return value === void 0 || typeof value === "boolean";
|
|
902
|
+
}
|
|
903
|
+
function optionalStringArray(value) {
|
|
904
|
+
return value === void 0 || Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
905
|
+
}
|
|
906
|
+
function optionalObject(value) {
|
|
907
|
+
return value === void 0 || isObject(value);
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
// src/runtime/http.ts
|
|
911
|
+
function errorResponse(c, status, code, message, details) {
|
|
912
|
+
const body = {
|
|
913
|
+
error: {
|
|
914
|
+
code,
|
|
915
|
+
message
|
|
916
|
+
}
|
|
917
|
+
};
|
|
918
|
+
if (details !== void 0) {
|
|
919
|
+
body.error.details = details;
|
|
945
920
|
}
|
|
921
|
+
return c.json(body, status);
|
|
922
|
+
}
|
|
923
|
+
function unsupportedCapability(c, capability) {
|
|
924
|
+
return errorResponse(
|
|
925
|
+
c,
|
|
926
|
+
501,
|
|
927
|
+
"unsupported_capability",
|
|
928
|
+
`Capability "${capability}" is not implemented by this runner`,
|
|
929
|
+
{ capability }
|
|
930
|
+
);
|
|
931
|
+
}
|
|
932
|
+
function serializeError(error) {
|
|
933
|
+
return serializeUnknown(error);
|
|
946
934
|
}
|
|
947
935
|
|
|
948
|
-
// src/
|
|
949
|
-
function
|
|
950
|
-
|
|
936
|
+
// src/runtime/query.ts
|
|
937
|
+
function optionalQueryString(value) {
|
|
938
|
+
const trimmed = value?.trim();
|
|
939
|
+
return trimmed === void 0 || trimmed.length === 0 ? void 0 : trimmed;
|
|
951
940
|
}
|
|
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);
|
|
941
|
+
function parseLimit(value, defaultMax = 50, max = 100) {
|
|
942
|
+
if (value === void 0 || value.trim().length === 0) {
|
|
943
|
+
return defaultMax;
|
|
960
944
|
}
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
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);
|
|
945
|
+
const limit = Number(value);
|
|
946
|
+
if (!Number.isInteger(limit) || limit <= 0) {
|
|
947
|
+
return void 0;
|
|
977
948
|
}
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
949
|
+
return Math.min(limit, max);
|
|
950
|
+
}
|
|
951
|
+
function parseTraceStatus(value) {
|
|
952
|
+
const status = optionalQueryString(value);
|
|
953
|
+
if (status === void 0) {
|
|
954
|
+
return void 0;
|
|
981
955
|
}
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
if (metadata === void 0) {
|
|
988
|
-
delete session.metadata;
|
|
989
|
-
} else {
|
|
990
|
-
session.metadata = metadata;
|
|
991
|
-
}
|
|
992
|
-
session.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
993
|
-
return materializeSession(session);
|
|
956
|
+
return status === "running" || status === "success" || status === "error" ? status : false;
|
|
957
|
+
}
|
|
958
|
+
function parseAfter(value) {
|
|
959
|
+
if (value === void 0 || value.trim().length === 0) {
|
|
960
|
+
return void 0;
|
|
994
961
|
}
|
|
995
|
-
|
|
996
|
-
|
|
962
|
+
const after = Number(value);
|
|
963
|
+
if (!Number.isInteger(after) || after < 0) {
|
|
964
|
+
return false;
|
|
997
965
|
}
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
966
|
+
return after;
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
// src/runtime/approvals.ts
|
|
970
|
+
function registerApprovalRoutes(app, approvals) {
|
|
971
|
+
app.get("/approvals", (c) => {
|
|
972
|
+
const status = parseApprovalStatus(c.req.query("status"));
|
|
973
|
+
if (status === false) {
|
|
974
|
+
return errorResponse(c, 400, "bad_request", "status must be pending or resolved");
|
|
1004
975
|
}
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
const
|
|
1009
|
-
if (
|
|
1010
|
-
|
|
1011
|
-
session.runs = [];
|
|
1012
|
-
session.messageCount = 0;
|
|
1013
|
-
session.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
976
|
+
const options = {};
|
|
977
|
+
const runId = optionalQueryString(c.req.query("runId"));
|
|
978
|
+
const agentId = optionalQueryString(c.req.query("agentId"));
|
|
979
|
+
const sessionId = optionalQueryString(c.req.query("sessionId"));
|
|
980
|
+
if (status !== void 0) {
|
|
981
|
+
options.status = status;
|
|
1014
982
|
}
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
async recordError(input) {
|
|
1018
|
-
await this.saveSessionRunTranscript({
|
|
1019
|
-
id: input.context.sessionId,
|
|
1020
|
-
runId: studioRunId(input.context) ?? input.runId,
|
|
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;
|
|
983
|
+
if (runId !== void 0) {
|
|
984
|
+
options.runId = runId;
|
|
1030
985
|
}
|
|
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;
|
|
986
|
+
if (agentId !== void 0) {
|
|
987
|
+
options.agentId = agentId;
|
|
1043
988
|
}
|
|
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;
|
|
989
|
+
if (sessionId !== void 0) {
|
|
990
|
+
options.sessionId = sessionId;
|
|
1065
991
|
}
|
|
1066
|
-
return
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
this.traces.delete(trace.id);
|
|
1075
|
-
}
|
|
992
|
+
return c.json({
|
|
993
|
+
approvals: approvals.list(options)
|
|
994
|
+
});
|
|
995
|
+
});
|
|
996
|
+
app.post("/approvals/:approvalId/decision", async (c) => {
|
|
997
|
+
const body = await parseApprovalDecisionRequest(c);
|
|
998
|
+
if ("error" in body) {
|
|
999
|
+
return body.error;
|
|
1076
1000
|
}
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
return this.traces.get(id);
|
|
1087
|
-
}
|
|
1088
|
-
saveTrace(trace) {
|
|
1089
|
-
this.traces.set(trace.id, trace);
|
|
1090
|
-
return trace;
|
|
1091
|
-
}
|
|
1092
|
-
appendPipelineLog(input) {
|
|
1093
|
-
const logs = this.pipelineLogs.get(input.pipelineId) ?? [];
|
|
1094
|
-
const entry = {
|
|
1095
|
-
id: globalThis.crypto.randomUUID(),
|
|
1096
|
-
pipelineId: input.pipelineId,
|
|
1097
|
-
...input.runId === void 0 ? {} : { runId: input.runId },
|
|
1098
|
-
sequence: logs.length,
|
|
1099
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
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;
|
|
1108
|
-
}
|
|
1109
|
-
listPipelineLogs(options) {
|
|
1110
|
-
return (this.pipelineLogs.get(options.pipelineId) ?? []).filter((log) => options.after === void 0 || log.sequence > options.after).slice(0, options.limit);
|
|
1111
|
-
}
|
|
1112
|
-
savePipelineRun(input) {
|
|
1113
|
-
const record = {
|
|
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;
|
|
1127
|
-
}
|
|
1128
|
-
getPipelineRun(options) {
|
|
1129
|
-
const run = this.pipelineRuns.get(options.runId);
|
|
1130
|
-
return run?.pipelineId === options.pipelineId ? run : void 0;
|
|
1131
|
-
}
|
|
1132
|
-
listPipelineRuns(options) {
|
|
1133
|
-
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);
|
|
1134
|
-
}
|
|
1135
|
-
};
|
|
1136
|
-
function sessionSummary(session) {
|
|
1137
|
-
return {
|
|
1138
|
-
id: session.id,
|
|
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
|
-
};
|
|
1146
|
-
}
|
|
1147
|
-
function materializeSession(session) {
|
|
1148
|
-
return {
|
|
1149
|
-
...sessionSummary(session),
|
|
1150
|
-
messages: [...session.messages],
|
|
1151
|
-
transcript: renumberTranscript(session.runs.flatMap((run) => run.transcript))
|
|
1152
|
-
};
|
|
1153
|
-
}
|
|
1154
|
-
function traceSummary(trace) {
|
|
1155
|
-
return {
|
|
1156
|
-
id: trace.id,
|
|
1157
|
-
sessionId: trace.sessionId,
|
|
1158
|
-
...trace.name === void 0 ? {} : { name: trace.name },
|
|
1159
|
-
status: trace.status,
|
|
1160
|
-
startedAt: trace.startedAt,
|
|
1161
|
-
...trace.endedAt === void 0 ? {} : { endedAt: trace.endedAt },
|
|
1162
|
-
...trace.durationMs === void 0 ? {} : { durationMs: trace.durationMs },
|
|
1163
|
-
...trace.output === void 0 ? {} : { output: trace.output },
|
|
1164
|
-
...trace.error === void 0 ? {} : { error: trace.error },
|
|
1165
|
-
...trace.usage === void 0 ? {} : { usage: trace.usage },
|
|
1166
|
-
...trace.metadata === void 0 ? {} : { metadata: trace.metadata },
|
|
1167
|
-
observationCount: trace.observations.length
|
|
1168
|
-
};
|
|
1169
|
-
}
|
|
1170
|
-
function traceAgentId(trace) {
|
|
1171
|
-
const nestedMetadata = trace.metadata?.metadata;
|
|
1172
|
-
return isJsonObject(nestedMetadata) && typeof nestedMetadata.agentId === "string" ? nestedMetadata.agentId : void 0;
|
|
1173
|
-
}
|
|
1174
|
-
function studioRunId(context) {
|
|
1175
|
-
const value = context.metadata?.studioRunId;
|
|
1176
|
-
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
1001
|
+
const result = approvals.decide(c.req.param("approvalId"), body);
|
|
1002
|
+
if (result === "missing") {
|
|
1003
|
+
return errorResponse(c, 404, "not_found", "Approval not found");
|
|
1004
|
+
}
|
|
1005
|
+
if (result === "resolved") {
|
|
1006
|
+
return errorResponse(c, 409, "conflict", "Approval is already resolved");
|
|
1007
|
+
}
|
|
1008
|
+
return c.json(result);
|
|
1009
|
+
});
|
|
1177
1010
|
}
|
|
1178
|
-
function
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
message: error.message
|
|
1183
|
-
};
|
|
1011
|
+
function parseApprovalStatus(value) {
|
|
1012
|
+
const status = optionalQueryString(value);
|
|
1013
|
+
if (status === void 0) {
|
|
1014
|
+
return void 0;
|
|
1184
1015
|
}
|
|
1185
|
-
return
|
|
1186
|
-
}
|
|
1187
|
-
function isJsonObject(value) {
|
|
1188
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1016
|
+
return status === "pending" || status === "resolved" ? status : false;
|
|
1189
1017
|
}
|
|
1190
|
-
function
|
|
1191
|
-
|
|
1192
|
-
|
|
1018
|
+
async function parseApprovalDecisionRequest(c) {
|
|
1019
|
+
let body;
|
|
1020
|
+
try {
|
|
1021
|
+
body = await c.req.json();
|
|
1022
|
+
} catch {
|
|
1023
|
+
return { error: errorResponse(c, 400, "bad_request", "Request body must be JSON") };
|
|
1193
1024
|
}
|
|
1194
|
-
if (
|
|
1195
|
-
return
|
|
1025
|
+
if (!isObject(body)) {
|
|
1026
|
+
return { error: errorResponse(c, 400, "bad_request", "Request body must be an object") };
|
|
1196
1027
|
}
|
|
1197
|
-
|
|
1198
|
-
}
|
|
1199
|
-
|
|
1200
|
-
// src/runtime/models.ts
|
|
1201
|
-
var STUDIO_MODEL_METADATA_KEY = "studioModel";
|
|
1202
|
-
function createStudioModelRegistry(config) {
|
|
1203
|
-
if (config === void 0) {
|
|
1204
|
-
return void 0;
|
|
1028
|
+
if (typeof body.approved !== "boolean") {
|
|
1029
|
+
return { error: errorResponse(c, 400, "bad_request", "approved must be a boolean") };
|
|
1205
1030
|
}
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
const id = normalizeProviderId(provider.id);
|
|
1209
|
-
if (providers.has(id)) {
|
|
1210
|
-
throw new Error(`Duplicate Studio model provider id: ${id}`);
|
|
1211
|
-
}
|
|
1212
|
-
const staticModels = /* @__PURE__ */ new Map();
|
|
1213
|
-
for (const model of provider.models ?? []) {
|
|
1214
|
-
const modelId = normalizeModelId(model.id);
|
|
1215
|
-
if (staticModels.has(modelId)) {
|
|
1216
|
-
throw new Error(`Duplicate Studio model id for provider ${id}: ${modelId}`);
|
|
1217
|
-
}
|
|
1218
|
-
staticModels.set(modelId, { ...model, id: modelId });
|
|
1219
|
-
}
|
|
1220
|
-
providers.set(id, {
|
|
1221
|
-
...provider,
|
|
1222
|
-
id,
|
|
1223
|
-
...provider.defaultModel === void 0 ? {} : { defaultModel: normalizeModelId(provider.defaultModel) },
|
|
1224
|
-
staticModels
|
|
1225
|
-
});
|
|
1031
|
+
if ("reason" in body && typeof body.reason !== "string") {
|
|
1032
|
+
return { error: errorResponse(c, 400, "bad_request", "reason must be a string") };
|
|
1226
1033
|
}
|
|
1227
|
-
return {
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
modelCache: /* @__PURE__ */ new Map()
|
|
1232
|
-
};
|
|
1034
|
+
return compact({
|
|
1035
|
+
approved: body.approved,
|
|
1036
|
+
reason: typeof body.reason === "string" && body.reason.trim().length > 0 ? body.reason.trim() : void 0
|
|
1037
|
+
});
|
|
1233
1038
|
}
|
|
1234
|
-
function
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1039
|
+
function createApprovalRuntime() {
|
|
1040
|
+
const approvals = /* @__PURE__ */ new Map();
|
|
1041
|
+
return {
|
|
1042
|
+
approvals,
|
|
1043
|
+
createHook(context) {
|
|
1044
|
+
const handleApprovalRequest = async ({ toolName, toolCallId, internalCallId, args, tool: control }, request) => {
|
|
1045
|
+
const decision = await requestApproval(approvals, context, compact({
|
|
1046
|
+
toolName,
|
|
1047
|
+
toolCallId,
|
|
1048
|
+
internalCallId,
|
|
1049
|
+
args,
|
|
1050
|
+
reason: request.reason,
|
|
1051
|
+
rejectMessage: request.rejectMessage
|
|
1052
|
+
}));
|
|
1053
|
+
return decision.approved ? control.run() : control.skip(decision.reason ?? request.rejectMessage ?? "Rejected in Anvia Studio.");
|
|
1054
|
+
};
|
|
1055
|
+
return {
|
|
1056
|
+
...createHook({
|
|
1057
|
+
async onToolCall({ toolName, toolCallId, internalCallId, args, tool: control }) {
|
|
1058
|
+
const registeredTool = context.getTool(toolName);
|
|
1059
|
+
if (registeredTool?.approval === void 0) {
|
|
1060
|
+
return control.run();
|
|
1061
|
+
}
|
|
1062
|
+
const approval = registeredTool.approval;
|
|
1063
|
+
const rawParsedArgs = parseToolArgs(args);
|
|
1064
|
+
const parsedArgs = registeredTool.parseApprovalArgs?.(rawParsedArgs) ?? rawParsedArgs;
|
|
1065
|
+
const approvalContext = compact({
|
|
1066
|
+
toolName,
|
|
1067
|
+
args: parsedArgs,
|
|
1068
|
+
rawArgs: args,
|
|
1069
|
+
toolCallId,
|
|
1070
|
+
internalCallId,
|
|
1071
|
+
run: compact({
|
|
1072
|
+
agentId: context.agentId,
|
|
1073
|
+
runId: context.runId,
|
|
1074
|
+
sessionId: context.sessionId,
|
|
1075
|
+
metadata: context.metadata
|
|
1076
|
+
})
|
|
1077
|
+
});
|
|
1078
|
+
const required = await approval.when(approvalContext);
|
|
1079
|
+
if (!required) {
|
|
1080
|
+
return control.run();
|
|
1081
|
+
}
|
|
1082
|
+
const reason = await resolveApprovalText(approval.reason, approvalContext);
|
|
1083
|
+
const rejectMessage = await resolveApprovalText(
|
|
1084
|
+
approval.rejectMessage,
|
|
1085
|
+
approvalContext
|
|
1086
|
+
);
|
|
1087
|
+
const decision = await requestApproval(approvals, context, compact({
|
|
1088
|
+
toolName,
|
|
1089
|
+
toolCallId,
|
|
1090
|
+
internalCallId,
|
|
1091
|
+
args,
|
|
1092
|
+
reason,
|
|
1093
|
+
rejectMessage
|
|
1094
|
+
}));
|
|
1095
|
+
return decision.approved ? control.run() : control.skip(decision.reason ?? rejectMessage ?? "Rejected in Anvia Studio.");
|
|
1096
|
+
}
|
|
1097
|
+
}),
|
|
1098
|
+
handleApprovalRequest
|
|
1099
|
+
};
|
|
1100
|
+
},
|
|
1101
|
+
list(options) {
|
|
1102
|
+
return [...approvals.values()].filter((approval) => {
|
|
1103
|
+
if (options.status === "pending" && approval.status !== "pending") {
|
|
1104
|
+
return false;
|
|
1105
|
+
}
|
|
1106
|
+
if (options.status === "resolved" && approval.status === "pending") {
|
|
1107
|
+
return false;
|
|
1108
|
+
}
|
|
1109
|
+
if (options.runId !== void 0 && approval.runId !== options.runId) {
|
|
1110
|
+
return false;
|
|
1111
|
+
}
|
|
1112
|
+
if (options.agentId !== void 0 && approval.agentId !== options.agentId) {
|
|
1113
|
+
return false;
|
|
1114
|
+
}
|
|
1115
|
+
if (options.sessionId !== void 0 && approval.sessionId !== options.sessionId) {
|
|
1116
|
+
return false;
|
|
1117
|
+
}
|
|
1118
|
+
return true;
|
|
1119
|
+
}).map(publicApproval);
|
|
1120
|
+
},
|
|
1121
|
+
decide(id, decision) {
|
|
1122
|
+
const approval = approvals.get(id);
|
|
1123
|
+
if (approval === void 0) {
|
|
1124
|
+
return "missing";
|
|
1125
|
+
}
|
|
1126
|
+
if (!isPendingApproval(approval)) {
|
|
1127
|
+
return "resolved";
|
|
1128
|
+
}
|
|
1129
|
+
const reason = decision.approved ? decision.reason : decision.reason ?? approval.rejectMessage ?? "Rejected in Anvia Studio.";
|
|
1130
|
+
const resolved = resolveApproval(approval, decision.approved ? "approved" : "rejected", compact({ reason }));
|
|
1131
|
+
approvals.set(id, resolved);
|
|
1132
|
+
approval.emit?.({ type: "tool_approval_result", approval: resolved });
|
|
1133
|
+
approval.resolve(compact({
|
|
1134
|
+
approved: decision.approved,
|
|
1135
|
+
reason
|
|
1136
|
+
}));
|
|
1137
|
+
return publicApproval(resolved);
|
|
1138
|
+
}
|
|
1139
|
+
};
|
|
1140
|
+
}
|
|
1141
|
+
async function requestApproval(approvals, context, request) {
|
|
1142
|
+
const id = globalThis.crypto.randomUUID();
|
|
1143
|
+
const approval = {
|
|
1144
|
+
...compact({
|
|
1145
|
+
id,
|
|
1146
|
+
runId: context.runId,
|
|
1147
|
+
agentId: context.agentId,
|
|
1148
|
+
sessionId: context.sessionId,
|
|
1149
|
+
toolName: request.toolName,
|
|
1150
|
+
callId: request.toolCallId,
|
|
1151
|
+
internalCallId: request.internalCallId,
|
|
1152
|
+
args: request.args,
|
|
1153
|
+
status: "pending",
|
|
1154
|
+
requestedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1155
|
+
reason: request.reason,
|
|
1156
|
+
rejectMessage: request.rejectMessage,
|
|
1157
|
+
emit: context.emit
|
|
1158
|
+
}),
|
|
1159
|
+
resolve: () => {
|
|
1160
|
+
}
|
|
1161
|
+
};
|
|
1162
|
+
const decision = new Promise((resolve2) => {
|
|
1163
|
+
approval.resolve = (decision2) => {
|
|
1164
|
+
const current = approvals.get(id);
|
|
1165
|
+
if (!isPendingApproval(current)) {
|
|
1166
|
+
if (current !== void 0) {
|
|
1167
|
+
resolve2(compact({
|
|
1168
|
+
approved: current.status === "approved",
|
|
1169
|
+
reason: current.reason
|
|
1170
|
+
}));
|
|
1171
|
+
}
|
|
1172
|
+
return;
|
|
1173
|
+
}
|
|
1174
|
+
const reason = decision2.approved ? decision2.reason : decision2.reason ?? request.rejectMessage ?? "Rejected in Anvia Studio.";
|
|
1175
|
+
const resolved = resolveApproval(current, decision2.approved ? "approved" : "rejected", compact({ reason }));
|
|
1176
|
+
approvals.set(id, resolved);
|
|
1177
|
+
context.emit?.({ type: "tool_approval_result", approval: resolved });
|
|
1178
|
+
resolve2(compact({
|
|
1179
|
+
approved: decision2.approved,
|
|
1180
|
+
reason
|
|
1181
|
+
}));
|
|
1182
|
+
};
|
|
1183
|
+
});
|
|
1184
|
+
approvals.set(id, approval);
|
|
1185
|
+
context.emit?.({ type: "tool_approval_request", approval: publicApproval(approval) });
|
|
1186
|
+
return decision;
|
|
1187
|
+
}
|
|
1188
|
+
async function resolveApprovalText(value, context) {
|
|
1189
|
+
return typeof value === "function" ? value(context) : value;
|
|
1190
|
+
}
|
|
1191
|
+
function isPendingApproval(approval) {
|
|
1192
|
+
return approval !== void 0 && approval.status === "pending" && "resolve" in approval;
|
|
1193
|
+
}
|
|
1194
|
+
function resolveApproval(approval, status, options = {}) {
|
|
1195
|
+
return publicApproval({
|
|
1196
|
+
...approval,
|
|
1197
|
+
...compact({
|
|
1198
|
+
status,
|
|
1199
|
+
resolvedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1200
|
+
reason: options.reason
|
|
1201
|
+
})
|
|
1202
|
+
});
|
|
1203
|
+
}
|
|
1204
|
+
function publicApproval(approval) {
|
|
1205
|
+
const { emit, rejectMessage, resolve: resolve2, ...rest } = approval;
|
|
1206
|
+
void emit;
|
|
1207
|
+
void rejectMessage;
|
|
1208
|
+
void resolve2;
|
|
1209
|
+
return rest;
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1212
|
+
// src/runtime/evals.ts
|
|
1213
|
+
import { runEvalSuite } from "@anvia/core/evals";
|
|
1214
|
+
|
|
1215
|
+
// src/runtime/models.ts
|
|
1216
|
+
var STUDIO_MODEL_METADATA_KEY = "studioModel";
|
|
1217
|
+
function createStudioModelRegistry(config) {
|
|
1218
|
+
if (config === void 0) {
|
|
1219
|
+
return void 0;
|
|
1220
|
+
}
|
|
1221
|
+
const providers = /* @__PURE__ */ new Map();
|
|
1222
|
+
for (const provider of config.providers) {
|
|
1223
|
+
const id = normalizeProviderId(provider.id);
|
|
1224
|
+
if (providers.has(id)) {
|
|
1225
|
+
throw new Error(`Duplicate Studio model provider id: ${id}`);
|
|
1226
|
+
}
|
|
1227
|
+
const staticModels = /* @__PURE__ */ new Map();
|
|
1228
|
+
for (const model of provider.models ?? []) {
|
|
1229
|
+
const modelId = normalizeModelId(model.id);
|
|
1230
|
+
if (staticModels.has(modelId)) {
|
|
1231
|
+
throw new Error(`Duplicate Studio model id for provider ${id}: ${modelId}`);
|
|
1232
|
+
}
|
|
1233
|
+
staticModels.set(modelId, { ...model, id: modelId });
|
|
1234
|
+
}
|
|
1235
|
+
providers.set(id, {
|
|
1236
|
+
...provider,
|
|
1237
|
+
id,
|
|
1238
|
+
...compact({ defaultModel: provider.defaultModel !== void 0 ? normalizeModelId(provider.defaultModel) : void 0 }),
|
|
1239
|
+
staticModels
|
|
1240
|
+
});
|
|
1241
|
+
}
|
|
1242
|
+
return {
|
|
1243
|
+
...compact({ defaultModel: config.default !== void 0 ? normalizeModelRef(config.default) : void 0 }),
|
|
1244
|
+
providers,
|
|
1245
|
+
agentPolicies: normalizeAgentPolicies(config.agents ?? {}),
|
|
1246
|
+
modelCache: /* @__PURE__ */ new Map()
|
|
1247
|
+
};
|
|
1248
|
+
}
|
|
1249
|
+
function studioModelsConfig(registry, agents) {
|
|
1250
|
+
if (registry === void 0) {
|
|
1251
|
+
return void 0;
|
|
1252
|
+
}
|
|
1253
|
+
const providers = [...registry.providers.values()].map((provider) => {
|
|
1254
|
+
const models = [...provider.staticModels.values()].map(
|
|
1240
1255
|
(model) => modelSummary(provider, model.id, model)
|
|
1241
1256
|
);
|
|
1242
1257
|
return {
|
|
1243
1258
|
id: provider.id,
|
|
1244
|
-
...provider.name
|
|
1245
|
-
|
|
1246
|
-
models,
|
|
1247
|
-
...provider.metadata === void 0 ? {} : { metadata: provider.metadata }
|
|
1259
|
+
...compact({ name: provider.name, defaultModel: provider.defaultModel, metadata: provider.metadata }),
|
|
1260
|
+
models
|
|
1248
1261
|
};
|
|
1249
1262
|
});
|
|
1250
1263
|
const agentIds = new Set(agents.map((agent) => agent.id));
|
|
@@ -1253,7 +1266,7 @@ function studioModelsConfig(registry, agents) {
|
|
|
1253
1266
|
);
|
|
1254
1267
|
return {
|
|
1255
1268
|
providers,
|
|
1256
|
-
...
|
|
1269
|
+
...compact({ default: registry.defaultModel }),
|
|
1257
1270
|
agents: agentsConfig
|
|
1258
1271
|
};
|
|
1259
1272
|
}
|
|
@@ -1267,7 +1280,7 @@ function registerModelRoutes(app, props) {
|
|
|
1267
1280
|
);
|
|
1268
1281
|
return c.json({
|
|
1269
1282
|
providers,
|
|
1270
|
-
...
|
|
1283
|
+
...compact({ defaultModel: props.registry.defaultModel })
|
|
1271
1284
|
});
|
|
1272
1285
|
});
|
|
1273
1286
|
app.get("/models/:providerId", async (c) => {
|
|
@@ -1380,9 +1393,9 @@ async function agentModelsCatalog(registry, agent) {
|
|
|
1380
1393
|
const defaultModel = policy?.default ?? registry.defaultModel;
|
|
1381
1394
|
return {
|
|
1382
1395
|
agentId: agent.id,
|
|
1383
|
-
...
|
|
1396
|
+
...compact({ defaultModel }),
|
|
1384
1397
|
models: [...models, ...exactPolicyModels],
|
|
1385
|
-
...warnings.length === 0 ?
|
|
1398
|
+
...compact({ warnings: warnings.length === 0 ? void 0 : warnings })
|
|
1386
1399
|
};
|
|
1387
1400
|
}
|
|
1388
1401
|
async function providerCatalog(provider) {
|
|
@@ -1400,14 +1413,15 @@ async function providerCatalog(provider) {
|
|
|
1400
1413
|
model.id,
|
|
1401
1414
|
modelSummary(provider, model.id, {
|
|
1402
1415
|
id: model.id,
|
|
1403
|
-
...
|
|
1404
|
-
...model.description === void 0 ? {} : { description: model.description },
|
|
1416
|
+
...compact({ name: model.name, description: model.description }),
|
|
1405
1417
|
...staticModel ?? {},
|
|
1406
1418
|
metadata: {
|
|
1407
|
-
...
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1419
|
+
...compact({
|
|
1420
|
+
type: model.type,
|
|
1421
|
+
createdAt: model.createdAt,
|
|
1422
|
+
ownedBy: model.ownedBy,
|
|
1423
|
+
contextLength: model.contextLength
|
|
1424
|
+
}),
|
|
1411
1425
|
...staticModel?.metadata ?? {}
|
|
1412
1426
|
}
|
|
1413
1427
|
})
|
|
@@ -1420,11 +1434,8 @@ async function providerCatalog(provider) {
|
|
|
1420
1434
|
}
|
|
1421
1435
|
return {
|
|
1422
1436
|
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 }
|
|
1437
|
+
...compact({ name: provider.name, defaultModel: provider.defaultModel, metadata: provider.metadata, warning }),
|
|
1438
|
+
models: [...models.values()].sort((left, right) => left.ref.localeCompare(right.ref))
|
|
1428
1439
|
};
|
|
1429
1440
|
}
|
|
1430
1441
|
function modelSummary(provider, modelId, model) {
|
|
@@ -1433,7 +1444,7 @@ function modelSummary(provider, modelId, model) {
|
|
|
1433
1444
|
id: modelId,
|
|
1434
1445
|
ref: `${provider.id}:${modelId}`,
|
|
1435
1446
|
providerId: provider.id,
|
|
1436
|
-
...
|
|
1447
|
+
...compact({ providerName: provider.name })
|
|
1437
1448
|
};
|
|
1438
1449
|
}
|
|
1439
1450
|
function ensureModelAllowed(registry, agentId, ref) {
|
|
@@ -1456,21 +1467,18 @@ function normalizeAgentPolicies(policies) {
|
|
|
1456
1467
|
Object.entries(policies).map(([agentId, policy]) => [
|
|
1457
1468
|
agentId.trim(),
|
|
1458
1469
|
{
|
|
1459
|
-
...
|
|
1460
|
-
|
|
1461
|
-
allowed: policy.allowed
|
|
1470
|
+
...compact({
|
|
1471
|
+
default: policy.default !== void 0 ? normalizeModelRef(policy.default) : void 0,
|
|
1472
|
+
allowed: policy.allowed?.map(
|
|
1462
1473
|
(entry) => typeof entry === "string" && entry.trim().endsWith(":*") ? `${normalizeProviderId(entry.trim().slice(0, -2))}:*` : normalizeModelRef(entry)
|
|
1463
1474
|
)
|
|
1464
|
-
}
|
|
1475
|
+
})
|
|
1465
1476
|
}
|
|
1466
1477
|
])
|
|
1467
1478
|
);
|
|
1468
1479
|
}
|
|
1469
1480
|
function publicPolicy(policy) {
|
|
1470
|
-
return {
|
|
1471
|
-
...policy.default === void 0 ? {} : { default: policy.default },
|
|
1472
|
-
...policy.allowed === void 0 ? {} : { allowed: policy.allowed }
|
|
1473
|
-
};
|
|
1481
|
+
return compact({ default: policy.default, allowed: policy.allowed });
|
|
1474
1482
|
}
|
|
1475
1483
|
function modelWarnings(ref, model, request) {
|
|
1476
1484
|
const warnings = [];
|
|
@@ -1572,126 +1580,69 @@ function agentHasMcpTools(agent) {
|
|
|
1572
1580
|
return agentToolItems(agent).some(({ tool }) => mcpServerName(tool) !== void 0);
|
|
1573
1581
|
}
|
|
1574
1582
|
|
|
1575
|
-
// src/runtime/
|
|
1576
|
-
function
|
|
1577
|
-
|
|
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();
|
|
1583
|
+
// src/runtime/config.ts
|
|
1584
|
+
function runnerId(options) {
|
|
1585
|
+
return options.id ?? "anvia-studio";
|
|
1591
1586
|
}
|
|
1592
|
-
function
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1587
|
+
function agentConfig(agent) {
|
|
1588
|
+
const name = agent.name ?? agent.agent.name;
|
|
1589
|
+
const description = agent.description ?? agent.agent.description;
|
|
1590
|
+
return compact({
|
|
1591
|
+
id: agent.id,
|
|
1592
|
+
name,
|
|
1593
|
+
description,
|
|
1594
|
+
quickPrompts: agent.quickPrompts ?? [],
|
|
1595
|
+
metadata: agent.metadata
|
|
1596
|
+
});
|
|
1600
1597
|
}
|
|
1601
|
-
function
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1598
|
+
function agentRuntimeSummary(agent) {
|
|
1599
|
+
const tools = agentToolItems(agent);
|
|
1600
|
+
const name = agent.name ?? agent.agent.name;
|
|
1601
|
+
const description = agent.description ?? agent.agent.description;
|
|
1602
|
+
return compact({
|
|
1603
|
+
id: agent.id,
|
|
1604
|
+
name,
|
|
1605
|
+
description,
|
|
1606
|
+
model: toJsonValue2(agent.agent.model),
|
|
1607
|
+
toolCount: tools.length,
|
|
1608
|
+
staticToolCount: tools.filter((item) => item.source === "static").length,
|
|
1609
|
+
dynamicToolCount: tools.filter((item) => item.source === "dynamic").length,
|
|
1610
|
+
approvalToolCount: tools.filter((item) => item.tool.approval !== void 0).length,
|
|
1611
|
+
mcpToolCount: tools.filter((item) => mcpServerName(item.tool) !== void 0).length,
|
|
1612
|
+
staticContextCount: agent.agent.staticContext.length,
|
|
1613
|
+
dynamicContextCount: agent.agent.dynamicContexts.length,
|
|
1614
|
+
observerCount: agent.agent.observers.length,
|
|
1615
|
+
hasMemory: agent.agent.memory !== void 0,
|
|
1616
|
+
hasHook: agent.agent.hook !== void 0,
|
|
1617
|
+
hasOutputSchema: agent.agent.outputSchema !== void 0,
|
|
1618
|
+
defaultMaxTurns: agent.agent.defaultMaxTurns,
|
|
1619
|
+
metadata: agent.metadata
|
|
1620
|
+
});
|
|
1612
1621
|
}
|
|
1613
|
-
function
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
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
|
-
});
|
|
1622
|
+
function pipelineConfig(pipeline) {
|
|
1623
|
+
const graph = pipeline.pipeline.graph();
|
|
1624
|
+
const stageNodes = graph.nodes.filter((node) => node.kind !== "input" && node.kind !== "output");
|
|
1625
|
+
return compact({
|
|
1626
|
+
id: pipeline.id,
|
|
1627
|
+
name: pipeline.name,
|
|
1628
|
+
description: pipeline.description,
|
|
1629
|
+
metadata: pipeline.metadata,
|
|
1630
|
+
stageCount: stageNodes.length,
|
|
1631
|
+
edgeCount: graph.edges.length,
|
|
1632
|
+
hasParallelStages: graph.nodes.some((node) => node.kind === "parallel"),
|
|
1633
|
+
agentCount: graph.nodes.filter((node) => node.kind === "agent").length,
|
|
1634
|
+
extractorCount: graph.nodes.filter((node) => node.kind === "extractor").length
|
|
1635
|
+
});
|
|
1685
1636
|
}
|
|
1686
1637
|
function buildConfig(options, agents, pipelines, stores) {
|
|
1687
1638
|
const models = options.models === void 0 ? void 0 : studioModelsConfig(createStudioModelRegistry(options.models), agents);
|
|
1688
|
-
return {
|
|
1639
|
+
return compact({
|
|
1689
1640
|
id: runnerId(options),
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1641
|
+
name: options.name,
|
|
1642
|
+
description: options.description,
|
|
1643
|
+
version: options.version,
|
|
1693
1644
|
agents: agents.map(agentConfig),
|
|
1694
|
-
|
|
1645
|
+
models,
|
|
1695
1646
|
pipelines: pipelines.map(pipelineConfig),
|
|
1696
1647
|
evals: options.evals.map(evalConfig),
|
|
1697
1648
|
chat: {
|
|
@@ -1699,60 +1650,7 @@ function buildConfig(options, agents, pipelines, stores) {
|
|
|
1699
1650
|
},
|
|
1700
1651
|
capabilities: capabilityConfig(options, agents, pipelines, stores),
|
|
1701
1652
|
unsupportedCapabilities: unsupportedCapabilities(stores)
|
|
1702
|
-
};
|
|
1703
|
-
}
|
|
1704
|
-
function runnerId(options) {
|
|
1705
|
-
return options.id ?? "anvia-studio";
|
|
1706
|
-
}
|
|
1707
|
-
function agentConfig(agent) {
|
|
1708
|
-
const name = agent.name ?? agent.agent.name;
|
|
1709
|
-
const description = agent.description ?? agent.agent.description;
|
|
1710
|
-
return {
|
|
1711
|
-
id: agent.id,
|
|
1712
|
-
...name === void 0 ? {} : { name },
|
|
1713
|
-
...description === void 0 ? {} : { description },
|
|
1714
|
-
quickPrompts: agent.quickPrompts ?? [],
|
|
1715
|
-
...agent.metadata === void 0 ? {} : { metadata: agent.metadata }
|
|
1716
|
-
};
|
|
1717
|
-
}
|
|
1718
|
-
function agentRuntimeSummary(agent) {
|
|
1719
|
-
const tools = agentToolItems(agent);
|
|
1720
|
-
const name = agent.name ?? agent.agent.name;
|
|
1721
|
-
const description = agent.description ?? agent.agent.description;
|
|
1722
|
-
return {
|
|
1723
|
-
id: agent.id,
|
|
1724
|
-
...name === void 0 ? {} : { name },
|
|
1725
|
-
...description === void 0 ? {} : { description },
|
|
1726
|
-
model: toJsonValue(agent.agent.model),
|
|
1727
|
-
toolCount: tools.length,
|
|
1728
|
-
staticToolCount: tools.filter((item) => item.source === "static").length,
|
|
1729
|
-
dynamicToolCount: tools.filter((item) => item.source === "dynamic").length,
|
|
1730
|
-
approvalToolCount: tools.filter((item) => item.tool.approval !== void 0).length,
|
|
1731
|
-
mcpToolCount: tools.filter((item) => mcpServerName(item.tool) !== void 0).length,
|
|
1732
|
-
staticContextCount: agent.agent.staticContext.length,
|
|
1733
|
-
dynamicContextCount: agent.agent.dynamicContexts.length,
|
|
1734
|
-
observerCount: agent.agent.observers.length,
|
|
1735
|
-
hasMemory: agent.agent.memory !== void 0,
|
|
1736
|
-
hasHook: agent.agent.hook !== void 0,
|
|
1737
|
-
hasOutputSchema: agent.agent.outputSchema !== void 0,
|
|
1738
|
-
...agent.agent.defaultMaxTurns === void 0 ? {} : { defaultMaxTurns: agent.agent.defaultMaxTurns },
|
|
1739
|
-
...agent.metadata === void 0 ? {} : { metadata: agent.metadata }
|
|
1740
|
-
};
|
|
1741
|
-
}
|
|
1742
|
-
function pipelineConfig(pipeline) {
|
|
1743
|
-
const graph = pipeline.pipeline.graph();
|
|
1744
|
-
const stageNodes = graph.nodes.filter((node) => node.kind !== "input" && node.kind !== "output");
|
|
1745
|
-
return {
|
|
1746
|
-
id: pipeline.id,
|
|
1747
|
-
...pipeline.name === void 0 ? {} : { name: pipeline.name },
|
|
1748
|
-
...pipeline.description === void 0 ? {} : { description: pipeline.description },
|
|
1749
|
-
...pipeline.metadata === void 0 ? {} : { metadata: pipeline.metadata },
|
|
1750
|
-
stageCount: stageNodes.length,
|
|
1751
|
-
edgeCount: graph.edges.length,
|
|
1752
|
-
hasParallelStages: graph.nodes.some((node) => node.kind === "parallel"),
|
|
1753
|
-
agentCount: graph.nodes.filter((node) => node.kind === "agent").length,
|
|
1754
|
-
extractorCount: graph.nodes.filter((node) => node.kind === "extractor").length
|
|
1755
|
-
};
|
|
1653
|
+
});
|
|
1756
1654
|
}
|
|
1757
1655
|
function capabilityConfig(_options, agents, pipelines, stores) {
|
|
1758
1656
|
const capabilities = {
|
|
@@ -1794,848 +1692,508 @@ function capabilityConfig(_options, agents, pipelines, stores) {
|
|
|
1794
1692
|
return capabilities;
|
|
1795
1693
|
}
|
|
1796
1694
|
function evalConfig(suite) {
|
|
1797
|
-
return {
|
|
1695
|
+
return compact({
|
|
1798
1696
|
id: suite.id ?? suite.name,
|
|
1799
1697
|
name: suite.name,
|
|
1800
|
-
|
|
1698
|
+
description: suite.description,
|
|
1801
1699
|
caseCount: suite.cases.length,
|
|
1802
1700
|
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);
|
|
1701
|
+
concurrency: suite.concurrency,
|
|
1702
|
+
metadata: suite.metadata
|
|
1703
|
+
});
|
|
1830
1704
|
}
|
|
1831
|
-
function
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
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;
|
|
1705
|
+
function unsupportedCapabilities(stores) {
|
|
1706
|
+
return [
|
|
1707
|
+
...stores.sessions === void 0 ? ["sessions"] : [],
|
|
1708
|
+
...stores.traces === void 0 ? ["traces"] : []
|
|
1709
|
+
];
|
|
1842
1710
|
}
|
|
1843
|
-
function
|
|
1844
|
-
return
|
|
1711
|
+
function toJsonValue2(value) {
|
|
1712
|
+
return serializeUnknown(value);
|
|
1845
1713
|
}
|
|
1846
|
-
|
|
1847
|
-
|
|
1714
|
+
|
|
1715
|
+
// src/runtime/evals.ts
|
|
1716
|
+
function registerEvalRoutes(app, props) {
|
|
1717
|
+
app.get(
|
|
1718
|
+
"/evals",
|
|
1719
|
+
(c) => c.json({
|
|
1720
|
+
evals: props.evals.map(evalConfig)
|
|
1721
|
+
})
|
|
1722
|
+
);
|
|
1723
|
+
app.get("/evals/:evalId", (c) => {
|
|
1724
|
+
const suite = props.evalMap.get(c.req.param("evalId"));
|
|
1725
|
+
if (suite === void 0) {
|
|
1726
|
+
return errorResponse(c, 404, "not_found", "Eval suite not found");
|
|
1727
|
+
}
|
|
1728
|
+
return c.json(evalConfig(suite));
|
|
1729
|
+
});
|
|
1730
|
+
app.post("/evals/:evalId/runs", async (c) => {
|
|
1731
|
+
const suite = props.evalMap.get(c.req.param("evalId"));
|
|
1732
|
+
if (suite === void 0) {
|
|
1733
|
+
return errorResponse(c, 404, "not_found", "Eval suite not found");
|
|
1734
|
+
}
|
|
1735
|
+
const body = await parseEvalRunRequest(c);
|
|
1736
|
+
if ("error" in body) {
|
|
1737
|
+
return body.error;
|
|
1738
|
+
}
|
|
1739
|
+
const runId = globalThis.crypto.randomUUID();
|
|
1740
|
+
const startedAt = Date.now();
|
|
1741
|
+
const result = await runEvalSuite({
|
|
1742
|
+
...suite,
|
|
1743
|
+
...compact({ concurrency: body.concurrency })
|
|
1744
|
+
});
|
|
1745
|
+
const endedAt = Date.now();
|
|
1746
|
+
const jsonResult = toJsonValue(result);
|
|
1747
|
+
const response = {
|
|
1748
|
+
runId,
|
|
1749
|
+
suiteId: suite.id ?? suite.name,
|
|
1750
|
+
startedAt: new Date(startedAt).toISOString(),
|
|
1751
|
+
endedAt: new Date(endedAt).toISOString(),
|
|
1752
|
+
durationMs: endedAt - startedAt,
|
|
1753
|
+
result: isJsonObject(jsonResult) ? jsonResult : { value: jsonResult }
|
|
1754
|
+
};
|
|
1755
|
+
return c.json(response);
|
|
1756
|
+
});
|
|
1848
1757
|
}
|
|
1849
|
-
function
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1758
|
+
async function parseEvalRunRequest(c) {
|
|
1759
|
+
let body = {};
|
|
1760
|
+
try {
|
|
1761
|
+
body = await c.req.json();
|
|
1762
|
+
} catch {
|
|
1763
|
+
body = {};
|
|
1855
1764
|
}
|
|
1856
|
-
|
|
1857
|
-
}
|
|
1858
|
-
function isAgentTraceOptions(value) {
|
|
1859
|
-
if (!isObject(value)) {
|
|
1860
|
-
return false;
|
|
1765
|
+
if (!isObject(body)) {
|
|
1766
|
+
return { error: errorResponse(c, 400, "bad_request", "Request body must be an object") };
|
|
1861
1767
|
}
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
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
|
|
1768
|
+
const request = {};
|
|
1769
|
+
if ("concurrency" in body) {
|
|
1770
|
+
if (!isPositiveInteger(body.concurrency)) {
|
|
1771
|
+
return {
|
|
1772
|
+
error: errorResponse(c, 400, "bad_request", "concurrency must be a positive integer")
|
|
1773
|
+
};
|
|
1896
1774
|
}
|
|
1897
|
-
|
|
1898
|
-
if (details !== void 0) {
|
|
1899
|
-
body.error.details = details;
|
|
1775
|
+
request.concurrency = body.concurrency;
|
|
1900
1776
|
}
|
|
1901
|
-
return
|
|
1902
|
-
}
|
|
1903
|
-
function serializeError(error) {
|
|
1904
|
-
return serializeUnknown(error);
|
|
1777
|
+
return request;
|
|
1905
1778
|
}
|
|
1906
1779
|
|
|
1907
|
-
// src/runtime/
|
|
1908
|
-
function
|
|
1909
|
-
app.get("/
|
|
1910
|
-
const
|
|
1911
|
-
if (
|
|
1912
|
-
return errorResponse(c, 400, "bad_request", "
|
|
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;
|
|
1780
|
+
// src/runtime/knowledge.ts
|
|
1781
|
+
function registerKnowledgeRoutes(app, props) {
|
|
1782
|
+
app.get("/knowledge", async (c) => {
|
|
1783
|
+
const limit = parseLimit(c.req.query("limit"));
|
|
1784
|
+
if (limit === void 0) {
|
|
1785
|
+
return errorResponse(c, 400, "bad_request", "Invalid limit");
|
|
1920
1786
|
}
|
|
1921
|
-
|
|
1922
|
-
|
|
1787
|
+
const summary = {
|
|
1788
|
+
agents: await Promise.all(props.agents.map(agentKnowledgeConfig)),
|
|
1789
|
+
evidence: await recentKnowledgeEvidence(props.traceStore, limit)
|
|
1790
|
+
};
|
|
1791
|
+
return c.json(summary);
|
|
1792
|
+
});
|
|
1793
|
+
app.get("/knowledge/items", async (c) => {
|
|
1794
|
+
const limit = parseLimit(c.req.query("limit"));
|
|
1795
|
+
if (limit === void 0) {
|
|
1796
|
+
return errorResponse(c, 400, "bad_request", "Invalid limit");
|
|
1923
1797
|
}
|
|
1924
|
-
|
|
1925
|
-
|
|
1798
|
+
const agentId = optionalQueryString(c.req.query("agentId"));
|
|
1799
|
+
const sourceId = optionalQueryString(c.req.query("sourceId"));
|
|
1800
|
+
if (agentId === void 0 || sourceId === void 0) {
|
|
1801
|
+
return errorResponse(c, 400, "bad_request", "agentId and sourceId are required");
|
|
1926
1802
|
}
|
|
1927
|
-
|
|
1928
|
-
|
|
1803
|
+
const agent = props.agents.find((item) => item.id === agentId);
|
|
1804
|
+
if (agent === void 0) {
|
|
1805
|
+
return errorResponse(c, 404, "not_found", "Agent not found");
|
|
1929
1806
|
}
|
|
1930
|
-
|
|
1931
|
-
|
|
1807
|
+
const page = await knowledgeItemsPage(agent, sourceId, {
|
|
1808
|
+
limit,
|
|
1809
|
+
cursor: optionalQueryString(c.req.query("cursor"))
|
|
1932
1810
|
});
|
|
1933
|
-
|
|
1934
|
-
|
|
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");
|
|
1811
|
+
if (page === void 0) {
|
|
1812
|
+
return errorResponse(c, 404, "not_found", "Knowledge source not found");
|
|
1945
1813
|
}
|
|
1946
|
-
return c.json(
|
|
1814
|
+
return c.json(page);
|
|
1947
1815
|
});
|
|
1948
1816
|
}
|
|
1949
|
-
function
|
|
1950
|
-
const
|
|
1951
|
-
|
|
1817
|
+
async function agentKnowledgeConfig(agent) {
|
|
1818
|
+
const agentName = agent.name ?? agent.agent.name;
|
|
1819
|
+
return {
|
|
1820
|
+
agentId: agent.id,
|
|
1821
|
+
...compact({ agentName }),
|
|
1822
|
+
sources: await knowledgeSources(agent),
|
|
1823
|
+
staticContext: agent.agent.staticContext.map((document) => ({
|
|
1824
|
+
id: document.id,
|
|
1825
|
+
text: document.text,
|
|
1826
|
+
...compact({ additionalProps: document.additionalProps !== void 0 ? jsonObjectFromRecord(document.additionalProps) : void 0 })
|
|
1827
|
+
}))
|
|
1828
|
+
};
|
|
1829
|
+
}
|
|
1830
|
+
async function knowledgeSources(agent) {
|
|
1831
|
+
const sources = [
|
|
1832
|
+
{
|
|
1833
|
+
sourceId: staticSourceId(),
|
|
1834
|
+
kind: "static_context",
|
|
1835
|
+
label: "Static context",
|
|
1836
|
+
count: agent.agent.staticContext.length,
|
|
1837
|
+
inspectable: true,
|
|
1838
|
+
itemCount: agent.agent.staticContext.length
|
|
1839
|
+
}
|
|
1840
|
+
];
|
|
1841
|
+
const dynamicContextSources = await Promise.all(
|
|
1842
|
+
agent.agent.dynamicContexts.map(async (registration, index) => {
|
|
1843
|
+
const inspect = inspectFn(registration.index);
|
|
1844
|
+
const count = await inspectableCount(inspect, registration.options.filter);
|
|
1845
|
+
return {
|
|
1846
|
+
sourceId: dynamicContextSourceId(index),
|
|
1847
|
+
kind: "dynamic_context",
|
|
1848
|
+
label: `Dynamic context ${index + 1}`,
|
|
1849
|
+
count: 1,
|
|
1850
|
+
registrationIndex: index,
|
|
1851
|
+
topK: registration.options.topK,
|
|
1852
|
+
...compact({ threshold: registration.options.threshold }),
|
|
1853
|
+
inspectable: inspect !== void 0,
|
|
1854
|
+
...compact({ itemCount: count })
|
|
1855
|
+
};
|
|
1856
|
+
})
|
|
1857
|
+
);
|
|
1858
|
+
const dynamicToolSources = await Promise.all(
|
|
1859
|
+
agent.agent.dynamicTools.map(async (registration, index) => {
|
|
1860
|
+
const inspect = inspectFn(registration.index);
|
|
1861
|
+
const count = await inspectableCount(inspect, registration.options.filter);
|
|
1862
|
+
return {
|
|
1863
|
+
sourceId: dynamicToolsSourceId(index),
|
|
1864
|
+
kind: "dynamic_tools",
|
|
1865
|
+
label: `Dynamic tools ${index + 1}`,
|
|
1866
|
+
count: 1,
|
|
1867
|
+
registrationIndex: index,
|
|
1868
|
+
topK: registration.options.topK,
|
|
1869
|
+
...compact({ threshold: registration.options.threshold }),
|
|
1870
|
+
inspectable: inspect !== void 0,
|
|
1871
|
+
...compact({ itemCount: count })
|
|
1872
|
+
};
|
|
1873
|
+
})
|
|
1874
|
+
);
|
|
1875
|
+
return [...sources, ...dynamicContextSources, ...dynamicToolSources];
|
|
1876
|
+
}
|
|
1877
|
+
async function inspectableCount(inspect, filter) {
|
|
1878
|
+
if (inspect === void 0) {
|
|
1952
1879
|
return void 0;
|
|
1953
1880
|
}
|
|
1954
|
-
|
|
1881
|
+
const page = await inspect({ limit: 1, filter });
|
|
1882
|
+
return page.totalCount;
|
|
1955
1883
|
}
|
|
1956
|
-
async function
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
body = await c.req.json();
|
|
1960
|
-
} catch {
|
|
1961
|
-
return { error: errorResponse(c, 400, "bad_request", "Request body must be JSON") };
|
|
1884
|
+
async function knowledgeItemsPage(agent, sourceId, request) {
|
|
1885
|
+
if (sourceId === staticSourceId()) {
|
|
1886
|
+
return staticKnowledgeItemsPage(agent, request);
|
|
1962
1887
|
}
|
|
1963
|
-
|
|
1964
|
-
|
|
1888
|
+
const dynamicContextIndex = dynamicSourceIndex(sourceId, "dynamic_context");
|
|
1889
|
+
if (dynamicContextIndex !== void 0) {
|
|
1890
|
+
const registration = agent.agent.dynamicContexts[dynamicContextIndex];
|
|
1891
|
+
if (registration === void 0) {
|
|
1892
|
+
return void 0;
|
|
1893
|
+
}
|
|
1894
|
+
const inspect = inspectFn(registration.index);
|
|
1895
|
+
if (inspect === void 0) {
|
|
1896
|
+
return nonInspectablePage(agent.id, sourceId, "dynamic_context");
|
|
1897
|
+
}
|
|
1898
|
+
const page = await inspect({
|
|
1899
|
+
limit: request.limit,
|
|
1900
|
+
cursor: request.cursor,
|
|
1901
|
+
filter: registration.options.filter
|
|
1902
|
+
});
|
|
1903
|
+
return {
|
|
1904
|
+
agentId: agent.id,
|
|
1905
|
+
sourceId,
|
|
1906
|
+
kind: "dynamic_context",
|
|
1907
|
+
inspectable: true,
|
|
1908
|
+
items: page.items.map((item) => dynamicContextItem(item)),
|
|
1909
|
+
...compact({ nextCursor: page.nextCursor, totalCount: page.totalCount })
|
|
1910
|
+
};
|
|
1965
1911
|
}
|
|
1966
|
-
|
|
1967
|
-
|
|
1912
|
+
const dynamicToolsIndex = dynamicSourceIndex(sourceId, "dynamic_tools");
|
|
1913
|
+
if (dynamicToolsIndex !== void 0) {
|
|
1914
|
+
const registration = agent.agent.dynamicTools[dynamicToolsIndex];
|
|
1915
|
+
if (registration === void 0) {
|
|
1916
|
+
return void 0;
|
|
1917
|
+
}
|
|
1918
|
+
const inspect = inspectFn(registration.index);
|
|
1919
|
+
if (inspect === void 0) {
|
|
1920
|
+
return nonInspectablePage(agent.id, sourceId, "dynamic_tools");
|
|
1921
|
+
}
|
|
1922
|
+
const page = await inspect({
|
|
1923
|
+
limit: request.limit,
|
|
1924
|
+
cursor: request.cursor,
|
|
1925
|
+
filter: registration.options.filter
|
|
1926
|
+
});
|
|
1927
|
+
return {
|
|
1928
|
+
agentId: agent.id,
|
|
1929
|
+
sourceId,
|
|
1930
|
+
kind: "dynamic_tools",
|
|
1931
|
+
inspectable: true,
|
|
1932
|
+
items: page.items.map((item) => dynamicToolItem(item)),
|
|
1933
|
+
...compact({ nextCursor: page.nextCursor, totalCount: page.totalCount })
|
|
1934
|
+
};
|
|
1968
1935
|
}
|
|
1969
|
-
|
|
1970
|
-
|
|
1936
|
+
return void 0;
|
|
1937
|
+
}
|
|
1938
|
+
function inspectFn(index) {
|
|
1939
|
+
if (!isRecord2(index) || typeof index.inspect !== "function") {
|
|
1940
|
+
return void 0;
|
|
1971
1941
|
}
|
|
1942
|
+
const inspect = index.inspect;
|
|
1943
|
+
return (request) => inspect.call(index, request);
|
|
1944
|
+
}
|
|
1945
|
+
function staticKnowledgeItemsPage(agent, request) {
|
|
1946
|
+
const start = Math.max(0, Math.trunc(Number(request.cursor ?? "0")));
|
|
1947
|
+
const page = agent.agent.staticContext.slice(start, start + request.limit);
|
|
1948
|
+
const nextOffset = start + page.length;
|
|
1972
1949
|
return {
|
|
1973
|
-
|
|
1974
|
-
|
|
1950
|
+
agentId: agent.id,
|
|
1951
|
+
sourceId: staticSourceId(),
|
|
1952
|
+
kind: "static_context",
|
|
1953
|
+
inspectable: true,
|
|
1954
|
+
items: page.map((document) => ({
|
|
1955
|
+
id: document.id,
|
|
1956
|
+
kind: "static_context",
|
|
1957
|
+
text: document.text,
|
|
1958
|
+
...compact({ metadata: document.additionalProps !== void 0 ? jsonObjectFromRecord(document.additionalProps) : void 0 })
|
|
1959
|
+
})),
|
|
1960
|
+
...compact({ nextCursor: nextOffset < agent.agent.staticContext.length ? String(nextOffset) : void 0 }),
|
|
1961
|
+
totalCount: agent.agent.staticContext.length
|
|
1975
1962
|
};
|
|
1976
1963
|
}
|
|
1977
|
-
function
|
|
1978
|
-
const approvals = /* @__PURE__ */ new Map();
|
|
1964
|
+
function nonInspectablePage(agentId, sourceId, kind) {
|
|
1979
1965
|
return {
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
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
|
-
}
|
|
1966
|
+
agentId,
|
|
1967
|
+
sourceId,
|
|
1968
|
+
kind,
|
|
1969
|
+
inspectable: false,
|
|
1970
|
+
items: [],
|
|
1971
|
+
message: "This source can be searched at runtime, but it does not expose browseable chunks."
|
|
2079
1972
|
};
|
|
2080
1973
|
}
|
|
2081
|
-
|
|
2082
|
-
const
|
|
2083
|
-
|
|
2084
|
-
id,
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
...
|
|
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
|
-
}
|
|
1974
|
+
function dynamicContextItem(item) {
|
|
1975
|
+
const text = isRecord2(item.document) && typeof item.document.text === "string" ? item.document.text : typeof item.document === "string" ? item.document : void 0;
|
|
1976
|
+
return {
|
|
1977
|
+
id: item.id,
|
|
1978
|
+
kind: "dynamic_context",
|
|
1979
|
+
...text === void 0 ? { document: toJsonValue(item.document) } : { text },
|
|
1980
|
+
...compact({ metadata: item.metadata !== void 0 ? jsonObjectFromRecord(item.metadata) : void 0 })
|
|
2099
1981
|
};
|
|
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
1982
|
}
|
|
2128
|
-
|
|
2129
|
-
|
|
1983
|
+
function dynamicToolItem(item) {
|
|
1984
|
+
const document = isRecord2(item.document) ? item.document : {};
|
|
1985
|
+
const definition = isRecord2(document.definition) ? document.definition : {};
|
|
1986
|
+
const toolName = typeof document.toolName === "string" ? document.toolName : typeof definition.name === "string" ? definition.name : item.id;
|
|
1987
|
+
const description = typeof definition.description === "string" ? definition.description : "";
|
|
1988
|
+
return {
|
|
1989
|
+
id: item.id,
|
|
1990
|
+
kind: "dynamic_tool",
|
|
1991
|
+
toolName,
|
|
1992
|
+
description,
|
|
1993
|
+
parameterKeys: parameterKeys(definition.parameters),
|
|
1994
|
+
document: toJsonValue(item.document),
|
|
1995
|
+
...compact({ metadata: item.metadata !== void 0 ? jsonObjectFromRecord(item.metadata) : void 0 })
|
|
1996
|
+
};
|
|
2130
1997
|
}
|
|
2131
|
-
function
|
|
2132
|
-
|
|
1998
|
+
function parameterKeys(parameters) {
|
|
1999
|
+
if (!isRecord2(parameters) || !isRecord2(parameters.properties)) {
|
|
2000
|
+
return [];
|
|
2001
|
+
}
|
|
2002
|
+
return Object.keys(parameters.properties);
|
|
2133
2003
|
}
|
|
2134
|
-
function
|
|
2135
|
-
return
|
|
2136
|
-
...approval,
|
|
2137
|
-
status,
|
|
2138
|
-
resolvedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2139
|
-
...options.reason === void 0 ? {} : { reason: options.reason }
|
|
2140
|
-
});
|
|
2004
|
+
function staticSourceId() {
|
|
2005
|
+
return "static-context";
|
|
2141
2006
|
}
|
|
2142
|
-
function
|
|
2143
|
-
|
|
2144
|
-
void emit;
|
|
2145
|
-
void rejectMessage;
|
|
2146
|
-
void resolve2;
|
|
2147
|
-
return rest;
|
|
2007
|
+
function dynamicContextSourceId(index) {
|
|
2008
|
+
return `dynamic-context-${index}`;
|
|
2148
2009
|
}
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
function
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2010
|
+
function dynamicToolsSourceId(index) {
|
|
2011
|
+
return `dynamic-tools-${index}`;
|
|
2012
|
+
}
|
|
2013
|
+
function dynamicSourceIndex(sourceId, kind) {
|
|
2014
|
+
const prefix = kind === "dynamic_context" ? "dynamic-context-" : "dynamic-tools-";
|
|
2015
|
+
if (!sourceId.startsWith(prefix)) {
|
|
2016
|
+
return void 0;
|
|
2017
|
+
}
|
|
2018
|
+
const index = Number(sourceId.slice(prefix.length));
|
|
2019
|
+
return Number.isInteger(index) && index >= 0 ? index : void 0;
|
|
2020
|
+
}
|
|
2021
|
+
async function recentKnowledgeEvidence(traceStore, limit) {
|
|
2022
|
+
if (traceStore?.listTraces === void 0) {
|
|
2023
|
+
return [];
|
|
2024
|
+
}
|
|
2025
|
+
const store = traceStore;
|
|
2026
|
+
const listTraces = store.listTraces;
|
|
2027
|
+
if (listTraces === void 0) {
|
|
2028
|
+
return [];
|
|
2029
|
+
}
|
|
2030
|
+
const summaries = await listTraces.call(store, { limit });
|
|
2031
|
+
const traces = await Promise.all(
|
|
2032
|
+
summaries.map((summary) => Promise.resolve(store.getTrace(summary.id)).catch(() => void 0))
|
|
2158
2033
|
);
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
const suite = props.evalMap.get(c.req.param("evalId"));
|
|
2168
|
-
if (suite === void 0) {
|
|
2169
|
-
return errorResponse(c, 404, "not_found", "Eval suite not found");
|
|
2034
|
+
return traces.flatMap(
|
|
2035
|
+
(trace) => trace === void 0 ? [] : evidenceFromTrace(trace)
|
|
2036
|
+
);
|
|
2037
|
+
}
|
|
2038
|
+
function evidenceFromTrace(trace) {
|
|
2039
|
+
return trace.observations.flatMap((observation) => {
|
|
2040
|
+
if (observation.kind !== "generation" || !isRecord2(observation.input)) {
|
|
2041
|
+
return [];
|
|
2170
2042
|
}
|
|
2171
|
-
const
|
|
2172
|
-
|
|
2173
|
-
|
|
2043
|
+
const documents = Array.isArray(observation.input.documents) ? observation.input.documents.flatMap((document) => evidenceDocument(document)) : [];
|
|
2044
|
+
const tools = Array.isArray(observation.input.tools) ? observation.input.tools.flatMap((tool) => evidenceToolName(tool)) : [];
|
|
2045
|
+
if (documents.length === 0 && tools.length === 0) {
|
|
2046
|
+
return [];
|
|
2174
2047
|
}
|
|
2175
|
-
const
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
return c.json(response);
|
|
2048
|
+
const query = queryFromGenerationInput(observation.input);
|
|
2049
|
+
return [
|
|
2050
|
+
{
|
|
2051
|
+
traceId: trace.id,
|
|
2052
|
+
sessionId: trace.sessionId,
|
|
2053
|
+
observationId: observation.id,
|
|
2054
|
+
observationName: observation.name,
|
|
2055
|
+
turn: observation.turn,
|
|
2056
|
+
startedAt: observation.startedAt,
|
|
2057
|
+
...compact({ query }),
|
|
2058
|
+
documentCount: documents.length,
|
|
2059
|
+
toolCount: tools.length,
|
|
2060
|
+
documents,
|
|
2061
|
+
tools
|
|
2062
|
+
}
|
|
2063
|
+
];
|
|
2192
2064
|
});
|
|
2193
2065
|
}
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
} catch {
|
|
2199
|
-
body = {};
|
|
2066
|
+
function queryFromGenerationInput(value) {
|
|
2067
|
+
const promptText = messageText(value.prompt);
|
|
2068
|
+
if (promptText.length > 0) {
|
|
2069
|
+
return promptText;
|
|
2200
2070
|
}
|
|
2201
|
-
if (
|
|
2202
|
-
|
|
2071
|
+
if (Array.isArray(value.chatHistory)) {
|
|
2072
|
+
for (let index = value.chatHistory.length - 1; index >= 0; index -= 1) {
|
|
2073
|
+
const text = messageText(value.chatHistory[index]);
|
|
2074
|
+
if (text.length > 0) {
|
|
2075
|
+
return text;
|
|
2076
|
+
}
|
|
2077
|
+
}
|
|
2203
2078
|
}
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
}
|
|
2079
|
+
if (Array.isArray(value.history)) {
|
|
2080
|
+
for (let index = value.history.length - 1; index >= 0; index -= 1) {
|
|
2081
|
+
const text = messageText(value.history[index]);
|
|
2082
|
+
if (text.length > 0) {
|
|
2083
|
+
return text;
|
|
2084
|
+
}
|
|
2210
2085
|
}
|
|
2211
|
-
request.concurrency = body.concurrency;
|
|
2212
2086
|
}
|
|
2213
|
-
return
|
|
2087
|
+
return void 0;
|
|
2214
2088
|
}
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
return errorResponse(c, 400, "bad_request", "Invalid limit");
|
|
2233
|
-
}
|
|
2234
|
-
const agentId = optionalQueryString(c.req.query("agentId"));
|
|
2235
|
-
const sourceId = optionalQueryString(c.req.query("sourceId"));
|
|
2236
|
-
if (agentId === void 0 || sourceId === void 0) {
|
|
2237
|
-
return errorResponse(c, 400, "bad_request", "agentId and sourceId are required");
|
|
2238
|
-
}
|
|
2239
|
-
const agent = props.agents.find((item) => item.id === agentId);
|
|
2240
|
-
if (agent === void 0) {
|
|
2241
|
-
return errorResponse(c, 404, "not_found", "Agent not found");
|
|
2242
|
-
}
|
|
2243
|
-
const page = await knowledgeItemsPage(agent, sourceId, {
|
|
2244
|
-
limit,
|
|
2245
|
-
cursor: optionalQueryString(c.req.query("cursor"))
|
|
2246
|
-
});
|
|
2247
|
-
if (page === void 0) {
|
|
2248
|
-
return errorResponse(c, 404, "not_found", "Knowledge source not found");
|
|
2249
|
-
}
|
|
2250
|
-
return c.json(page);
|
|
2251
|
-
});
|
|
2089
|
+
function messageText(value) {
|
|
2090
|
+
if (typeof value === "string") {
|
|
2091
|
+
return value.trim();
|
|
2092
|
+
}
|
|
2093
|
+
if (!isRecord2(value)) {
|
|
2094
|
+
return "";
|
|
2095
|
+
}
|
|
2096
|
+
if (typeof value.text === "string") {
|
|
2097
|
+
return value.text.trim();
|
|
2098
|
+
}
|
|
2099
|
+
if (typeof value.content === "string") {
|
|
2100
|
+
return value.content.trim();
|
|
2101
|
+
}
|
|
2102
|
+
if (Array.isArray(value.content)) {
|
|
2103
|
+
return value.content.map(contentText).filter(Boolean).join("\n").trim();
|
|
2104
|
+
}
|
|
2105
|
+
return "";
|
|
2252
2106
|
}
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
};
|
|
2107
|
+
function contentText(value) {
|
|
2108
|
+
if (typeof value === "string") {
|
|
2109
|
+
return value.trim();
|
|
2110
|
+
}
|
|
2111
|
+
if (!isRecord2(value)) {
|
|
2112
|
+
return "";
|
|
2113
|
+
}
|
|
2114
|
+
if (typeof value.text === "string") {
|
|
2115
|
+
return value.text.trim();
|
|
2116
|
+
}
|
|
2117
|
+
return "";
|
|
2265
2118
|
}
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2119
|
+
function evidenceDocument(value) {
|
|
2120
|
+
if (!isRecord2(value)) {
|
|
2121
|
+
return [];
|
|
2122
|
+
}
|
|
2123
|
+
const id = typeof value.id === "string" ? value.id : void 0;
|
|
2124
|
+
const text = typeof value.text === "string" ? value.text : void 0;
|
|
2125
|
+
const additionalProps = isRecord2(value.additionalProps) ? jsonObjectFromRecord(value.additionalProps) : void 0;
|
|
2126
|
+
if (id === void 0 && text === void 0 && additionalProps === void 0) {
|
|
2127
|
+
return [];
|
|
2128
|
+
}
|
|
2129
|
+
return [
|
|
2130
|
+
compact({ id, text, additionalProps })
|
|
2276
2131
|
];
|
|
2277
|
-
const dynamicContextSources = await Promise.all(
|
|
2278
|
-
agent.agent.dynamicContexts.map(async (registration, index) => {
|
|
2279
|
-
const inspect = inspectFn(registration.index);
|
|
2280
|
-
const count = await inspectableCount(inspect, registration.options.filter);
|
|
2281
|
-
return {
|
|
2282
|
-
sourceId: dynamicContextSourceId(index),
|
|
2283
|
-
kind: "dynamic_context",
|
|
2284
|
-
label: `Dynamic context ${index + 1}`,
|
|
2285
|
-
count: 1,
|
|
2286
|
-
registrationIndex: index,
|
|
2287
|
-
topK: registration.options.topK,
|
|
2288
|
-
...registration.options.threshold === void 0 ? {} : { threshold: registration.options.threshold },
|
|
2289
|
-
inspectable: inspect !== void 0,
|
|
2290
|
-
...count === void 0 ? {} : { itemCount: count }
|
|
2291
|
-
};
|
|
2292
|
-
})
|
|
2293
|
-
);
|
|
2294
|
-
const dynamicToolSources = await Promise.all(
|
|
2295
|
-
agent.agent.dynamicTools.map(async (registration, index) => {
|
|
2296
|
-
const inspect = inspectFn(registration.index);
|
|
2297
|
-
const count = await inspectableCount(inspect, registration.options.filter);
|
|
2298
|
-
return {
|
|
2299
|
-
sourceId: dynamicToolsSourceId(index),
|
|
2300
|
-
kind: "dynamic_tools",
|
|
2301
|
-
label: `Dynamic tools ${index + 1}`,
|
|
2302
|
-
count: 1,
|
|
2303
|
-
registrationIndex: index,
|
|
2304
|
-
topK: registration.options.topK,
|
|
2305
|
-
...registration.options.threshold === void 0 ? {} : { threshold: registration.options.threshold },
|
|
2306
|
-
inspectable: inspect !== void 0,
|
|
2307
|
-
...count === void 0 ? {} : { itemCount: count }
|
|
2308
|
-
};
|
|
2309
|
-
})
|
|
2310
|
-
);
|
|
2311
|
-
return [...sources, ...dynamicContextSources, ...dynamicToolSources];
|
|
2312
2132
|
}
|
|
2313
|
-
|
|
2314
|
-
if (
|
|
2315
|
-
return
|
|
2133
|
+
function evidenceToolName(value) {
|
|
2134
|
+
if (!isRecord2(value) || typeof value.name !== "string") {
|
|
2135
|
+
return [];
|
|
2316
2136
|
}
|
|
2317
|
-
|
|
2318
|
-
return page.totalCount;
|
|
2137
|
+
return [value.name];
|
|
2319
2138
|
}
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
const
|
|
2331
|
-
|
|
2332
|
-
|
|
2139
|
+
function jsonObjectFromRecord(value) {
|
|
2140
|
+
return compactJsonObject(value);
|
|
2141
|
+
}
|
|
2142
|
+
function isRecord2(value) {
|
|
2143
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2144
|
+
}
|
|
2145
|
+
|
|
2146
|
+
// src/runtime/mcps.ts
|
|
2147
|
+
function registerMcpRoutes(app, props) {
|
|
2148
|
+
app.get("/agents/:agentId/mcps", async (c) => {
|
|
2149
|
+
const agentId = c.req.param("agentId");
|
|
2150
|
+
const agent = props.agentMap.get(agentId);
|
|
2151
|
+
if (agent === void 0) {
|
|
2152
|
+
return errorResponse(c, 404, "not_found", "Agent not found");
|
|
2333
2153
|
}
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
filter: registration.options.filter
|
|
2154
|
+
return c.json({
|
|
2155
|
+
agentId,
|
|
2156
|
+
servers: await agentMcpMetadata(agent)
|
|
2338
2157
|
});
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
}
|
|
2349
|
-
const dynamicToolsIndex = dynamicSourceIndex(sourceId, "dynamic_tools");
|
|
2350
|
-
if (dynamicToolsIndex !== void 0) {
|
|
2351
|
-
const registration = agent.agent.dynamicTools[dynamicToolsIndex];
|
|
2352
|
-
if (registration === void 0) {
|
|
2353
|
-
return void 0;
|
|
2158
|
+
});
|
|
2159
|
+
}
|
|
2160
|
+
async function agentMcpMetadata(agent) {
|
|
2161
|
+
const servers = /* @__PURE__ */ new Map();
|
|
2162
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2163
|
+
for (const { tool, source } of agentToolItems(agent)) {
|
|
2164
|
+
const serverName = mcpServerName(tool);
|
|
2165
|
+
if (serverName === void 0) {
|
|
2166
|
+
continue;
|
|
2354
2167
|
}
|
|
2355
|
-
const
|
|
2356
|
-
|
|
2357
|
-
|
|
2168
|
+
const definition = await tool.definition("");
|
|
2169
|
+
const key = `${serverName}:${source}:${definition.name}`;
|
|
2170
|
+
if (seen.has(key)) {
|
|
2171
|
+
continue;
|
|
2358
2172
|
}
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2173
|
+
seen.add(key);
|
|
2174
|
+
const tools = servers.get(serverName) ?? [];
|
|
2175
|
+
tools.push({
|
|
2176
|
+
name: definition.name,
|
|
2177
|
+
description: definition.description,
|
|
2178
|
+
parameters: definition.parameters,
|
|
2179
|
+
source
|
|
2180
|
+
});
|
|
2181
|
+
servers.set(serverName, tools);
|
|
2182
|
+
}
|
|
2183
|
+
return [...servers.entries()].map(([name, tools]) => {
|
|
2184
|
+
const sortedTools = tools.sort((left, right) => {
|
|
2185
|
+
if (left.source !== right.source) {
|
|
2186
|
+
return left.source === "static" ? -1 : 1;
|
|
2187
|
+
}
|
|
2188
|
+
return left.name.localeCompare(right.name);
|
|
2363
2189
|
});
|
|
2364
2190
|
return {
|
|
2365
2191
|
agentId: agent.id,
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
items: page.items.map((item) => dynamicToolItem(item)),
|
|
2370
|
-
...page.nextCursor === void 0 ? {} : { nextCursor: page.nextCursor },
|
|
2371
|
-
...page.totalCount === void 0 ? {} : { totalCount: page.totalCount }
|
|
2192
|
+
name,
|
|
2193
|
+
toolCount: sortedTools.length,
|
|
2194
|
+
tools: sortedTools
|
|
2372
2195
|
};
|
|
2373
|
-
}
|
|
2374
|
-
return void 0;
|
|
2375
|
-
}
|
|
2376
|
-
function inspectFn(index) {
|
|
2377
|
-
if (!isRecord2(index) || typeof index.inspect !== "function") {
|
|
2378
|
-
return void 0;
|
|
2379
|
-
}
|
|
2380
|
-
const inspect = index.inspect;
|
|
2381
|
-
return (request) => inspect.call(index, request);
|
|
2382
|
-
}
|
|
2383
|
-
function staticKnowledgeItemsPage(agent, request) {
|
|
2384
|
-
const start = Math.max(0, Math.trunc(Number(request.cursor ?? "0")));
|
|
2385
|
-
const page = agent.agent.staticContext.slice(start, start + request.limit);
|
|
2386
|
-
const nextOffset = start + page.length;
|
|
2387
|
-
return {
|
|
2388
|
-
agentId: agent.id,
|
|
2389
|
-
sourceId: staticSourceId(),
|
|
2390
|
-
kind: "static_context",
|
|
2391
|
-
inspectable: true,
|
|
2392
|
-
items: page.map((document) => ({
|
|
2393
|
-
id: document.id,
|
|
2394
|
-
kind: "static_context",
|
|
2395
|
-
text: document.text,
|
|
2396
|
-
...document.additionalProps === void 0 ? {} : { metadata: jsonObjectFromRecord(document.additionalProps) }
|
|
2397
|
-
})),
|
|
2398
|
-
...nextOffset < agent.agent.staticContext.length ? { nextCursor: String(nextOffset) } : {},
|
|
2399
|
-
totalCount: agent.agent.staticContext.length
|
|
2400
|
-
};
|
|
2401
|
-
}
|
|
2402
|
-
function nonInspectablePage(agentId, sourceId, kind) {
|
|
2403
|
-
return {
|
|
2404
|
-
agentId,
|
|
2405
|
-
sourceId,
|
|
2406
|
-
kind,
|
|
2407
|
-
inspectable: false,
|
|
2408
|
-
items: [],
|
|
2409
|
-
message: "This source can be searched at runtime, but it does not expose browseable chunks."
|
|
2410
|
-
};
|
|
2411
|
-
}
|
|
2412
|
-
function dynamicContextItem(item) {
|
|
2413
|
-
const text = isRecord2(item.document) && typeof item.document.text === "string" ? item.document.text : typeof item.document === "string" ? item.document : void 0;
|
|
2414
|
-
return {
|
|
2415
|
-
id: item.id,
|
|
2416
|
-
kind: "dynamic_context",
|
|
2417
|
-
...text === void 0 ? { document: toJsonValue(item.document) } : { text },
|
|
2418
|
-
...item.metadata === void 0 ? {} : { metadata: jsonObjectFromRecord(item.metadata) }
|
|
2419
|
-
};
|
|
2420
|
-
}
|
|
2421
|
-
function dynamicToolItem(item) {
|
|
2422
|
-
const document = isRecord2(item.document) ? item.document : {};
|
|
2423
|
-
const definition = isRecord2(document.definition) ? document.definition : {};
|
|
2424
|
-
const toolName = typeof document.toolName === "string" ? document.toolName : typeof definition.name === "string" ? definition.name : item.id;
|
|
2425
|
-
const description = typeof definition.description === "string" ? definition.description : "";
|
|
2426
|
-
return {
|
|
2427
|
-
id: item.id,
|
|
2428
|
-
kind: "dynamic_tool",
|
|
2429
|
-
toolName,
|
|
2430
|
-
description,
|
|
2431
|
-
parameterKeys: parameterKeys(definition.parameters),
|
|
2432
|
-
document: toJsonValue(item.document),
|
|
2433
|
-
...item.metadata === void 0 ? {} : { metadata: jsonObjectFromRecord(item.metadata) }
|
|
2434
|
-
};
|
|
2435
|
-
}
|
|
2436
|
-
function parameterKeys(parameters) {
|
|
2437
|
-
if (!isRecord2(parameters) || !isRecord2(parameters.properties)) {
|
|
2438
|
-
return [];
|
|
2439
|
-
}
|
|
2440
|
-
return Object.keys(parameters.properties);
|
|
2441
|
-
}
|
|
2442
|
-
function staticSourceId() {
|
|
2443
|
-
return "static-context";
|
|
2444
|
-
}
|
|
2445
|
-
function dynamicContextSourceId(index) {
|
|
2446
|
-
return `dynamic-context-${index}`;
|
|
2447
|
-
}
|
|
2448
|
-
function dynamicToolsSourceId(index) {
|
|
2449
|
-
return `dynamic-tools-${index}`;
|
|
2450
|
-
}
|
|
2451
|
-
function dynamicSourceIndex(sourceId, kind) {
|
|
2452
|
-
const prefix = kind === "dynamic_context" ? "dynamic-context-" : "dynamic-tools-";
|
|
2453
|
-
if (!sourceId.startsWith(prefix)) {
|
|
2454
|
-
return void 0;
|
|
2455
|
-
}
|
|
2456
|
-
const index = Number(sourceId.slice(prefix.length));
|
|
2457
|
-
return Number.isInteger(index) && index >= 0 ? index : void 0;
|
|
2458
|
-
}
|
|
2459
|
-
async function recentKnowledgeEvidence(traceStore, limit) {
|
|
2460
|
-
if (traceStore?.listTraces === void 0) {
|
|
2461
|
-
return [];
|
|
2462
|
-
}
|
|
2463
|
-
const store = traceStore;
|
|
2464
|
-
const listTraces = store.listTraces;
|
|
2465
|
-
if (listTraces === void 0) {
|
|
2466
|
-
return [];
|
|
2467
|
-
}
|
|
2468
|
-
const summaries = await listTraces.call(store, { limit });
|
|
2469
|
-
const traces = await Promise.all(
|
|
2470
|
-
summaries.map((summary) => Promise.resolve(store.getTrace(summary.id)).catch(() => void 0))
|
|
2471
|
-
);
|
|
2472
|
-
return traces.flatMap(
|
|
2473
|
-
(trace) => trace === void 0 ? [] : evidenceFromTrace(trace)
|
|
2474
|
-
);
|
|
2475
|
-
}
|
|
2476
|
-
function evidenceFromTrace(trace) {
|
|
2477
|
-
return trace.observations.flatMap((observation) => {
|
|
2478
|
-
if (observation.kind !== "generation" || !isRecord2(observation.input)) {
|
|
2479
|
-
return [];
|
|
2480
|
-
}
|
|
2481
|
-
const documents = Array.isArray(observation.input.documents) ? observation.input.documents.flatMap((document) => evidenceDocument(document)) : [];
|
|
2482
|
-
const tools = Array.isArray(observation.input.tools) ? observation.input.tools.flatMap((tool) => evidenceToolName(tool)) : [];
|
|
2483
|
-
if (documents.length === 0 && tools.length === 0) {
|
|
2484
|
-
return [];
|
|
2485
|
-
}
|
|
2486
|
-
const query = queryFromGenerationInput(observation.input);
|
|
2487
|
-
return [
|
|
2488
|
-
{
|
|
2489
|
-
traceId: trace.id,
|
|
2490
|
-
sessionId: trace.sessionId,
|
|
2491
|
-
observationId: observation.id,
|
|
2492
|
-
observationName: observation.name,
|
|
2493
|
-
turn: observation.turn,
|
|
2494
|
-
startedAt: observation.startedAt,
|
|
2495
|
-
...query === void 0 ? {} : { query },
|
|
2496
|
-
documentCount: documents.length,
|
|
2497
|
-
toolCount: tools.length,
|
|
2498
|
-
documents,
|
|
2499
|
-
tools
|
|
2500
|
-
}
|
|
2501
|
-
];
|
|
2502
|
-
});
|
|
2503
|
-
}
|
|
2504
|
-
function queryFromGenerationInput(value) {
|
|
2505
|
-
const promptText = messageText(value.prompt);
|
|
2506
|
-
if (promptText.length > 0) {
|
|
2507
|
-
return promptText;
|
|
2508
|
-
}
|
|
2509
|
-
if (Array.isArray(value.chatHistory)) {
|
|
2510
|
-
for (let index = value.chatHistory.length - 1; index >= 0; index -= 1) {
|
|
2511
|
-
const text = messageText(value.chatHistory[index]);
|
|
2512
|
-
if (text.length > 0) {
|
|
2513
|
-
return text;
|
|
2514
|
-
}
|
|
2515
|
-
}
|
|
2516
|
-
}
|
|
2517
|
-
if (Array.isArray(value.history)) {
|
|
2518
|
-
for (let index = value.history.length - 1; index >= 0; index -= 1) {
|
|
2519
|
-
const text = messageText(value.history[index]);
|
|
2520
|
-
if (text.length > 0) {
|
|
2521
|
-
return text;
|
|
2522
|
-
}
|
|
2523
|
-
}
|
|
2524
|
-
}
|
|
2525
|
-
return void 0;
|
|
2526
|
-
}
|
|
2527
|
-
function messageText(value) {
|
|
2528
|
-
if (typeof value === "string") {
|
|
2529
|
-
return value.trim();
|
|
2530
|
-
}
|
|
2531
|
-
if (!isRecord2(value)) {
|
|
2532
|
-
return "";
|
|
2533
|
-
}
|
|
2534
|
-
if (typeof value.text === "string") {
|
|
2535
|
-
return value.text.trim();
|
|
2536
|
-
}
|
|
2537
|
-
if (typeof value.content === "string") {
|
|
2538
|
-
return value.content.trim();
|
|
2539
|
-
}
|
|
2540
|
-
if (Array.isArray(value.content)) {
|
|
2541
|
-
return value.content.map(contentText).filter(Boolean).join("\n").trim();
|
|
2542
|
-
}
|
|
2543
|
-
return "";
|
|
2544
|
-
}
|
|
2545
|
-
function contentText(value) {
|
|
2546
|
-
if (typeof value === "string") {
|
|
2547
|
-
return value.trim();
|
|
2548
|
-
}
|
|
2549
|
-
if (!isRecord2(value)) {
|
|
2550
|
-
return "";
|
|
2551
|
-
}
|
|
2552
|
-
if (typeof value.text === "string") {
|
|
2553
|
-
return value.text.trim();
|
|
2554
|
-
}
|
|
2555
|
-
return "";
|
|
2556
|
-
}
|
|
2557
|
-
function evidenceDocument(value) {
|
|
2558
|
-
if (!isRecord2(value)) {
|
|
2559
|
-
return [];
|
|
2560
|
-
}
|
|
2561
|
-
const id = typeof value.id === "string" ? value.id : void 0;
|
|
2562
|
-
const text = typeof value.text === "string" ? value.text : void 0;
|
|
2563
|
-
const additionalProps = isRecord2(value.additionalProps) ? jsonObjectFromRecord(value.additionalProps) : void 0;
|
|
2564
|
-
if (id === void 0 && text === void 0 && additionalProps === void 0) {
|
|
2565
|
-
return [];
|
|
2566
|
-
}
|
|
2567
|
-
return [
|
|
2568
|
-
{
|
|
2569
|
-
...id === void 0 ? {} : { id },
|
|
2570
|
-
...text === void 0 ? {} : { text },
|
|
2571
|
-
...additionalProps === void 0 ? {} : { additionalProps }
|
|
2572
|
-
}
|
|
2573
|
-
];
|
|
2574
|
-
}
|
|
2575
|
-
function evidenceToolName(value) {
|
|
2576
|
-
if (!isRecord2(value) || typeof value.name !== "string") {
|
|
2577
|
-
return [];
|
|
2578
|
-
}
|
|
2579
|
-
return [value.name];
|
|
2580
|
-
}
|
|
2581
|
-
function jsonObjectFromRecord(value) {
|
|
2582
|
-
return compactJsonObject(value);
|
|
2583
|
-
}
|
|
2584
|
-
function isRecord2(value) {
|
|
2585
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2586
|
-
}
|
|
2587
|
-
|
|
2588
|
-
// src/runtime/mcps.ts
|
|
2589
|
-
function registerMcpRoutes(app, props) {
|
|
2590
|
-
app.get("/agents/:agentId/mcps", async (c) => {
|
|
2591
|
-
const agentId = c.req.param("agentId");
|
|
2592
|
-
const agent = props.agentMap.get(agentId);
|
|
2593
|
-
if (agent === void 0) {
|
|
2594
|
-
return errorResponse(c, 404, "not_found", "Agent not found");
|
|
2595
|
-
}
|
|
2596
|
-
return c.json({
|
|
2597
|
-
agentId,
|
|
2598
|
-
servers: await agentMcpMetadata(agent)
|
|
2599
|
-
});
|
|
2600
|
-
});
|
|
2601
|
-
}
|
|
2602
|
-
async function agentMcpMetadata(agent) {
|
|
2603
|
-
const servers = /* @__PURE__ */ new Map();
|
|
2604
|
-
const seen = /* @__PURE__ */ new Set();
|
|
2605
|
-
for (const { tool, source } of agentToolItems(agent)) {
|
|
2606
|
-
const serverName = mcpServerName(tool);
|
|
2607
|
-
if (serverName === void 0) {
|
|
2608
|
-
continue;
|
|
2609
|
-
}
|
|
2610
|
-
const definition = await tool.definition("");
|
|
2611
|
-
const key = `${serverName}:${source}:${definition.name}`;
|
|
2612
|
-
if (seen.has(key)) {
|
|
2613
|
-
continue;
|
|
2614
|
-
}
|
|
2615
|
-
seen.add(key);
|
|
2616
|
-
const tools = servers.get(serverName) ?? [];
|
|
2617
|
-
tools.push({
|
|
2618
|
-
name: definition.name,
|
|
2619
|
-
description: definition.description,
|
|
2620
|
-
parameters: definition.parameters,
|
|
2621
|
-
source
|
|
2622
|
-
});
|
|
2623
|
-
servers.set(serverName, tools);
|
|
2624
|
-
}
|
|
2625
|
-
return [...servers.entries()].map(([name, tools]) => {
|
|
2626
|
-
const sortedTools = tools.sort((left, right) => {
|
|
2627
|
-
if (left.source !== right.source) {
|
|
2628
|
-
return left.source === "static" ? -1 : 1;
|
|
2629
|
-
}
|
|
2630
|
-
return left.name.localeCompare(right.name);
|
|
2631
|
-
});
|
|
2632
|
-
return {
|
|
2633
|
-
agentId: agent.id,
|
|
2634
|
-
name,
|
|
2635
|
-
toolCount: sortedTools.length,
|
|
2636
|
-
tools: sortedTools
|
|
2637
|
-
};
|
|
2638
|
-
}).sort((left, right) => left.name.localeCompare(right.name));
|
|
2196
|
+
}).sort((left, right) => left.name.localeCompare(right.name));
|
|
2639
2197
|
}
|
|
2640
2198
|
|
|
2641
2199
|
// src/runtime/memory.ts
|
|
@@ -2681,7 +2239,7 @@ function registerMemoryRoutes(app, props) {
|
|
|
2681
2239
|
const agentId = optionalQueryString(c.req.query("agentId"));
|
|
2682
2240
|
const userId = optionalQueryString(c.req.query("userId"));
|
|
2683
2241
|
const sessions = await props.sessionStore.listSessions({
|
|
2684
|
-
...
|
|
2242
|
+
...compact({ agentId }),
|
|
2685
2243
|
limit: 100
|
|
2686
2244
|
});
|
|
2687
2245
|
const conversations = sessions.map(memoryConversationSummary).filter((session) => userId === void 0 || session.userId === userId).slice(0, limit);
|
|
@@ -2713,16 +2271,16 @@ function registerMemoryRoutes(app, props) {
|
|
|
2713
2271
|
});
|
|
2714
2272
|
}
|
|
2715
2273
|
function memoryConversationSummary(session) {
|
|
2716
|
-
return {
|
|
2274
|
+
return compact({
|
|
2717
2275
|
id: session.id,
|
|
2718
2276
|
userId: sessionUserId(session),
|
|
2719
2277
|
agentId: session.agentId,
|
|
2720
|
-
|
|
2278
|
+
title: session.title,
|
|
2721
2279
|
createdAt: session.createdAt,
|
|
2722
2280
|
updatedAt: session.updatedAt,
|
|
2723
2281
|
messageCount: session.messageCount,
|
|
2724
|
-
|
|
2725
|
-
};
|
|
2282
|
+
metadata: session.metadata
|
|
2283
|
+
});
|
|
2726
2284
|
}
|
|
2727
2285
|
function sessionUserId(session) {
|
|
2728
2286
|
const userId = session.metadata?.userId;
|
|
@@ -2809,9 +2367,11 @@ var StudioObservabilityHub = class {
|
|
|
2809
2367
|
function observeStores(stores, hub) {
|
|
2810
2368
|
return {
|
|
2811
2369
|
...stores,
|
|
2812
|
-
...
|
|
2813
|
-
|
|
2814
|
-
|
|
2370
|
+
...compact({
|
|
2371
|
+
sessions: stores.sessions !== void 0 ? observeSessionStore(stores.sessions, hub) : void 0,
|
|
2372
|
+
traces: stores.traces !== void 0 ? observeTraceStore(stores.traces, hub) : void 0,
|
|
2373
|
+
pipelineLogs: stores.pipelineLogs !== void 0 ? observePipelineLogStore(stores.pipelineLogs, hub) : void 0
|
|
2374
|
+
})
|
|
2815
2375
|
};
|
|
2816
2376
|
}
|
|
2817
2377
|
function registerObservabilityRoutes(app, hub) {
|
|
@@ -2832,7 +2392,7 @@ function registerObservabilityRoutes(app, hub) {
|
|
|
2832
2392
|
});
|
|
2833
2393
|
}
|
|
2834
2394
|
function observabilityEvents(hub, types) {
|
|
2835
|
-
const subscription = hub.subscribe(
|
|
2395
|
+
const subscription = hub.subscribe(compact({ types }));
|
|
2836
2396
|
return {
|
|
2837
2397
|
[Symbol.asyncIterator]() {
|
|
2838
2398
|
return {
|
|
@@ -2924,7 +2484,7 @@ function observeTraceStore(store, hub) {
|
|
|
2924
2484
|
const saveTrace = target.saveTrace.bind(target);
|
|
2925
2485
|
return async (...args) => {
|
|
2926
2486
|
const trace = await saveTrace(...args);
|
|
2927
|
-
hub.emit({ type: "trace", trace:
|
|
2487
|
+
hub.emit({ type: "trace", trace: traceSummary(trace) });
|
|
2928
2488
|
return trace;
|
|
2929
2489
|
};
|
|
2930
2490
|
}
|
|
@@ -2951,20 +2511,22 @@ function parseEventTypes(value) {
|
|
|
2951
2511
|
function isEventType(value) {
|
|
2952
2512
|
return value === "session_log" || value === "pipeline_log" || value === "trace";
|
|
2953
2513
|
}
|
|
2954
|
-
function
|
|
2514
|
+
function traceSummary(trace) {
|
|
2955
2515
|
return {
|
|
2956
2516
|
id: trace.id,
|
|
2957
2517
|
sessionId: trace.sessionId,
|
|
2958
|
-
...trace.name === void 0 ? {} : { name: trace.name },
|
|
2959
2518
|
status: trace.status,
|
|
2960
2519
|
startedAt: trace.startedAt,
|
|
2961
|
-
|
|
2962
|
-
...
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2520
|
+
observationCount: trace.observations.length,
|
|
2521
|
+
...compact({
|
|
2522
|
+
name: trace.name,
|
|
2523
|
+
endedAt: trace.endedAt,
|
|
2524
|
+
durationMs: trace.durationMs,
|
|
2525
|
+
output: trace.output,
|
|
2526
|
+
error: trace.error,
|
|
2527
|
+
usage: trace.usage,
|
|
2528
|
+
metadata: trace.metadata
|
|
2529
|
+
})
|
|
2968
2530
|
};
|
|
2969
2531
|
}
|
|
2970
2532
|
|
|
@@ -2986,7 +2548,7 @@ function pipelineRunReceivedLog(props) {
|
|
|
2986
2548
|
category: "api",
|
|
2987
2549
|
event: "pipeline.run_received",
|
|
2988
2550
|
message: "Pipeline run request received",
|
|
2989
|
-
metadata:
|
|
2551
|
+
metadata: compact({
|
|
2990
2552
|
stream: props.stream,
|
|
2991
2553
|
inputBytes: byteLength2(formatUnknown(props.input)),
|
|
2992
2554
|
metadataKeys: Object.keys(props.metadata ?? {})
|
|
@@ -3002,7 +2564,7 @@ function pipelineRunStartedLog(pipeline, runId) {
|
|
|
3002
2564
|
category: "run",
|
|
3003
2565
|
event: "pipeline.run_started",
|
|
3004
2566
|
message: "Pipeline run started",
|
|
3005
|
-
metadata:
|
|
2567
|
+
metadata: compact({
|
|
3006
2568
|
stageCount: graph.nodes.filter((node) => node.kind !== "input" && node.kind !== "output").length,
|
|
3007
2569
|
edgeCount: graph.edges.length
|
|
3008
2570
|
})
|
|
@@ -3016,7 +2578,7 @@ function pipelineRunCompletedLog(props) {
|
|
|
3016
2578
|
category: "run",
|
|
3017
2579
|
event: "pipeline.run_completed",
|
|
3018
2580
|
message: "Pipeline run completed",
|
|
3019
|
-
metadata:
|
|
2581
|
+
metadata: compact({
|
|
3020
2582
|
durationMs: props.durationMs,
|
|
3021
2583
|
outputBytes: byteLength2(formatUnknown(props.output))
|
|
3022
2584
|
})
|
|
@@ -3030,7 +2592,7 @@ function pipelineRunFailedLog(pipelineId, runId, error, startedAt) {
|
|
|
3030
2592
|
category: "run",
|
|
3031
2593
|
event: "pipeline.run_failed",
|
|
3032
2594
|
message: "Pipeline run failed",
|
|
3033
|
-
metadata:
|
|
2595
|
+
metadata: compact({
|
|
3034
2596
|
durationMs: Date.now() - startedAt,
|
|
3035
2597
|
error: serializeError(error)
|
|
3036
2598
|
})
|
|
@@ -3057,7 +2619,7 @@ function pipelineStageLog(pipelineId, runId, event) {
|
|
|
3057
2619
|
category,
|
|
3058
2620
|
event: `${event.node.kind}.completed`,
|
|
3059
2621
|
message: `${event.node.label} completed`,
|
|
3060
|
-
metadata:
|
|
2622
|
+
metadata: compact({
|
|
3061
2623
|
...nodeMetadata(event.node),
|
|
3062
2624
|
durationMs: event.durationMs
|
|
3063
2625
|
})
|
|
@@ -3070,7 +2632,7 @@ function pipelineStageLog(pipelineId, runId, event) {
|
|
|
3070
2632
|
category,
|
|
3071
2633
|
event: `${event.node.kind}.failed`,
|
|
3072
2634
|
message: `${event.node.label} failed`,
|
|
3073
|
-
metadata:
|
|
2635
|
+
metadata: compact({
|
|
3074
2636
|
...nodeMetadata(event.node),
|
|
3075
2637
|
durationMs: event.durationMs,
|
|
3076
2638
|
error: serializeError(event.error)
|
|
@@ -3090,7 +2652,7 @@ function stageCategory(node) {
|
|
|
3090
2652
|
return "stage";
|
|
3091
2653
|
}
|
|
3092
2654
|
function nodeMetadata(node) {
|
|
3093
|
-
return
|
|
2655
|
+
return compact({
|
|
3094
2656
|
nodeId: node.id,
|
|
3095
2657
|
kind: node.kind,
|
|
3096
2658
|
label: node.label,
|
|
@@ -3099,50 +2661,153 @@ function nodeMetadata(node) {
|
|
|
3099
2661
|
branchKey: node.branchKey
|
|
3100
2662
|
});
|
|
3101
2663
|
}
|
|
3102
|
-
function cleanMetadata(value) {
|
|
3103
|
-
return Object.fromEntries(
|
|
3104
|
-
Object.entries(value).filter(([, item]) => item !== void 0)
|
|
3105
|
-
);
|
|
3106
|
-
}
|
|
3107
2664
|
function byteLength2(value) {
|
|
3108
2665
|
return value === void 0 ? void 0 : new TextEncoder().encode(value).length;
|
|
3109
2666
|
}
|
|
3110
|
-
function formatUnknown(value) {
|
|
3111
|
-
try {
|
|
3112
|
-
return JSON.stringify(value);
|
|
3113
|
-
} catch {
|
|
3114
|
-
return void 0;
|
|
3115
|
-
}
|
|
3116
|
-
}
|
|
3117
2667
|
|
|
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 });
|
|
3138
|
-
}
|
|
3139
|
-
}
|
|
3140
|
-
next() {
|
|
3141
|
-
const value = this.values.shift();
|
|
3142
|
-
if (value !== void 0) {
|
|
3143
|
-
return Promise.resolve({ done: false, value });
|
|
2668
|
+
// src/runtime/transcript.ts
|
|
2669
|
+
function renumberTranscript(entries) {
|
|
2670
|
+
return entries.map((entry, entryId) => ({ ...entry, entryId }));
|
|
2671
|
+
}
|
|
2672
|
+
function transcriptFromMessages(messages) {
|
|
2673
|
+
const transcript = [];
|
|
2674
|
+
for (const message of messages) {
|
|
2675
|
+
if (message.role === "system") {
|
|
2676
|
+
continue;
|
|
3144
2677
|
}
|
|
3145
|
-
if (
|
|
2678
|
+
if (message.role === "user") {
|
|
2679
|
+
const attachments = attachmentsFromMessage(message);
|
|
2680
|
+
let textEntryAdded = false;
|
|
2681
|
+
for (const content of message.content) {
|
|
2682
|
+
if (content.type === "text") {
|
|
2683
|
+
transcript.push(compact({
|
|
2684
|
+
entryId: transcript.length,
|
|
2685
|
+
kind: "message",
|
|
2686
|
+
role: "user",
|
|
2687
|
+
text: content.text,
|
|
2688
|
+
attachments: attachments.length === 0 ? void 0 : attachments
|
|
2689
|
+
}));
|
|
2690
|
+
textEntryAdded = true;
|
|
2691
|
+
}
|
|
2692
|
+
}
|
|
2693
|
+
if (!textEntryAdded && attachments.length > 0) {
|
|
2694
|
+
transcript.push({
|
|
2695
|
+
entryId: transcript.length,
|
|
2696
|
+
kind: "message",
|
|
2697
|
+
role: "user",
|
|
2698
|
+
text: "",
|
|
2699
|
+
attachments
|
|
2700
|
+
});
|
|
2701
|
+
}
|
|
2702
|
+
continue;
|
|
2703
|
+
}
|
|
2704
|
+
if (message.role === "tool") {
|
|
2705
|
+
for (const content of message.content) {
|
|
2706
|
+
transcript.push({
|
|
2707
|
+
entryId: transcript.length,
|
|
2708
|
+
kind: "tool",
|
|
2709
|
+
toolName: "tool_result",
|
|
2710
|
+
callId: content.callId ?? content.id,
|
|
2711
|
+
result: content.content.map(
|
|
2712
|
+
(item) => "text" in item ? item.text : `[image:${item.mediaType ?? "image/png"}]`
|
|
2713
|
+
).join("\n"),
|
|
2714
|
+
structuredResult: content.content
|
|
2715
|
+
});
|
|
2716
|
+
}
|
|
2717
|
+
continue;
|
|
2718
|
+
}
|
|
2719
|
+
for (const content of message.content) {
|
|
2720
|
+
if (content.type === "text") {
|
|
2721
|
+
appendAssistantTranscriptText(transcript, content.text);
|
|
2722
|
+
} else if (content.type === "reasoning") {
|
|
2723
|
+
transcript.push(compact({
|
|
2724
|
+
entryId: transcript.length,
|
|
2725
|
+
kind: "reasoning",
|
|
2726
|
+
reasoningId: content.id,
|
|
2727
|
+
text: content.text
|
|
2728
|
+
}));
|
|
2729
|
+
} else if (content.type === "tool_call") {
|
|
2730
|
+
transcript.push({
|
|
2731
|
+
entryId: transcript.length,
|
|
2732
|
+
kind: "tool",
|
|
2733
|
+
toolName: content.function.name,
|
|
2734
|
+
callId: content.callId ?? content.id,
|
|
2735
|
+
args: formatJson(content.function.arguments)
|
|
2736
|
+
});
|
|
2737
|
+
}
|
|
2738
|
+
}
|
|
2739
|
+
}
|
|
2740
|
+
return transcript;
|
|
2741
|
+
}
|
|
2742
|
+
function attachmentsFromMessage(message) {
|
|
2743
|
+
if (message.role !== "user" && message.role !== "assistant") {
|
|
2744
|
+
return [];
|
|
2745
|
+
}
|
|
2746
|
+
return message.content.flatMap((content) => {
|
|
2747
|
+
if (content.type === "image") {
|
|
2748
|
+
return [
|
|
2749
|
+
{
|
|
2750
|
+
kind: "image",
|
|
2751
|
+
...content.source.type === "base64" ? { data: content.source.data, mediaType: content.source.mediaType } : { url: content.source.url }
|
|
2752
|
+
}
|
|
2753
|
+
];
|
|
2754
|
+
}
|
|
2755
|
+
if (content.type === "document") {
|
|
2756
|
+
return [
|
|
2757
|
+
compact({
|
|
2758
|
+
kind: "document",
|
|
2759
|
+
name: content.source.filename,
|
|
2760
|
+
mediaType: content.source.mediaType,
|
|
2761
|
+
data: content.source.type === "base64" ? content.source.data : void 0,
|
|
2762
|
+
url: content.source.type === "url" ? content.source.url : void 0
|
|
2763
|
+
})
|
|
2764
|
+
];
|
|
2765
|
+
}
|
|
2766
|
+
return [];
|
|
2767
|
+
});
|
|
2768
|
+
}
|
|
2769
|
+
function appendAssistantTranscriptText(transcript, text) {
|
|
2770
|
+
const last = transcript.at(-1);
|
|
2771
|
+
if (last?.kind === "message" && last.role === "assistant") {
|
|
2772
|
+
last.text = `${last.text}${text}`;
|
|
2773
|
+
return;
|
|
2774
|
+
}
|
|
2775
|
+
transcript.push({
|
|
2776
|
+
entryId: transcript.length,
|
|
2777
|
+
kind: "message",
|
|
2778
|
+
role: "assistant",
|
|
2779
|
+
text
|
|
2780
|
+
});
|
|
2781
|
+
}
|
|
2782
|
+
|
|
2783
|
+
// src/runtime/runs.ts
|
|
2784
|
+
var AsyncEventQueue = class {
|
|
2785
|
+
values = [];
|
|
2786
|
+
resolvers = [];
|
|
2787
|
+
closed = false;
|
|
2788
|
+
push(value) {
|
|
2789
|
+
if (this.closed) {
|
|
2790
|
+
return;
|
|
2791
|
+
}
|
|
2792
|
+
const resolver = this.resolvers.shift();
|
|
2793
|
+
if (resolver !== void 0) {
|
|
2794
|
+
resolver({ done: false, value });
|
|
2795
|
+
return;
|
|
2796
|
+
}
|
|
2797
|
+
this.values.push(value);
|
|
2798
|
+
}
|
|
2799
|
+
close() {
|
|
2800
|
+
this.closed = true;
|
|
2801
|
+
for (const resolver of this.resolvers.splice(0)) {
|
|
2802
|
+
resolver({ done: true, value: void 0 });
|
|
2803
|
+
}
|
|
2804
|
+
}
|
|
2805
|
+
next() {
|
|
2806
|
+
const value = this.values.shift();
|
|
2807
|
+
if (value !== void 0) {
|
|
2808
|
+
return Promise.resolve({ done: false, value });
|
|
2809
|
+
}
|
|
2810
|
+
if (this.closed) {
|
|
3146
2811
|
return Promise.resolve({ done: true, value: void 0 });
|
|
3147
2812
|
}
|
|
3148
2813
|
return new Promise((resolve2) => this.resolvers.push(resolve2));
|
|
@@ -3263,21 +2928,21 @@ function acceptTranscriptStreamEvent(transcript, event) {
|
|
|
3263
2928
|
kind: "tool",
|
|
3264
2929
|
toolName: event.toolCall.function.name,
|
|
3265
2930
|
callId: event.toolCall.callId ?? event.toolCall.id,
|
|
3266
|
-
args:
|
|
2931
|
+
args: formatJson(event.toolCall.function.arguments)
|
|
3267
2932
|
});
|
|
3268
2933
|
}
|
|
3269
2934
|
if (event.type === "tool_result") {
|
|
3270
2935
|
const matched = findTranscriptToolEntry(transcript, event.toolName, event.toolCallId);
|
|
3271
2936
|
if (matched === void 0) {
|
|
3272
|
-
transcript.push({
|
|
2937
|
+
transcript.push(compact({
|
|
3273
2938
|
entryId: transcript.length,
|
|
3274
2939
|
kind: "tool",
|
|
3275
2940
|
toolName: event.toolName,
|
|
3276
|
-
|
|
2941
|
+
callId: event.toolCallId,
|
|
3277
2942
|
args: event.args,
|
|
3278
2943
|
result: event.result,
|
|
3279
|
-
|
|
3280
|
-
});
|
|
2944
|
+
structuredResult: event.structuredResult
|
|
2945
|
+
}));
|
|
3281
2946
|
return;
|
|
3282
2947
|
}
|
|
3283
2948
|
matched.args = matched.args ?? event.args;
|
|
@@ -3289,15 +2954,15 @@ function acceptTranscriptStreamEvent(transcript, event) {
|
|
|
3289
2954
|
if (event.type === "agent_tool_event") {
|
|
3290
2955
|
const matched = findTranscriptToolEntry(transcript, event.toolName, event.toolCallId);
|
|
3291
2956
|
if (matched === void 0) {
|
|
3292
|
-
transcript.push({
|
|
2957
|
+
transcript.push(compact({
|
|
3293
2958
|
entryId: transcript.length,
|
|
3294
2959
|
kind: "tool",
|
|
3295
2960
|
toolName: event.toolName,
|
|
3296
|
-
|
|
2961
|
+
callId: event.toolCallId,
|
|
3297
2962
|
childEvents: [childAgentTranscriptEvent(event)].filter(
|
|
3298
2963
|
(childEvent) => childEvent !== void 0
|
|
3299
2964
|
)
|
|
3300
|
-
});
|
|
2965
|
+
}));
|
|
3301
2966
|
return;
|
|
3302
2967
|
}
|
|
3303
2968
|
appendChildAgentTranscriptEvent(matched, event);
|
|
@@ -3323,13 +2988,13 @@ function acceptTranscriptStreamEvent(transcript, event) {
|
|
|
3323
2988
|
approvalCallId(event.approval)
|
|
3324
2989
|
);
|
|
3325
2990
|
if (matched !== void 0) {
|
|
3326
|
-
matched.approval = {
|
|
2991
|
+
matched.approval = compact({
|
|
3327
2992
|
id: event.approval.id,
|
|
3328
2993
|
status: event.approval.status,
|
|
3329
2994
|
requestedAt: event.approval.requestedAt,
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
};
|
|
2995
|
+
resolvedAt: event.approval.resolvedAt,
|
|
2996
|
+
reason: event.approval.reason
|
|
2997
|
+
});
|
|
3333
2998
|
}
|
|
3334
2999
|
}
|
|
3335
3000
|
if (event.type === "tool_question_request") {
|
|
@@ -3354,14 +3019,14 @@ function acceptTranscriptStreamEvent(transcript, event) {
|
|
|
3354
3019
|
questionCallId(event.question)
|
|
3355
3020
|
);
|
|
3356
3021
|
if (matched !== void 0) {
|
|
3357
|
-
matched.question = {
|
|
3022
|
+
matched.question = compact({
|
|
3358
3023
|
id: event.question.id,
|
|
3359
3024
|
status: event.question.status,
|
|
3360
3025
|
requestedAt: event.question.requestedAt,
|
|
3361
|
-
|
|
3026
|
+
answeredAt: event.question.answeredAt,
|
|
3362
3027
|
questions: event.question.questions,
|
|
3363
|
-
|
|
3364
|
-
};
|
|
3028
|
+
answers: event.question.answers
|
|
3029
|
+
});
|
|
3365
3030
|
}
|
|
3366
3031
|
}
|
|
3367
3032
|
if (event.type === "final" && event.trace?.traceId !== void 0) {
|
|
@@ -3415,51 +3080,51 @@ function appendChildAgentTranscriptEvent(entry, event) {
|
|
|
3415
3080
|
function childAgentTranscriptEvent(event) {
|
|
3416
3081
|
const child = event.event;
|
|
3417
3082
|
if (child.type === "text_delta") {
|
|
3418
|
-
return {
|
|
3083
|
+
return compact({
|
|
3419
3084
|
kind: "message",
|
|
3420
3085
|
agentId: event.agentId,
|
|
3421
|
-
|
|
3086
|
+
agentName: event.agentName,
|
|
3422
3087
|
text: child.delta
|
|
3423
|
-
};
|
|
3088
|
+
});
|
|
3424
3089
|
}
|
|
3425
3090
|
if (child.type === "reasoning_delta") {
|
|
3426
|
-
return {
|
|
3091
|
+
return compact({
|
|
3427
3092
|
kind: "reasoning",
|
|
3428
3093
|
agentId: event.agentId,
|
|
3429
|
-
|
|
3430
|
-
|
|
3094
|
+
agentName: event.agentName,
|
|
3095
|
+
reasoningId: child.id,
|
|
3431
3096
|
text: child.delta
|
|
3432
|
-
};
|
|
3097
|
+
});
|
|
3433
3098
|
}
|
|
3434
3099
|
if (child.type === "tool_call") {
|
|
3435
|
-
return {
|
|
3100
|
+
return compact({
|
|
3436
3101
|
kind: "tool",
|
|
3437
3102
|
agentId: event.agentId,
|
|
3438
|
-
|
|
3103
|
+
agentName: event.agentName,
|
|
3439
3104
|
toolName: child.toolCall.function.name,
|
|
3440
|
-
|
|
3441
|
-
args:
|
|
3442
|
-
};
|
|
3105
|
+
callId: child.toolCall.callId ?? child.toolCall.id,
|
|
3106
|
+
args: formatJson(child.toolCall.function.arguments)
|
|
3107
|
+
});
|
|
3443
3108
|
}
|
|
3444
3109
|
if (child.type === "tool_result") {
|
|
3445
|
-
return {
|
|
3110
|
+
return compact({
|
|
3446
3111
|
kind: "tool",
|
|
3447
3112
|
agentId: event.agentId,
|
|
3448
|
-
|
|
3113
|
+
agentName: event.agentName,
|
|
3449
3114
|
toolName: child.toolName,
|
|
3450
|
-
|
|
3115
|
+
callId: child.toolCallId,
|
|
3451
3116
|
args: child.args,
|
|
3452
3117
|
result: child.result,
|
|
3453
|
-
|
|
3454
|
-
};
|
|
3118
|
+
structuredResult: child.structuredResult
|
|
3119
|
+
});
|
|
3455
3120
|
}
|
|
3456
3121
|
if (child.type === "error") {
|
|
3457
|
-
return {
|
|
3122
|
+
return compact({
|
|
3458
3123
|
kind: "message",
|
|
3459
3124
|
agentId: event.agentId,
|
|
3460
|
-
|
|
3125
|
+
agentName: event.agentName,
|
|
3461
3126
|
text: `Error: ${errorText(child.error)}`
|
|
3462
|
-
};
|
|
3127
|
+
});
|
|
3463
3128
|
}
|
|
3464
3129
|
return void 0;
|
|
3465
3130
|
}
|
|
@@ -3532,12 +3197,12 @@ function appendTranscriptReasoningText(transcript, delta, reasoningId) {
|
|
|
3532
3197
|
last.text = `${last.text}${delta}`;
|
|
3533
3198
|
return;
|
|
3534
3199
|
}
|
|
3535
|
-
transcript.push({
|
|
3200
|
+
transcript.push(compact({
|
|
3536
3201
|
entryId: transcript.length,
|
|
3537
3202
|
kind: "reasoning",
|
|
3538
|
-
|
|
3203
|
+
reasoningId,
|
|
3539
3204
|
text: delta
|
|
3540
|
-
});
|
|
3205
|
+
}));
|
|
3541
3206
|
}
|
|
3542
3207
|
function findTranscriptToolEntry(transcript, toolName, callId) {
|
|
3543
3208
|
for (let index = transcript.length - 1; index >= 0; index -= 1) {
|
|
@@ -3574,7 +3239,7 @@ function extractMessageText(message) {
|
|
|
3574
3239
|
return [item.text];
|
|
3575
3240
|
}
|
|
3576
3241
|
if (item.type === "tool_call") {
|
|
3577
|
-
return [`${item.function.name}(${
|
|
3242
|
+
return [`${item.function.name}(${formatJson(item.function.arguments)})`];
|
|
3578
3243
|
}
|
|
3579
3244
|
if (item.type === "tool_result") {
|
|
3580
3245
|
return item.content.map(
|
|
@@ -3599,25 +3264,19 @@ function optionalTranscriptAttachments(message) {
|
|
|
3599
3264
|
}
|
|
3600
3265
|
if (content.type === "document") {
|
|
3601
3266
|
return [
|
|
3602
|
-
{
|
|
3267
|
+
compact({
|
|
3603
3268
|
kind: "document",
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3269
|
+
name: content.source.filename,
|
|
3270
|
+
mediaType: content.source.mediaType,
|
|
3271
|
+
data: content.source.type === "base64" ? content.source.data : void 0,
|
|
3272
|
+
url: content.source.type === "url" ? content.source.url : void 0
|
|
3273
|
+
})
|
|
3608
3274
|
];
|
|
3609
3275
|
}
|
|
3610
3276
|
return [];
|
|
3611
3277
|
});
|
|
3612
3278
|
return attachments.length === 0 ? {} : { attachments };
|
|
3613
3279
|
}
|
|
3614
|
-
function formatJson2(value) {
|
|
3615
|
-
try {
|
|
3616
|
-
return JSON.stringify(value, null, 2);
|
|
3617
|
-
} catch {
|
|
3618
|
-
return String(value);
|
|
3619
|
-
}
|
|
3620
|
-
}
|
|
3621
3280
|
async function parseRunRequest(c) {
|
|
3622
3281
|
let body;
|
|
3623
3282
|
try {
|
|
@@ -3695,7 +3354,7 @@ async function parseRunRequest(c) {
|
|
|
3695
3354
|
}
|
|
3696
3355
|
}
|
|
3697
3356
|
if ("metadata" in body) {
|
|
3698
|
-
if (!
|
|
3357
|
+
if (!isJsonObject(body.metadata)) {
|
|
3699
3358
|
return { error: errorResponse(c, 400, "bad_request", "metadata must be an object") };
|
|
3700
3359
|
}
|
|
3701
3360
|
request.metadata = body.metadata;
|
|
@@ -3751,7 +3410,7 @@ function registerPipelineRoutes(app, props) {
|
|
|
3751
3410
|
const logs = await props.logStore.listPipelineLogs({
|
|
3752
3411
|
pipelineId,
|
|
3753
3412
|
limit,
|
|
3754
|
-
...
|
|
3413
|
+
...compact({ after })
|
|
3755
3414
|
});
|
|
3756
3415
|
const last = logs.at(-1);
|
|
3757
3416
|
return c.json({
|
|
@@ -3822,7 +3481,7 @@ function registerPipelineRoutes(app, props) {
|
|
|
3822
3481
|
}
|
|
3823
3482
|
return executePipelineRun(c, props, pipeline, {
|
|
3824
3483
|
input: sourceRun.input,
|
|
3825
|
-
...
|
|
3484
|
+
...compact({ stream: body.stream }),
|
|
3826
3485
|
metadata: replayMetadata(sourceRun.metadata, body.metadata, sourceRun.runId)
|
|
3827
3486
|
});
|
|
3828
3487
|
});
|
|
@@ -3838,7 +3497,7 @@ async function executePipelineRun(c, props, pipeline, body) {
|
|
|
3838
3497
|
runId,
|
|
3839
3498
|
stream: body.stream === true,
|
|
3840
3499
|
input: body.input,
|
|
3841
|
-
...
|
|
3500
|
+
...compact({ metadata: body.metadata })
|
|
3842
3501
|
})
|
|
3843
3502
|
);
|
|
3844
3503
|
await savePipelineRun(props.runStore, {
|
|
@@ -3846,7 +3505,7 @@ async function executePipelineRun(c, props, pipeline, body) {
|
|
|
3846
3505
|
pipelineId: pipeline.id,
|
|
3847
3506
|
status: "running",
|
|
3848
3507
|
input: body.input,
|
|
3849
|
-
...
|
|
3508
|
+
...compact({ metadata: body.metadata }),
|
|
3850
3509
|
startedAt: startedAtIso
|
|
3851
3510
|
});
|
|
3852
3511
|
if (body.stream === true) {
|
|
@@ -3856,9 +3515,8 @@ async function executePipelineRun(c, props, pipeline, body) {
|
|
|
3856
3515
|
input: body.input,
|
|
3857
3516
|
startedAt,
|
|
3858
3517
|
startedAtIso,
|
|
3859
|
-
...
|
|
3860
|
-
...
|
|
3861
|
-
...props.runStore === void 0 ? {} : { runStore: props.runStore }
|
|
3518
|
+
...compact({ metadata: body.metadata }),
|
|
3519
|
+
...compact({ logStore: props.logStore, runStore: props.runStore })
|
|
3862
3520
|
});
|
|
3863
3521
|
}
|
|
3864
3522
|
try {
|
|
@@ -3878,7 +3536,7 @@ async function executePipelineRun(c, props, pipeline, body) {
|
|
|
3878
3536
|
status: "success",
|
|
3879
3537
|
input: body.input,
|
|
3880
3538
|
output: jsonOutput,
|
|
3881
|
-
...
|
|
3539
|
+
...compact({ metadata: body.metadata }),
|
|
3882
3540
|
startedAt: startedAtIso,
|
|
3883
3541
|
endedAt: new Date(endedAt).toISOString(),
|
|
3884
3542
|
durationMs: endedAt - startedAt
|
|
@@ -3906,7 +3564,7 @@ async function executePipelineRun(c, props, pipeline, body) {
|
|
|
3906
3564
|
status: "error",
|
|
3907
3565
|
input: body.input,
|
|
3908
3566
|
error: serializeError(error),
|
|
3909
|
-
...
|
|
3567
|
+
...compact({ metadata: body.metadata }),
|
|
3910
3568
|
startedAt: startedAtIso,
|
|
3911
3569
|
endedAt: new Date(endedAt).toISOString(),
|
|
3912
3570
|
durationMs: endedAt - startedAt
|
|
@@ -3953,7 +3611,7 @@ async function* pipelineRunEvents(props) {
|
|
|
3953
3611
|
status: "success",
|
|
3954
3612
|
input: props.input,
|
|
3955
3613
|
output: jsonOutput,
|
|
3956
|
-
...
|
|
3614
|
+
...compact({ metadata: props.metadata }),
|
|
3957
3615
|
startedAt: props.startedAtIso,
|
|
3958
3616
|
endedAt: new Date(endedAt).toISOString(),
|
|
3959
3617
|
durationMs: endedAt - props.startedAt
|
|
@@ -3984,7 +3642,7 @@ async function* pipelineRunEvents(props) {
|
|
|
3984
3642
|
status: "error",
|
|
3985
3643
|
input: props.input,
|
|
3986
3644
|
error: serializeError(error),
|
|
3987
|
-
...
|
|
3645
|
+
...compact({ metadata: props.metadata }),
|
|
3988
3646
|
startedAt: props.startedAtIso,
|
|
3989
3647
|
endedAt: new Date(endedAt).toISOString(),
|
|
3990
3648
|
durationMs: endedAt - props.startedAt
|
|
@@ -4023,7 +3681,7 @@ async function parsePipelineRunRequest(c) {
|
|
|
4023
3681
|
if (!isObject(body)) {
|
|
4024
3682
|
return { error: errorResponse(c, 400, "bad_request", "Request body must be an object") };
|
|
4025
3683
|
}
|
|
4026
|
-
if (!("input" in body) || !
|
|
3684
|
+
if (!("input" in body) || !isJsonValue2(body.input)) {
|
|
4027
3685
|
return { error: errorResponse(c, 400, "bad_request", "input must be JSON-compatible") };
|
|
4028
3686
|
}
|
|
4029
3687
|
const request = {
|
|
@@ -4036,7 +3694,7 @@ async function parsePipelineRunRequest(c) {
|
|
|
4036
3694
|
request.stream = body.stream;
|
|
4037
3695
|
}
|
|
4038
3696
|
if ("metadata" in body) {
|
|
4039
|
-
if (!
|
|
3697
|
+
if (!isJsonObject(body.metadata)) {
|
|
4040
3698
|
return { error: errorResponse(c, 400, "bad_request", "metadata must be an object") };
|
|
4041
3699
|
}
|
|
4042
3700
|
request.metadata = body.metadata;
|
|
@@ -4061,7 +3719,7 @@ async function parsePipelineReplayRequest(c) {
|
|
|
4061
3719
|
request.stream = body.stream;
|
|
4062
3720
|
}
|
|
4063
3721
|
if ("metadata" in body) {
|
|
4064
|
-
if (!
|
|
3722
|
+
if (!isJsonObject(body.metadata)) {
|
|
4065
3723
|
return { error: errorResponse(c, 400, "bad_request", "metadata must be an object") };
|
|
4066
3724
|
}
|
|
4067
3725
|
request.metadata = body.metadata;
|
|
@@ -4095,15 +3753,15 @@ function parsePipelineLogAfter(value) {
|
|
|
4095
3753
|
}
|
|
4096
3754
|
return after;
|
|
4097
3755
|
}
|
|
4098
|
-
function
|
|
3756
|
+
function isJsonValue2(value) {
|
|
4099
3757
|
if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
4100
3758
|
return Number.isFinite(value) || typeof value !== "number";
|
|
4101
3759
|
}
|
|
4102
3760
|
if (Array.isArray(value)) {
|
|
4103
|
-
return value.every(
|
|
3761
|
+
return value.every(isJsonValue2);
|
|
4104
3762
|
}
|
|
4105
3763
|
if (isObject(value)) {
|
|
4106
|
-
return Object.values(value).every((item) => item === void 0 ||
|
|
3764
|
+
return Object.values(value).every((item) => item === void 0 || isJsonValue2(item));
|
|
4107
3765
|
}
|
|
4108
3766
|
return false;
|
|
4109
3767
|
}
|
|
@@ -4187,12 +3845,12 @@ async function parseQuestionAnswerRequest(c) {
|
|
|
4187
3845
|
if ("custom" in answer && typeof answer.custom !== "boolean") {
|
|
4188
3846
|
return { error: errorResponse(c, 400, "bad_request", "custom must be a boolean") };
|
|
4189
3847
|
}
|
|
4190
|
-
answers.push({
|
|
3848
|
+
answers.push(compact({
|
|
4191
3849
|
questionId: answer.questionId.trim(),
|
|
4192
3850
|
answer: answer.answer.trim(),
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
});
|
|
3851
|
+
choice: typeof answer.choice === "string" ? answer.choice : void 0,
|
|
3852
|
+
custom: typeof answer.custom === "boolean" ? answer.custom : void 0
|
|
3853
|
+
}));
|
|
4196
3854
|
}
|
|
4197
3855
|
return { answers };
|
|
4198
3856
|
}
|
|
@@ -4210,13 +3868,13 @@ function createQuestionRuntime() {
|
|
|
4210
3868
|
if ("error" in prompts) {
|
|
4211
3869
|
return control.skip(prompts.error);
|
|
4212
3870
|
}
|
|
4213
|
-
const answers = await requestQuestion(questions, context, {
|
|
3871
|
+
const answers = await requestQuestion(questions, context, compact({
|
|
4214
3872
|
toolName,
|
|
4215
|
-
|
|
3873
|
+
toolCallId,
|
|
4216
3874
|
internalCallId,
|
|
4217
3875
|
args,
|
|
4218
3876
|
questions: prompts.questions
|
|
4219
|
-
});
|
|
3877
|
+
}));
|
|
4220
3878
|
return control.skip(JSON.stringify({ answers }));
|
|
4221
3879
|
}
|
|
4222
3880
|
});
|
|
@@ -4260,18 +3918,20 @@ function createQuestionRuntime() {
|
|
|
4260
3918
|
async function requestQuestion(questions, context, request) {
|
|
4261
3919
|
const id = globalThis.crypto.randomUUID();
|
|
4262
3920
|
const question = {
|
|
4263
|
-
|
|
4264
|
-
|
|
4265
|
-
|
|
4266
|
-
|
|
4267
|
-
|
|
4268
|
-
|
|
4269
|
-
|
|
4270
|
-
|
|
4271
|
-
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
3921
|
+
...compact({
|
|
3922
|
+
id,
|
|
3923
|
+
runId: context.runId,
|
|
3924
|
+
agentId: context.agentId,
|
|
3925
|
+
sessionId: context.sessionId,
|
|
3926
|
+
toolName: request.toolName,
|
|
3927
|
+
callId: request.toolCallId,
|
|
3928
|
+
internalCallId: request.internalCallId,
|
|
3929
|
+
args: request.args,
|
|
3930
|
+
questions: request.questions,
|
|
3931
|
+
status: "pending",
|
|
3932
|
+
requestedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3933
|
+
emit: context.emit
|
|
3934
|
+
}),
|
|
4275
3935
|
resolve: () => {
|
|
4276
3936
|
}
|
|
4277
3937
|
};
|
|
@@ -4382,7 +4042,7 @@ function sessionCreatedLog(session) {
|
|
|
4382
4042
|
category: "session",
|
|
4383
4043
|
event: "session.created",
|
|
4384
4044
|
message: "Session created",
|
|
4385
|
-
metadata:
|
|
4045
|
+
metadata: compact({
|
|
4386
4046
|
agentId: session.agentId,
|
|
4387
4047
|
hasTitle: session.title !== void 0,
|
|
4388
4048
|
titleLength: session.title?.length ?? 0
|
|
@@ -4397,7 +4057,7 @@ function runReceivedLog(props) {
|
|
|
4397
4057
|
category: "api",
|
|
4398
4058
|
event: "run.received",
|
|
4399
4059
|
message: "Run request received",
|
|
4400
|
-
metadata:
|
|
4060
|
+
metadata: compact({
|
|
4401
4061
|
agentId: props.agentId,
|
|
4402
4062
|
stream: props.stream,
|
|
4403
4063
|
message: messageSummary(props.message),
|
|
@@ -4416,7 +4076,7 @@ function runStartedLog(session, runId) {
|
|
|
4416
4076
|
category: "run",
|
|
4417
4077
|
event: "run.started",
|
|
4418
4078
|
message: "Run started",
|
|
4419
|
-
metadata:
|
|
4079
|
+
metadata: compact({
|
|
4420
4080
|
agentId: session.agentId,
|
|
4421
4081
|
existingMessageCount: session.messageCount
|
|
4422
4082
|
})
|
|
@@ -4430,7 +4090,7 @@ function memoryLoadedLog(session, runId) {
|
|
|
4430
4090
|
category: "memory",
|
|
4431
4091
|
event: "memory.loaded",
|
|
4432
4092
|
message: "Session memory loaded",
|
|
4433
|
-
metadata:
|
|
4093
|
+
metadata: compact({
|
|
4434
4094
|
messageCount: session.messageCount,
|
|
4435
4095
|
transcriptEntries: session.transcript.length
|
|
4436
4096
|
})
|
|
@@ -4444,7 +4104,7 @@ function runCompletedLog(props) {
|
|
|
4444
4104
|
category: "run",
|
|
4445
4105
|
event: "run.completed",
|
|
4446
4106
|
message: "Run completed",
|
|
4447
|
-
metadata:
|
|
4107
|
+
metadata: compact({
|
|
4448
4108
|
durationMs: props.durationMs,
|
|
4449
4109
|
usage: usageSummary(props.usage),
|
|
4450
4110
|
outputBytes: byteLength3(props.output),
|
|
@@ -4460,7 +4120,7 @@ function memorySavedLog(props) {
|
|
|
4460
4120
|
category: "memory",
|
|
4461
4121
|
event: "memory.saved",
|
|
4462
4122
|
message: "Session memory saved",
|
|
4463
|
-
metadata:
|
|
4123
|
+
metadata: compact({
|
|
4464
4124
|
messageCount: props.messageCount
|
|
4465
4125
|
})
|
|
4466
4126
|
};
|
|
@@ -4473,7 +4133,7 @@ function runFailedLog(sessionId, runId, error, startedAt) {
|
|
|
4473
4133
|
category: "run",
|
|
4474
4134
|
event: "run.failed",
|
|
4475
4135
|
message: "Run failed",
|
|
4476
|
-
metadata:
|
|
4136
|
+
metadata: compact({
|
|
4477
4137
|
durationMs: Date.now() - startedAt,
|
|
4478
4138
|
error: serializeError(error)
|
|
4479
4139
|
})
|
|
@@ -4490,7 +4150,7 @@ function logsFromStreamEvent(props) {
|
|
|
4490
4150
|
category: "prompt",
|
|
4491
4151
|
event: "prompt.prepared",
|
|
4492
4152
|
message: `Turn ${event.turn} prompt prepared`,
|
|
4493
|
-
metadata:
|
|
4153
|
+
metadata: compact({
|
|
4494
4154
|
turn: event.turn,
|
|
4495
4155
|
prompt: messageSummary(event.prompt),
|
|
4496
4156
|
historyCount: event.history.length
|
|
@@ -4507,11 +4167,11 @@ function logsFromStreamEvent(props) {
|
|
|
4507
4167
|
category: "tool",
|
|
4508
4168
|
event: "tool.called",
|
|
4509
4169
|
message: `Tool ${event.toolCall.function.name} called`,
|
|
4510
|
-
metadata:
|
|
4170
|
+
metadata: compact({
|
|
4511
4171
|
turn: event.turn,
|
|
4512
4172
|
toolName: event.toolCall.function.name,
|
|
4513
4173
|
callId: event.toolCall.callId ?? event.toolCall.id,
|
|
4514
|
-
argumentBytes: byteLength3(
|
|
4174
|
+
argumentBytes: byteLength3(formatUnknown(event.toolCall.function.arguments))
|
|
4515
4175
|
})
|
|
4516
4176
|
}
|
|
4517
4177
|
];
|
|
@@ -4525,7 +4185,7 @@ function logsFromStreamEvent(props) {
|
|
|
4525
4185
|
category: "tool",
|
|
4526
4186
|
event: "tool.completed",
|
|
4527
4187
|
message: `Tool ${event.toolName} completed`,
|
|
4528
|
-
metadata:
|
|
4188
|
+
metadata: compact({
|
|
4529
4189
|
turn: event.turn,
|
|
4530
4190
|
toolName: event.toolName,
|
|
4531
4191
|
callId: event.toolCallId,
|
|
@@ -4546,7 +4206,7 @@ function logsFromStreamEvent(props) {
|
|
|
4546
4206
|
category: "model",
|
|
4547
4207
|
event: "model.turn.completed",
|
|
4548
4208
|
message: `Model turn ${event.turn} completed`,
|
|
4549
|
-
metadata:
|
|
4209
|
+
metadata: compact({
|
|
4550
4210
|
turn: event.turn,
|
|
4551
4211
|
contentCount: event.response.choice.length,
|
|
4552
4212
|
usage: usageSummary(event.response.usage)
|
|
@@ -4579,7 +4239,7 @@ function logsFromStreamEvent(props) {
|
|
|
4579
4239
|
category: "approval",
|
|
4580
4240
|
event: "approval.requested",
|
|
4581
4241
|
message: `Approval requested for ${event.approval.toolName}`,
|
|
4582
|
-
metadata:
|
|
4242
|
+
metadata: compact({
|
|
4583
4243
|
approvalId: event.approval.id,
|
|
4584
4244
|
toolName: event.approval.toolName,
|
|
4585
4245
|
callId: event.approval.callId,
|
|
@@ -4590,411 +4250,715 @@ function logsFromStreamEvent(props) {
|
|
|
4590
4250
|
}
|
|
4591
4251
|
];
|
|
4592
4252
|
}
|
|
4593
|
-
if (event.type === "tool_approval_result") {
|
|
4594
|
-
return [
|
|
4595
|
-
{
|
|
4596
|
-
sessionId,
|
|
4597
|
-
runId,
|
|
4598
|
-
level: event.approval.status === "approved" ? "info" : "warn",
|
|
4599
|
-
category: "approval",
|
|
4600
|
-
event: "approval.resolved",
|
|
4601
|
-
message: `Approval ${event.approval.status} for ${event.approval.toolName}`,
|
|
4602
|
-
metadata:
|
|
4603
|
-
approvalId: event.approval.id,
|
|
4604
|
-
toolName: event.approval.toolName,
|
|
4605
|
-
callId: event.approval.callId,
|
|
4606
|
-
status: event.approval.status,
|
|
4607
|
-
hasReason: event.approval.reason !== void 0
|
|
4608
|
-
})
|
|
4609
|
-
}
|
|
4610
|
-
];
|
|
4253
|
+
if (event.type === "tool_approval_result") {
|
|
4254
|
+
return [
|
|
4255
|
+
{
|
|
4256
|
+
sessionId,
|
|
4257
|
+
runId,
|
|
4258
|
+
level: event.approval.status === "approved" ? "info" : "warn",
|
|
4259
|
+
category: "approval",
|
|
4260
|
+
event: "approval.resolved",
|
|
4261
|
+
message: `Approval ${event.approval.status} for ${event.approval.toolName}`,
|
|
4262
|
+
metadata: compact({
|
|
4263
|
+
approvalId: event.approval.id,
|
|
4264
|
+
toolName: event.approval.toolName,
|
|
4265
|
+
callId: event.approval.callId,
|
|
4266
|
+
status: event.approval.status,
|
|
4267
|
+
hasReason: event.approval.reason !== void 0
|
|
4268
|
+
})
|
|
4269
|
+
}
|
|
4270
|
+
];
|
|
4271
|
+
}
|
|
4272
|
+
if (event.type === "tool_question_request") {
|
|
4273
|
+
return [
|
|
4274
|
+
{
|
|
4275
|
+
sessionId,
|
|
4276
|
+
runId,
|
|
4277
|
+
level: "info",
|
|
4278
|
+
category: "question",
|
|
4279
|
+
event: "question.requested",
|
|
4280
|
+
message: `Question requested by ${event.question.toolName}`,
|
|
4281
|
+
metadata: compact({
|
|
4282
|
+
questionId: event.question.id,
|
|
4283
|
+
toolName: event.question.toolName,
|
|
4284
|
+
callId: event.question.callId,
|
|
4285
|
+
status: event.question.status,
|
|
4286
|
+
questionCount: event.question.questions.length,
|
|
4287
|
+
argumentBytes: byteLength3(event.question.args)
|
|
4288
|
+
})
|
|
4289
|
+
}
|
|
4290
|
+
];
|
|
4291
|
+
}
|
|
4292
|
+
if (event.type === "tool_question_result") {
|
|
4293
|
+
return [
|
|
4294
|
+
{
|
|
4295
|
+
sessionId,
|
|
4296
|
+
runId,
|
|
4297
|
+
level: "info",
|
|
4298
|
+
category: "question",
|
|
4299
|
+
event: "question.answered",
|
|
4300
|
+
message: `Question answered for ${event.question.toolName}`,
|
|
4301
|
+
metadata: compact({
|
|
4302
|
+
questionId: event.question.id,
|
|
4303
|
+
toolName: event.question.toolName,
|
|
4304
|
+
callId: event.question.callId,
|
|
4305
|
+
status: event.question.status,
|
|
4306
|
+
answerCount: event.question.answers?.length ?? 0
|
|
4307
|
+
})
|
|
4308
|
+
}
|
|
4309
|
+
];
|
|
4310
|
+
}
|
|
4311
|
+
if (event.type === "agent_tool_event") {
|
|
4312
|
+
return childAgentLog(event, sessionId, runId);
|
|
4313
|
+
}
|
|
4314
|
+
return [];
|
|
4315
|
+
}
|
|
4316
|
+
async function* emitLog(store, input) {
|
|
4317
|
+
const log = await appendSessionLog(store, input);
|
|
4318
|
+
if (log !== void 0) {
|
|
4319
|
+
yield { type: "session_log", log };
|
|
4320
|
+
}
|
|
4321
|
+
}
|
|
4322
|
+
function childAgentLog(event, sessionId, runId) {
|
|
4323
|
+
const child = event.event;
|
|
4324
|
+
if (child.type === "tool_call") {
|
|
4325
|
+
return [
|
|
4326
|
+
{
|
|
4327
|
+
sessionId,
|
|
4328
|
+
runId,
|
|
4329
|
+
level: "debug",
|
|
4330
|
+
category: "tool",
|
|
4331
|
+
event: "child_tool.called",
|
|
4332
|
+
message: `Child agent ${event.agentName ?? event.agentId} called ${child.toolCall.function.name}`,
|
|
4333
|
+
metadata: compact({
|
|
4334
|
+
parentToolName: event.toolName,
|
|
4335
|
+
agentId: event.agentId,
|
|
4336
|
+
hasAgentName: event.agentName !== void 0,
|
|
4337
|
+
turn: event.turn,
|
|
4338
|
+
childTurn: child.turn,
|
|
4339
|
+
toolName: child.toolCall.function.name,
|
|
4340
|
+
callId: child.toolCall.callId ?? child.toolCall.id,
|
|
4341
|
+
argumentBytes: byteLength3(formatUnknown(child.toolCall.function.arguments))
|
|
4342
|
+
})
|
|
4343
|
+
}
|
|
4344
|
+
];
|
|
4345
|
+
}
|
|
4346
|
+
if (child.type === "tool_result") {
|
|
4347
|
+
return [
|
|
4348
|
+
{
|
|
4349
|
+
sessionId,
|
|
4350
|
+
runId,
|
|
4351
|
+
level: "debug",
|
|
4352
|
+
category: "tool",
|
|
4353
|
+
event: "child_tool.completed",
|
|
4354
|
+
message: `Child agent ${event.agentName ?? event.agentId} completed ${child.toolName}`,
|
|
4355
|
+
metadata: compact({
|
|
4356
|
+
parentToolName: event.toolName,
|
|
4357
|
+
agentId: event.agentId,
|
|
4358
|
+
hasAgentName: event.agentName !== void 0,
|
|
4359
|
+
turn: event.turn,
|
|
4360
|
+
childTurn: child.turn,
|
|
4361
|
+
toolName: child.toolName,
|
|
4362
|
+
callId: child.toolCallId,
|
|
4363
|
+
resultBytes: byteLength3(child.result),
|
|
4364
|
+
structuredResultBytes: child.structuredResult === void 0 ? void 0 : byteLength3(JSON.stringify(child.structuredResult))
|
|
4365
|
+
})
|
|
4366
|
+
}
|
|
4367
|
+
];
|
|
4368
|
+
}
|
|
4369
|
+
if (child.type === "turn_start") {
|
|
4370
|
+
return [
|
|
4371
|
+
{
|
|
4372
|
+
sessionId,
|
|
4373
|
+
runId,
|
|
4374
|
+
level: "debug",
|
|
4375
|
+
category: "run",
|
|
4376
|
+
event: "child_agent.turn_started",
|
|
4377
|
+
message: `Child agent ${event.agentName ?? event.agentId} turn ${child.turn} started`,
|
|
4378
|
+
metadata: compact({
|
|
4379
|
+
parentToolName: event.toolName,
|
|
4380
|
+
agentId: event.agentId,
|
|
4381
|
+
hasAgentName: event.agentName !== void 0,
|
|
4382
|
+
childTurn: child.turn,
|
|
4383
|
+
historyCount: child.history.length
|
|
4384
|
+
})
|
|
4385
|
+
}
|
|
4386
|
+
];
|
|
4387
|
+
}
|
|
4388
|
+
if (child.type === "final") {
|
|
4389
|
+
return [
|
|
4390
|
+
{
|
|
4391
|
+
sessionId,
|
|
4392
|
+
runId,
|
|
4393
|
+
level: "debug",
|
|
4394
|
+
category: "run",
|
|
4395
|
+
event: "child_agent.completed",
|
|
4396
|
+
message: `Child agent ${event.agentName ?? event.agentId} completed`,
|
|
4397
|
+
metadata: compact({
|
|
4398
|
+
parentToolName: event.toolName,
|
|
4399
|
+
agentId: event.agentId,
|
|
4400
|
+
hasAgentName: event.agentName !== void 0,
|
|
4401
|
+
usage: usageSummary(child.usage),
|
|
4402
|
+
outputBytes: byteLength3(child.output),
|
|
4403
|
+
messageCount: child.messages.length
|
|
4404
|
+
})
|
|
4405
|
+
}
|
|
4406
|
+
];
|
|
4407
|
+
}
|
|
4408
|
+
if (child.type === "error") {
|
|
4409
|
+
return [
|
|
4410
|
+
{
|
|
4411
|
+
sessionId,
|
|
4412
|
+
runId,
|
|
4413
|
+
level: "error",
|
|
4414
|
+
category: "run",
|
|
4415
|
+
event: "child_agent.failed",
|
|
4416
|
+
message: `Child agent ${event.agentName ?? event.agentId} failed`,
|
|
4417
|
+
metadata: compact({
|
|
4418
|
+
parentToolName: event.toolName,
|
|
4419
|
+
agentId: event.agentId,
|
|
4420
|
+
hasAgentName: event.agentName !== void 0,
|
|
4421
|
+
error: serializeError(child.error)
|
|
4422
|
+
})
|
|
4423
|
+
}
|
|
4424
|
+
];
|
|
4425
|
+
}
|
|
4426
|
+
return [];
|
|
4427
|
+
}
|
|
4428
|
+
function messageSummary(message) {
|
|
4429
|
+
if (typeof message === "string") {
|
|
4430
|
+
return {
|
|
4431
|
+
role: "user",
|
|
4432
|
+
contentKind: "text",
|
|
4433
|
+
byteLength: byteLength3(message)
|
|
4434
|
+
};
|
|
4435
|
+
}
|
|
4436
|
+
return {
|
|
4437
|
+
role: message.role,
|
|
4438
|
+
contentKind: Array.isArray(message.content) ? "parts" : "text",
|
|
4439
|
+
partCount: Array.isArray(message.content) ? message.content.length : 1,
|
|
4440
|
+
byteLength: byteLength3(formatUnknown(message.content))
|
|
4441
|
+
};
|
|
4442
|
+
}
|
|
4443
|
+
function usageSummary(value) {
|
|
4444
|
+
if (value === void 0 || value === null || typeof value !== "object") {
|
|
4445
|
+
return void 0;
|
|
4446
|
+
}
|
|
4447
|
+
const record = value;
|
|
4448
|
+
return compact({
|
|
4449
|
+
inputTokens: numericValue(record.inputTokens),
|
|
4450
|
+
outputTokens: numericValue(record.outputTokens),
|
|
4451
|
+
totalTokens: numericValue(record.totalTokens),
|
|
4452
|
+
cachedInputTokens: numericValue(record.cachedInputTokens),
|
|
4453
|
+
cacheCreationInputTokens: numericValue(record.cacheCreationInputTokens)
|
|
4454
|
+
});
|
|
4455
|
+
}
|
|
4456
|
+
function numericValue(value) {
|
|
4457
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
4458
|
+
}
|
|
4459
|
+
function byteLength3(value) {
|
|
4460
|
+
return value === void 0 ? 0 : new TextEncoder().encode(value).byteLength;
|
|
4461
|
+
}
|
|
4462
|
+
|
|
4463
|
+
// src/runtime/sessions.ts
|
|
4464
|
+
function registerSessionRoutes(app, props) {
|
|
4465
|
+
app.get("/sessions", async (c) => {
|
|
4466
|
+
const agentId = optionalQueryString(c.req.query("agentId"));
|
|
4467
|
+
if (agentId !== void 0 && !props.agentMap.has(agentId)) {
|
|
4468
|
+
return errorResponse(c, 404, "not_found", "Agent not found");
|
|
4469
|
+
}
|
|
4470
|
+
const limit = parseLimit(c.req.query("limit"));
|
|
4471
|
+
if (limit === void 0) {
|
|
4472
|
+
return errorResponse(c, 400, "bad_request", "limit must be a positive integer");
|
|
4473
|
+
}
|
|
4474
|
+
const sessions = await props.sessionStore.listSessions({
|
|
4475
|
+
...compact({ agentId }),
|
|
4476
|
+
limit
|
|
4477
|
+
});
|
|
4478
|
+
return c.json({ sessions });
|
|
4479
|
+
});
|
|
4480
|
+
app.post("/sessions", async (c) => {
|
|
4481
|
+
const body = await parseCreateSessionRequest(c);
|
|
4482
|
+
if ("error" in body) {
|
|
4483
|
+
return body.error;
|
|
4484
|
+
}
|
|
4485
|
+
if (!props.agentMap.has(body.agentId)) {
|
|
4486
|
+
return errorResponse(c, 404, "not_found", "Agent not found");
|
|
4487
|
+
}
|
|
4488
|
+
const session = await props.sessionStore.createSession({
|
|
4489
|
+
id: globalThis.crypto.randomUUID(),
|
|
4490
|
+
agentId: body.agentId,
|
|
4491
|
+
...compact({ title: body.title, metadata: body.metadata })
|
|
4492
|
+
});
|
|
4493
|
+
await appendSessionLog(props.sessionStore, sessionCreatedLog(session));
|
|
4494
|
+
return c.json(session, 201);
|
|
4495
|
+
});
|
|
4496
|
+
app.get("/sessions/:sessionId", async (c) => {
|
|
4497
|
+
const session = await props.sessionStore.getSession(c.req.param("sessionId"));
|
|
4498
|
+
if (session === void 0) {
|
|
4499
|
+
return errorResponse(c, 404, "not_found", "Session not found");
|
|
4500
|
+
}
|
|
4501
|
+
return c.json(session);
|
|
4502
|
+
});
|
|
4503
|
+
app.get("/sessions/:sessionId/logs", async (c) => {
|
|
4504
|
+
const sessionId = c.req.param("sessionId");
|
|
4505
|
+
const session = await props.sessionStore.getSession(sessionId);
|
|
4506
|
+
if (session === void 0) {
|
|
4507
|
+
return errorResponse(c, 404, "not_found", "Session not found");
|
|
4508
|
+
}
|
|
4509
|
+
if (props.sessionStore.listSessionLogs === void 0) {
|
|
4510
|
+
return errorResponse(
|
|
4511
|
+
c,
|
|
4512
|
+
501,
|
|
4513
|
+
"unsupported_capability",
|
|
4514
|
+
'Capability "sessions.logs" is not implemented by this runner',
|
|
4515
|
+
{ capability: "sessions", operation: "logs" }
|
|
4516
|
+
);
|
|
4517
|
+
}
|
|
4518
|
+
const limit = parseLimit(c.req.query("limit"), 200, 1e3);
|
|
4519
|
+
if (limit === void 0) {
|
|
4520
|
+
return errorResponse(c, 400, "bad_request", "limit must be a positive integer");
|
|
4521
|
+
}
|
|
4522
|
+
const after = parseAfter(c.req.query("after"));
|
|
4523
|
+
if (after === false) {
|
|
4524
|
+
return errorResponse(c, 400, "bad_request", "after must be a non-negative integer");
|
|
4525
|
+
}
|
|
4526
|
+
const logs = await props.sessionStore.listSessionLogs({
|
|
4527
|
+
sessionId,
|
|
4528
|
+
limit,
|
|
4529
|
+
...compact({ after })
|
|
4530
|
+
});
|
|
4531
|
+
const last = logs.at(-1);
|
|
4532
|
+
return c.json({
|
|
4533
|
+
logs,
|
|
4534
|
+
...logs.length === limit && last !== void 0 ? { nextCursor: last.sequence } : {}
|
|
4535
|
+
});
|
|
4536
|
+
});
|
|
4537
|
+
app.delete("/sessions/:sessionId", async (c) => {
|
|
4538
|
+
if (props.sessionStore.deleteSession === void 0) {
|
|
4539
|
+
return errorResponse(
|
|
4540
|
+
c,
|
|
4541
|
+
501,
|
|
4542
|
+
"unsupported_capability",
|
|
4543
|
+
'Capability "sessions.delete" is not implemented by this runner',
|
|
4544
|
+
{ capability: "sessions", operation: "delete" }
|
|
4545
|
+
);
|
|
4546
|
+
}
|
|
4547
|
+
const deleted = await props.sessionStore.deleteSession(c.req.param("sessionId"));
|
|
4548
|
+
if (!deleted) {
|
|
4549
|
+
return errorResponse(c, 404, "not_found", "Session not found");
|
|
4550
|
+
}
|
|
4551
|
+
return c.body(null, 204);
|
|
4552
|
+
});
|
|
4553
|
+
app.get("/sessions/:sessionId/traces", async (c) => {
|
|
4554
|
+
if (props.traceStore === void 0) {
|
|
4555
|
+
return unsupportedCapability(c, "traces");
|
|
4556
|
+
}
|
|
4557
|
+
const sessionId = c.req.param("sessionId");
|
|
4558
|
+
const session = await props.sessionStore.getSession(sessionId);
|
|
4559
|
+
if (session === void 0) {
|
|
4560
|
+
return errorResponse(c, 404, "not_found", "Session not found");
|
|
4561
|
+
}
|
|
4562
|
+
const limit = parseLimit(c.req.query("limit"));
|
|
4563
|
+
if (limit === void 0) {
|
|
4564
|
+
return errorResponse(c, 400, "bad_request", "limit must be a positive integer");
|
|
4565
|
+
}
|
|
4566
|
+
const traces = await props.traceStore.listSessionTraces({ sessionId, limit });
|
|
4567
|
+
return c.json({ traces });
|
|
4568
|
+
});
|
|
4569
|
+
}
|
|
4570
|
+
async function parseCreateSessionRequest(c) {
|
|
4571
|
+
let body;
|
|
4572
|
+
try {
|
|
4573
|
+
body = await c.req.json();
|
|
4574
|
+
} catch {
|
|
4575
|
+
return { error: errorResponse(c, 400, "bad_request", "Request body must be JSON") };
|
|
4576
|
+
}
|
|
4577
|
+
if (!isObject(body)) {
|
|
4578
|
+
return { error: errorResponse(c, 400, "bad_request", "Request body must be an object") };
|
|
4579
|
+
}
|
|
4580
|
+
if (typeof body.agentId !== "string" || body.agentId.trim().length === 0) {
|
|
4581
|
+
return { error: errorResponse(c, 400, "bad_request", "agentId must be a string") };
|
|
4582
|
+
}
|
|
4583
|
+
const request = {
|
|
4584
|
+
agentId: body.agentId.trim()
|
|
4585
|
+
};
|
|
4586
|
+
if ("title" in body) {
|
|
4587
|
+
if (typeof body.title !== "string") {
|
|
4588
|
+
return { error: errorResponse(c, 400, "bad_request", "title must be a string") };
|
|
4589
|
+
}
|
|
4590
|
+
const title = body.title.trim();
|
|
4591
|
+
if (title.length > 0) {
|
|
4592
|
+
request.title = title;
|
|
4593
|
+
}
|
|
4594
|
+
}
|
|
4595
|
+
if ("metadata" in body) {
|
|
4596
|
+
if (!isJsonObject(body.metadata)) {
|
|
4597
|
+
return { error: errorResponse(c, 400, "bad_request", "metadata must be an object") };
|
|
4598
|
+
}
|
|
4599
|
+
request.metadata = body.metadata;
|
|
4600
|
+
}
|
|
4601
|
+
return request;
|
|
4602
|
+
}
|
|
4603
|
+
|
|
4604
|
+
// src/storage/memory-store.ts
|
|
4605
|
+
function createInMemoryStudioStore() {
|
|
4606
|
+
return new InMemoryStudioStore();
|
|
4607
|
+
}
|
|
4608
|
+
var InMemoryStudioStore = class {
|
|
4609
|
+
kind = "memory";
|
|
4610
|
+
sessions = /* @__PURE__ */ new Map();
|
|
4611
|
+
traces = /* @__PURE__ */ new Map();
|
|
4612
|
+
pipelineLogs = /* @__PURE__ */ new Map();
|
|
4613
|
+
pipelineRuns = /* @__PURE__ */ new Map();
|
|
4614
|
+
listSessions(options) {
|
|
4615
|
+
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);
|
|
4616
|
+
}
|
|
4617
|
+
createSession(input) {
|
|
4618
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
4619
|
+
const session = {
|
|
4620
|
+
...compact({
|
|
4621
|
+
id: input.id,
|
|
4622
|
+
agentId: input.agentId,
|
|
4623
|
+
title: input.title,
|
|
4624
|
+
createdAt: now,
|
|
4625
|
+
updatedAt: now,
|
|
4626
|
+
messageCount: 0,
|
|
4627
|
+
metadata: input.metadata
|
|
4628
|
+
}),
|
|
4629
|
+
messages: [],
|
|
4630
|
+
runs: [],
|
|
4631
|
+
logs: []
|
|
4632
|
+
};
|
|
4633
|
+
this.sessions.set(input.id, session);
|
|
4634
|
+
return sessionSummary(session);
|
|
4635
|
+
}
|
|
4636
|
+
getSession(id) {
|
|
4637
|
+
const session = this.sessions.get(id);
|
|
4638
|
+
return session === void 0 ? void 0 : materializeSession(session);
|
|
4639
|
+
}
|
|
4640
|
+
updateSessionMetadata(id, metadata) {
|
|
4641
|
+
const session = this.sessions.get(id);
|
|
4642
|
+
if (session === void 0) {
|
|
4643
|
+
return void 0;
|
|
4644
|
+
}
|
|
4645
|
+
if (metadata === void 0) {
|
|
4646
|
+
delete session.metadata;
|
|
4647
|
+
} else {
|
|
4648
|
+
session.metadata = metadata;
|
|
4649
|
+
}
|
|
4650
|
+
session.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
4651
|
+
return materializeSession(session);
|
|
4652
|
+
}
|
|
4653
|
+
load(context) {
|
|
4654
|
+
return Promise.resolve(this.sessions.get(context.sessionId)?.messages ?? []);
|
|
4655
|
+
}
|
|
4656
|
+
append(input) {
|
|
4657
|
+
const session = this.sessions.get(input.context.sessionId);
|
|
4658
|
+
if (session !== void 0) {
|
|
4659
|
+
session.messages.push(...input.messages);
|
|
4660
|
+
session.messageCount = session.messages.length;
|
|
4661
|
+
session.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
4662
|
+
}
|
|
4663
|
+
return Promise.resolve();
|
|
4664
|
+
}
|
|
4665
|
+
clear(context) {
|
|
4666
|
+
const session = this.sessions.get(context.sessionId);
|
|
4667
|
+
if (session !== void 0) {
|
|
4668
|
+
session.messages = [];
|
|
4669
|
+
session.runs = [];
|
|
4670
|
+
session.messageCount = 0;
|
|
4671
|
+
session.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
4672
|
+
}
|
|
4673
|
+
return Promise.resolve();
|
|
4674
|
+
}
|
|
4675
|
+
async recordError(input) {
|
|
4676
|
+
await this.saveSessionRunTranscript({
|
|
4677
|
+
id: input.context.sessionId,
|
|
4678
|
+
runId: studioRunId(input.context) ?? input.runId,
|
|
4679
|
+
transcript: transcriptFromMessages(input.messages),
|
|
4680
|
+
status: "error",
|
|
4681
|
+
error: serializeJsonError(input.error)
|
|
4682
|
+
});
|
|
4683
|
+
}
|
|
4684
|
+
saveSessionRunTranscript(input) {
|
|
4685
|
+
const session = this.sessions.get(input.id);
|
|
4686
|
+
if (session === void 0) {
|
|
4687
|
+
return void 0;
|
|
4688
|
+
}
|
|
4689
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
4690
|
+
const existingIndex = session.runs.findIndex((run2) => run2.runId === input.runId);
|
|
4691
|
+
const run = {
|
|
4692
|
+
...input,
|
|
4693
|
+
transcript: renumberTranscript(input.transcript),
|
|
4694
|
+
createdAt: existingIndex === -1 ? now : session.runs[existingIndex]?.createdAt ?? now,
|
|
4695
|
+
updatedAt: now
|
|
4696
|
+
};
|
|
4697
|
+
if (existingIndex === -1) {
|
|
4698
|
+
session.runs.push(run);
|
|
4699
|
+
} else {
|
|
4700
|
+
session.runs[existingIndex] = run;
|
|
4701
|
+
}
|
|
4702
|
+
session.updatedAt = now;
|
|
4703
|
+
return materializeSession(session);
|
|
4704
|
+
}
|
|
4705
|
+
appendSessionLog(input) {
|
|
4706
|
+
const session = this.sessions.get(input.sessionId);
|
|
4707
|
+
const logs = session?.logs ?? [];
|
|
4708
|
+
const entry = compact({
|
|
4709
|
+
id: globalThis.crypto.randomUUID(),
|
|
4710
|
+
sessionId: input.sessionId,
|
|
4711
|
+
runId: input.runId,
|
|
4712
|
+
sequence: logs.length,
|
|
4713
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4714
|
+
level: input.level,
|
|
4715
|
+
category: input.category,
|
|
4716
|
+
event: input.event,
|
|
4717
|
+
message: input.message,
|
|
4718
|
+
metadata: input.metadata
|
|
4719
|
+
});
|
|
4720
|
+
if (session !== void 0) {
|
|
4721
|
+
session.logs.push(entry);
|
|
4722
|
+
session.updatedAt = entry.timestamp;
|
|
4723
|
+
}
|
|
4724
|
+
return entry;
|
|
4725
|
+
}
|
|
4726
|
+
listSessionLogs(options) {
|
|
4727
|
+
return (this.sessions.get(options.sessionId)?.logs ?? []).filter((log) => options.after === void 0 || log.sequence > options.after).slice(0, options.limit);
|
|
4611
4728
|
}
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
{
|
|
4615
|
-
|
|
4616
|
-
runId,
|
|
4617
|
-
level: "info",
|
|
4618
|
-
category: "question",
|
|
4619
|
-
event: "question.requested",
|
|
4620
|
-
message: `Question requested by ${event.question.toolName}`,
|
|
4621
|
-
metadata: cleanMetadata2({
|
|
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
|
-
})
|
|
4729
|
+
deleteSession(id) {
|
|
4730
|
+
for (const trace of this.traces.values()) {
|
|
4731
|
+
if (trace.sessionId === id) {
|
|
4732
|
+
this.traces.delete(trace.id);
|
|
4629
4733
|
}
|
|
4630
|
-
|
|
4734
|
+
}
|
|
4735
|
+
return this.sessions.delete(id);
|
|
4631
4736
|
}
|
|
4632
|
-
|
|
4633
|
-
return [
|
|
4634
|
-
{
|
|
4635
|
-
sessionId,
|
|
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
|
-
})
|
|
4648
|
-
}
|
|
4649
|
-
];
|
|
4737
|
+
listTraces(options) {
|
|
4738
|
+
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);
|
|
4650
4739
|
}
|
|
4651
|
-
|
|
4652
|
-
return
|
|
4740
|
+
listSessionTraces(options) {
|
|
4741
|
+
return this.listTraces({ sessionId: options.sessionId, limit: options.limit });
|
|
4653
4742
|
}
|
|
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 };
|
|
4743
|
+
getTrace(id) {
|
|
4744
|
+
return this.traces.get(id);
|
|
4660
4745
|
}
|
|
4661
|
-
|
|
4662
|
-
|
|
4663
|
-
|
|
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
|
-
];
|
|
4746
|
+
saveTrace(trace) {
|
|
4747
|
+
this.traces.set(trace.id, trace);
|
|
4748
|
+
return trace;
|
|
4685
4749
|
}
|
|
4686
|
-
|
|
4687
|
-
|
|
4688
|
-
|
|
4689
|
-
|
|
4690
|
-
|
|
4691
|
-
|
|
4692
|
-
|
|
4693
|
-
|
|
4694
|
-
|
|
4695
|
-
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
|
|
4699
|
-
|
|
4700
|
-
|
|
4701
|
-
|
|
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
|
-
];
|
|
4750
|
+
appendPipelineLog(input) {
|
|
4751
|
+
const logs = this.pipelineLogs.get(input.pipelineId) ?? [];
|
|
4752
|
+
const entry = compact({
|
|
4753
|
+
id: globalThis.crypto.randomUUID(),
|
|
4754
|
+
pipelineId: input.pipelineId,
|
|
4755
|
+
runId: input.runId,
|
|
4756
|
+
sequence: logs.length,
|
|
4757
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4758
|
+
level: input.level,
|
|
4759
|
+
category: input.category,
|
|
4760
|
+
event: input.event,
|
|
4761
|
+
message: input.message,
|
|
4762
|
+
metadata: input.metadata
|
|
4763
|
+
});
|
|
4764
|
+
this.pipelineLogs.set(input.pipelineId, [...logs, entry]);
|
|
4765
|
+
return entry;
|
|
4708
4766
|
}
|
|
4709
|
-
|
|
4710
|
-
return [
|
|
4711
|
-
{
|
|
4712
|
-
sessionId,
|
|
4713
|
-
runId,
|
|
4714
|
-
level: "debug",
|
|
4715
|
-
category: "run",
|
|
4716
|
-
event: "child_agent.turn_started",
|
|
4717
|
-
message: `Child agent ${event.agentName ?? event.agentId} turn ${child.turn} started`,
|
|
4718
|
-
metadata: cleanMetadata2({
|
|
4719
|
-
parentToolName: event.toolName,
|
|
4720
|
-
agentId: event.agentId,
|
|
4721
|
-
hasAgentName: event.agentName !== void 0,
|
|
4722
|
-
childTurn: child.turn,
|
|
4723
|
-
historyCount: child.history.length
|
|
4724
|
-
})
|
|
4725
|
-
}
|
|
4726
|
-
];
|
|
4767
|
+
listPipelineLogs(options) {
|
|
4768
|
+
return (this.pipelineLogs.get(options.pipelineId) ?? []).filter((log) => options.after === void 0 || log.sequence > options.after).slice(0, options.limit);
|
|
4727
4769
|
}
|
|
4728
|
-
|
|
4729
|
-
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
|
|
4734
|
-
|
|
4735
|
-
|
|
4736
|
-
|
|
4737
|
-
|
|
4738
|
-
|
|
4739
|
-
|
|
4740
|
-
|
|
4741
|
-
|
|
4742
|
-
|
|
4743
|
-
messageCount: child.messages.length
|
|
4744
|
-
})
|
|
4745
|
-
}
|
|
4746
|
-
];
|
|
4770
|
+
savePipelineRun(input) {
|
|
4771
|
+
const record = compact({
|
|
4772
|
+
runId: input.runId,
|
|
4773
|
+
pipelineId: input.pipelineId,
|
|
4774
|
+
status: input.status,
|
|
4775
|
+
input: input.input,
|
|
4776
|
+
output: input.output,
|
|
4777
|
+
error: input.error,
|
|
4778
|
+
metadata: input.metadata,
|
|
4779
|
+
startedAt: input.startedAt,
|
|
4780
|
+
endedAt: input.endedAt,
|
|
4781
|
+
durationMs: input.durationMs
|
|
4782
|
+
});
|
|
4783
|
+
this.pipelineRuns.set(input.runId, record);
|
|
4784
|
+
return record;
|
|
4747
4785
|
}
|
|
4748
|
-
|
|
4749
|
-
|
|
4750
|
-
|
|
4751
|
-
sessionId,
|
|
4752
|
-
runId,
|
|
4753
|
-
level: "error",
|
|
4754
|
-
category: "run",
|
|
4755
|
-
event: "child_agent.failed",
|
|
4756
|
-
message: `Child agent ${event.agentName ?? event.agentId} failed`,
|
|
4757
|
-
metadata: cleanMetadata2({
|
|
4758
|
-
parentToolName: event.toolName,
|
|
4759
|
-
agentId: event.agentId,
|
|
4760
|
-
hasAgentName: event.agentName !== void 0,
|
|
4761
|
-
error: serializeError(child.error)
|
|
4762
|
-
})
|
|
4763
|
-
}
|
|
4764
|
-
];
|
|
4786
|
+
getPipelineRun(options) {
|
|
4787
|
+
const run = this.pipelineRuns.get(options.runId);
|
|
4788
|
+
return run?.pipelineId === options.pipelineId ? run : void 0;
|
|
4765
4789
|
}
|
|
4766
|
-
|
|
4767
|
-
|
|
4768
|
-
function messageSummary(message) {
|
|
4769
|
-
if (typeof message === "string") {
|
|
4770
|
-
return {
|
|
4771
|
-
role: "user",
|
|
4772
|
-
contentKind: "text",
|
|
4773
|
-
byteLength: byteLength3(message)
|
|
4774
|
-
};
|
|
4790
|
+
listPipelineRuns(options) {
|
|
4791
|
+
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
4792
|
}
|
|
4793
|
+
};
|
|
4794
|
+
function sessionSummary(session) {
|
|
4795
|
+
return compact({
|
|
4796
|
+
id: session.id,
|
|
4797
|
+
agentId: session.agentId,
|
|
4798
|
+
title: session.title,
|
|
4799
|
+
createdAt: session.createdAt,
|
|
4800
|
+
updatedAt: session.updatedAt,
|
|
4801
|
+
messageCount: session.messages.length,
|
|
4802
|
+
metadata: session.metadata
|
|
4803
|
+
});
|
|
4804
|
+
}
|
|
4805
|
+
function materializeSession(session) {
|
|
4776
4806
|
return {
|
|
4777
|
-
|
|
4778
|
-
|
|
4779
|
-
|
|
4780
|
-
byteLength: byteLength3(formatUnknown2(message.content))
|
|
4807
|
+
...sessionSummary(session),
|
|
4808
|
+
messages: [...session.messages],
|
|
4809
|
+
transcript: renumberTranscript(session.runs.flatMap((run) => run.transcript))
|
|
4781
4810
|
};
|
|
4782
4811
|
}
|
|
4783
|
-
function
|
|
4784
|
-
|
|
4785
|
-
|
|
4786
|
-
|
|
4787
|
-
|
|
4788
|
-
|
|
4789
|
-
|
|
4790
|
-
|
|
4791
|
-
|
|
4792
|
-
|
|
4793
|
-
|
|
4812
|
+
function traceSummary2(trace) {
|
|
4813
|
+
return compact({
|
|
4814
|
+
id: trace.id,
|
|
4815
|
+
sessionId: trace.sessionId,
|
|
4816
|
+
name: trace.name,
|
|
4817
|
+
status: trace.status,
|
|
4818
|
+
startedAt: trace.startedAt,
|
|
4819
|
+
endedAt: trace.endedAt,
|
|
4820
|
+
durationMs: trace.durationMs,
|
|
4821
|
+
output: trace.output,
|
|
4822
|
+
error: trace.error,
|
|
4823
|
+
usage: trace.usage,
|
|
4824
|
+
metadata: trace.metadata,
|
|
4825
|
+
observationCount: trace.observations.length
|
|
4794
4826
|
});
|
|
4795
4827
|
}
|
|
4796
|
-
function
|
|
4797
|
-
const
|
|
4798
|
-
|
|
4799
|
-
|
|
4800
|
-
|
|
4801
|
-
|
|
4802
|
-
|
|
4803
|
-
|
|
4804
|
-
|
|
4805
|
-
|
|
4828
|
+
function traceAgentId(trace) {
|
|
4829
|
+
const nestedMetadata = trace.metadata?.metadata;
|
|
4830
|
+
return isJsonObject2(nestedMetadata) && typeof nestedMetadata.agentId === "string" ? nestedMetadata.agentId : void 0;
|
|
4831
|
+
}
|
|
4832
|
+
function studioRunId(context) {
|
|
4833
|
+
const value = context.metadata?.studioRunId;
|
|
4834
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
4835
|
+
}
|
|
4836
|
+
function serializeJsonError(error) {
|
|
4837
|
+
if (error instanceof Error) {
|
|
4838
|
+
return {
|
|
4839
|
+
name: error.name,
|
|
4840
|
+
message: error.message
|
|
4841
|
+
};
|
|
4806
4842
|
}
|
|
4807
|
-
return
|
|
4843
|
+
return isJsonValue3(error) ? error : String(error);
|
|
4844
|
+
}
|
|
4845
|
+
function isJsonObject2(value) {
|
|
4846
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4808
4847
|
}
|
|
4809
|
-
function
|
|
4848
|
+
function isJsonValue3(value) {
|
|
4810
4849
|
if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
4811
|
-
return
|
|
4850
|
+
return true;
|
|
4812
4851
|
}
|
|
4813
4852
|
if (Array.isArray(value)) {
|
|
4814
|
-
return value.
|
|
4815
|
-
}
|
|
4816
|
-
if (typeof value === "object" && value !== null) {
|
|
4817
|
-
return cleanMetadata2(value);
|
|
4853
|
+
return value.every(isJsonValue3);
|
|
4818
4854
|
}
|
|
4819
|
-
return
|
|
4855
|
+
return isJsonObject2(value) && Object.values(value).every(isJsonValue3);
|
|
4820
4856
|
}
|
|
4821
|
-
|
|
4822
|
-
|
|
4857
|
+
|
|
4858
|
+
// src/runtime/shared.ts
|
|
4859
|
+
function resolveStores(options) {
|
|
4860
|
+
const defaultStore = defaultStudioStore();
|
|
4861
|
+
const sessions = resolveSessionStore(options, defaultStore);
|
|
4862
|
+
const traces = resolveTraceStore(options, sessions, defaultStore);
|
|
4863
|
+
const pipelineLogs = resolvePipelineLogStore(options, sessions, defaultStore);
|
|
4864
|
+
const pipelineRuns = resolvePipelineRunStore(options, sessions, pipelineLogs, defaultStore);
|
|
4865
|
+
return compact({
|
|
4866
|
+
sessions,
|
|
4867
|
+
traces,
|
|
4868
|
+
pipelineLogs,
|
|
4869
|
+
pipelineRuns
|
|
4870
|
+
});
|
|
4823
4871
|
}
|
|
4824
|
-
function
|
|
4825
|
-
return
|
|
4872
|
+
function defaultStudioStore() {
|
|
4873
|
+
return createInMemoryStudioStore();
|
|
4826
4874
|
}
|
|
4827
|
-
function
|
|
4828
|
-
if (
|
|
4829
|
-
return
|
|
4875
|
+
function resolveSessionStore(options, defaultStore) {
|
|
4876
|
+
if (options.stores?.sessions === false) {
|
|
4877
|
+
return void 0;
|
|
4830
4878
|
}
|
|
4831
|
-
|
|
4832
|
-
return
|
|
4833
|
-
} catch {
|
|
4834
|
-
return String(value);
|
|
4879
|
+
if (options.stores?.sessions !== void 0) {
|
|
4880
|
+
return options.stores.sessions;
|
|
4835
4881
|
}
|
|
4882
|
+
return defaultStore;
|
|
4836
4883
|
}
|
|
4837
|
-
|
|
4838
|
-
|
|
4839
|
-
|
|
4840
|
-
app.get("/sessions", async (c) => {
|
|
4841
|
-
const agentId = optionalQueryString(c.req.query("agentId"));
|
|
4842
|
-
if (agentId !== void 0 && !props.agentMap.has(agentId)) {
|
|
4843
|
-
return errorResponse(c, 404, "not_found", "Agent not found");
|
|
4844
|
-
}
|
|
4845
|
-
const limit = parseLimit(c.req.query("limit"));
|
|
4846
|
-
if (limit === void 0) {
|
|
4847
|
-
return errorResponse(c, 400, "bad_request", "limit must be a positive integer");
|
|
4848
|
-
}
|
|
4849
|
-
const sessions = await props.sessionStore.listSessions({
|
|
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 });
|
|
4944
|
-
});
|
|
4945
|
-
}
|
|
4946
|
-
function parseSessionLogLimit(value) {
|
|
4947
|
-
if (value === void 0 || value.trim().length === 0) {
|
|
4948
|
-
return 200;
|
|
4884
|
+
function resolveTraceStore(options, sessionStore, defaultStore) {
|
|
4885
|
+
if (options.stores?.traces !== void 0) {
|
|
4886
|
+
return options.stores.traces;
|
|
4949
4887
|
}
|
|
4950
|
-
|
|
4951
|
-
if (!Number.isInteger(limit) || limit <= 0) {
|
|
4888
|
+
if (sessionStore === void 0) {
|
|
4952
4889
|
return void 0;
|
|
4953
4890
|
}
|
|
4954
|
-
|
|
4891
|
+
if (isTraceStore(sessionStore)) {
|
|
4892
|
+
return sessionStore;
|
|
4893
|
+
}
|
|
4894
|
+
return defaultStore;
|
|
4955
4895
|
}
|
|
4956
|
-
function
|
|
4957
|
-
if (
|
|
4896
|
+
function resolvePipelineLogStore(options, sessionStore, defaultStore) {
|
|
4897
|
+
if (options.stores?.pipelineLogs === false) {
|
|
4958
4898
|
return void 0;
|
|
4959
4899
|
}
|
|
4960
|
-
|
|
4961
|
-
|
|
4962
|
-
return false;
|
|
4900
|
+
if (options.stores?.pipelineLogs !== void 0) {
|
|
4901
|
+
return options.stores.pipelineLogs;
|
|
4963
4902
|
}
|
|
4964
|
-
|
|
4903
|
+
if (sessionStore !== void 0 && isPipelineLogStore(sessionStore)) {
|
|
4904
|
+
return sessionStore;
|
|
4905
|
+
}
|
|
4906
|
+
return defaultStore;
|
|
4965
4907
|
}
|
|
4966
|
-
|
|
4967
|
-
|
|
4968
|
-
|
|
4969
|
-
body = await c.req.json();
|
|
4970
|
-
} catch {
|
|
4971
|
-
return { error: errorResponse(c, 400, "bad_request", "Request body must be JSON") };
|
|
4908
|
+
function resolvePipelineRunStore(options, sessionStore, pipelineLogStore, defaultStore) {
|
|
4909
|
+
if (options.stores?.pipelineRuns === false) {
|
|
4910
|
+
return void 0;
|
|
4972
4911
|
}
|
|
4973
|
-
if (
|
|
4974
|
-
return
|
|
4912
|
+
if (options.stores?.pipelineRuns !== void 0) {
|
|
4913
|
+
return options.stores.pipelineRuns;
|
|
4975
4914
|
}
|
|
4976
|
-
if (
|
|
4977
|
-
return
|
|
4915
|
+
if (sessionStore !== void 0 && isPipelineRunStore(sessionStore)) {
|
|
4916
|
+
return sessionStore;
|
|
4978
4917
|
}
|
|
4979
|
-
|
|
4980
|
-
|
|
4981
|
-
}
|
|
4982
|
-
|
|
4983
|
-
|
|
4984
|
-
|
|
4918
|
+
if (pipelineLogStore !== void 0 && isPipelineRunStore(pipelineLogStore)) {
|
|
4919
|
+
return pipelineLogStore;
|
|
4920
|
+
}
|
|
4921
|
+
return defaultStore;
|
|
4922
|
+
}
|
|
4923
|
+
function isTraceStore(store) {
|
|
4924
|
+
const candidate = store;
|
|
4925
|
+
return typeof candidate.listSessionTraces === "function" && typeof candidate.getTrace === "function" && typeof candidate.saveTrace === "function";
|
|
4926
|
+
}
|
|
4927
|
+
function isPipelineLogStore(store) {
|
|
4928
|
+
const candidate = store;
|
|
4929
|
+
return typeof candidate.appendPipelineLog === "function" && typeof candidate.listPipelineLogs === "function";
|
|
4930
|
+
}
|
|
4931
|
+
function isPipelineRunStore(store) {
|
|
4932
|
+
const candidate = store;
|
|
4933
|
+
return typeof candidate.savePipelineRun === "function" && typeof candidate.getPipelineRun === "function" && typeof candidate.listPipelineRuns === "function";
|
|
4934
|
+
}
|
|
4935
|
+
function normalizeAgents(agents) {
|
|
4936
|
+
const ids = /* @__PURE__ */ new Set();
|
|
4937
|
+
return agents.map((agent) => {
|
|
4938
|
+
const id = agent.id.trim();
|
|
4939
|
+
if (id.length === 0) {
|
|
4940
|
+
throw new Error("Studio agent id cannot be empty");
|
|
4985
4941
|
}
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
request.title = title;
|
|
4942
|
+
if (ids.has(id)) {
|
|
4943
|
+
throw new Error(`Duplicate runner agent id: ${id}`);
|
|
4989
4944
|
}
|
|
4990
|
-
|
|
4991
|
-
|
|
4992
|
-
|
|
4993
|
-
|
|
4945
|
+
ids.add(id);
|
|
4946
|
+
return { ...agent, id };
|
|
4947
|
+
});
|
|
4948
|
+
}
|
|
4949
|
+
function normalizePipelines(pipelines) {
|
|
4950
|
+
const ids = /* @__PURE__ */ new Set();
|
|
4951
|
+
return pipelines.map((pipeline) => {
|
|
4952
|
+
const id = pipeline.id.trim();
|
|
4953
|
+
if (id.length === 0) {
|
|
4954
|
+
throw new Error("Studio pipeline id cannot be empty");
|
|
4994
4955
|
}
|
|
4995
|
-
|
|
4996
|
-
|
|
4997
|
-
|
|
4956
|
+
if (ids.has(id)) {
|
|
4957
|
+
throw new Error(`Duplicate Studio pipeline id: ${id}`);
|
|
4958
|
+
}
|
|
4959
|
+
ids.add(id);
|
|
4960
|
+
return { ...pipeline, id };
|
|
4961
|
+
});
|
|
4998
4962
|
}
|
|
4999
4963
|
|
|
5000
4964
|
// src/runtime/status.ts
|
|
@@ -5003,30 +4967,31 @@ function registerStatusRoutes(app, props) {
|
|
|
5003
4967
|
const summary = {
|
|
5004
4968
|
runner: {
|
|
5005
4969
|
id: runnerId(props.options),
|
|
5006
|
-
...props.options.name
|
|
5007
|
-
...props.options.version === void 0 ? {} : { version: props.options.version }
|
|
4970
|
+
...compact({ name: props.options.name, version: props.options.version })
|
|
5008
4971
|
},
|
|
5009
4972
|
storage: {
|
|
5010
|
-
...
|
|
5011
|
-
|
|
5012
|
-
|
|
5013
|
-
|
|
4973
|
+
...compact({
|
|
4974
|
+
sessions: props.stores.sessions?.kind,
|
|
4975
|
+
traces: props.stores.traces?.kind,
|
|
4976
|
+
pipelineLogs: props.stores.pipelineLogs !== void 0 ? "available" : void 0,
|
|
4977
|
+
pipelineRuns: props.stores.pipelineRuns !== void 0 ? "available" : void 0
|
|
4978
|
+
})
|
|
5014
4979
|
},
|
|
5015
4980
|
counts: {
|
|
5016
4981
|
agents: props.agents.length,
|
|
5017
4982
|
pipelines: props.pipelines.length,
|
|
5018
|
-
...
|
|
5019
|
-
|
|
5020
|
-
|
|
5021
|
-
pipelineRuns: (await Promise.all(
|
|
4983
|
+
...compact({
|
|
4984
|
+
sessions: props.stores.sessions !== void 0 ? (await props.stores.sessions.listSessions({ limit: 100 })).length : void 0,
|
|
4985
|
+
traces: props.stores.traces?.listTraces !== void 0 ? (await props.stores.traces.listTraces({ limit: 100 })).length : void 0,
|
|
4986
|
+
pipelineRuns: props.stores.pipelineRuns !== void 0 && props.pipelines.length > 0 ? (await Promise.all(
|
|
5022
4987
|
props.pipelines.map(
|
|
5023
4988
|
(pipeline) => props.stores.pipelineRuns?.listPipelineRuns({
|
|
5024
4989
|
pipelineId: pipeline.id,
|
|
5025
4990
|
limit: 100
|
|
5026
4991
|
})
|
|
5027
4992
|
)
|
|
5028
|
-
)).reduce((sum, runs) => sum + (runs?.length ?? 0), 0)
|
|
5029
|
-
}
|
|
4993
|
+
)).reduce((sum, runs) => sum + (runs?.length ?? 0), 0) : void 0
|
|
4994
|
+
})
|
|
5030
4995
|
},
|
|
5031
4996
|
capabilities: capabilityConfig(props.options, props.agents, props.pipelines, props.stores),
|
|
5032
4997
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -5110,16 +5075,16 @@ async function parseToolRunRequest(c) {
|
|
|
5110
5075
|
if (body === void 0 || body === null) {
|
|
5111
5076
|
return { args: {} };
|
|
5112
5077
|
}
|
|
5113
|
-
if (!
|
|
5078
|
+
if (!isJsonObject(body)) {
|
|
5114
5079
|
return { error: errorResponse(c, 400, "bad_request", "Request body must be an object") };
|
|
5115
5080
|
}
|
|
5116
5081
|
const args = Object.hasOwn(body, "args") ? body.args : {};
|
|
5117
|
-
if (!
|
|
5082
|
+
if (!isJsonValue(args)) {
|
|
5118
5083
|
return { error: errorResponse(c, 400, "bad_request", "args must be JSON-compatible") };
|
|
5119
5084
|
}
|
|
5120
5085
|
const request = { args };
|
|
5121
5086
|
if (Object.hasOwn(body, "context")) {
|
|
5122
|
-
if (!
|
|
5087
|
+
if (!isJsonObject(body.context)) {
|
|
5123
5088
|
return { error: errorResponse(c, 400, "bad_request", "context must be an object") };
|
|
5124
5089
|
}
|
|
5125
5090
|
request.context = body.context;
|
|
@@ -5177,9 +5142,7 @@ function registerTraceRoutes(app, traceStore) {
|
|
|
5177
5142
|
const sessionId = optionalQueryString(c.req.query("sessionId"));
|
|
5178
5143
|
const traces = await traceStore.listTraces({
|
|
5179
5144
|
limit,
|
|
5180
|
-
...
|
|
5181
|
-
...sessionId === void 0 ? {} : { sessionId },
|
|
5182
|
-
...status === void 0 ? {} : { status }
|
|
5145
|
+
...compact({ agentId, sessionId, status })
|
|
5183
5146
|
});
|
|
5184
5147
|
return c.json({ traces });
|
|
5185
5148
|
});
|
|
@@ -5222,7 +5185,7 @@ var Studio = class {
|
|
|
5222
5185
|
const port = serveOptions.port ?? Number(process.env.RUNNER_PORT ?? 4021);
|
|
5223
5186
|
this.server = serve({
|
|
5224
5187
|
fetch: (request) => this.fetch(request),
|
|
5225
|
-
...
|
|
5188
|
+
...compact({ hostname: serveOptions.hostname }),
|
|
5226
5189
|
port
|
|
5227
5190
|
});
|
|
5228
5191
|
const log = serveOptions.log ?? true;
|
|
@@ -5262,9 +5225,9 @@ function studioOptionsFromTargets(targets, options) {
|
|
|
5262
5225
|
agents: inferStudioAgents(agents, options.quickPrompts ?? {}),
|
|
5263
5226
|
pipelines: inferStudioPipelines(pipelines),
|
|
5264
5227
|
evals: options.evals ?? [],
|
|
5265
|
-
...
|
|
5266
|
-
...
|
|
5267
|
-
...
|
|
5228
|
+
...compact({ models: options.models }),
|
|
5229
|
+
...compact({ stores: options.stores }),
|
|
5230
|
+
...compact({ ui: options.ui })
|
|
5268
5231
|
};
|
|
5269
5232
|
}
|
|
5270
5233
|
function inferStudioAgents(agents, quickPrompts) {
|
|
@@ -5286,9 +5249,9 @@ function inferStudioPipelines(pipelines) {
|
|
|
5286
5249
|
return {
|
|
5287
5250
|
id,
|
|
5288
5251
|
pipeline,
|
|
5289
|
-
...
|
|
5290
|
-
...
|
|
5291
|
-
...
|
|
5252
|
+
...compact({ name: pipeline.name }),
|
|
5253
|
+
...compact({ description: pipeline.description }),
|
|
5254
|
+
...compact({ metadata: pipeline.metadata })
|
|
5292
5255
|
};
|
|
5293
5256
|
});
|
|
5294
5257
|
}
|
|
@@ -5304,7 +5267,7 @@ function uniqueAgentId(baseId, ids) {
|
|
|
5304
5267
|
}
|
|
5305
5268
|
function agentMetadata(agent) {
|
|
5306
5269
|
return {
|
|
5307
|
-
...
|
|
5270
|
+
...compact({ defaultMaxTurns: agent.defaultMaxTurns }),
|
|
5308
5271
|
staticContextCount: agent.staticContext.length,
|
|
5309
5272
|
dynamicContextCount: agent.dynamicContexts.length,
|
|
5310
5273
|
dynamicToolCount: agent.dynamicTools.length,
|
|
@@ -5375,13 +5338,13 @@ function createStudioApp(options) {
|
|
|
5375
5338
|
});
|
|
5376
5339
|
registerKnowledgeRoutes(app, {
|
|
5377
5340
|
agents,
|
|
5378
|
-
...
|
|
5341
|
+
...compact({ traceStore: stores.traces })
|
|
5379
5342
|
});
|
|
5380
5343
|
registerPipelineRoutes(app, {
|
|
5381
5344
|
pipelines,
|
|
5382
5345
|
pipelineMap,
|
|
5383
|
-
...
|
|
5384
|
-
...
|
|
5346
|
+
...compact({ logStore: stores.pipelineLogs }),
|
|
5347
|
+
...compact({ runStore: stores.pipelineRuns })
|
|
5385
5348
|
});
|
|
5386
5349
|
app.post("/agents/:agentId/runs", async (c) => {
|
|
5387
5350
|
const agentId = c.req.param("agentId");
|
|
@@ -5428,8 +5391,8 @@ function createStudioApp(options) {
|
|
|
5428
5391
|
agentId,
|
|
5429
5392
|
message: body.message,
|
|
5430
5393
|
stream: body.stream === true,
|
|
5431
|
-
...
|
|
5432
|
-
...
|
|
5394
|
+
...compact({ maxTurns: body.maxTurns }),
|
|
5395
|
+
...compact({ toolConcurrency: body.toolConcurrency }),
|
|
5433
5396
|
hasTrace: body.trace !== void 0,
|
|
5434
5397
|
...body.metadata === void 0 && selectedModel.ref === void 0 ? {} : {
|
|
5435
5398
|
metadata: {
|
|
@@ -5498,8 +5461,8 @@ function createStudioApp(options) {
|
|
|
5498
5461
|
approvalRuntime.createHook({
|
|
5499
5462
|
runId,
|
|
5500
5463
|
agentId,
|
|
5501
|
-
...
|
|
5502
|
-
...
|
|
5464
|
+
...compact({ sessionId: session?.id }),
|
|
5465
|
+
...compact({ metadata: body.metadata }),
|
|
5503
5466
|
getTool: (toolName) => runAgent.getTool(toolName),
|
|
5504
5467
|
emit: (event) => runtimeEvents.push(event)
|
|
5505
5468
|
})
|
|
@@ -5507,8 +5470,8 @@ function createStudioApp(options) {
|
|
|
5507
5470
|
questionRuntime.createHook({
|
|
5508
5471
|
runId,
|
|
5509
5472
|
agentId,
|
|
5510
|
-
...
|
|
5511
|
-
...
|
|
5473
|
+
...compact({ sessionId: session?.id }),
|
|
5474
|
+
...compact({ metadata: body.metadata }),
|
|
5512
5475
|
emit: (event) => runtimeEvents.push(event)
|
|
5513
5476
|
})
|
|
5514
5477
|
);
|
|
@@ -5543,16 +5506,16 @@ function createStudioApp(options) {
|
|
|
5543
5506
|
approvalRuntime.createHook({
|
|
5544
5507
|
runId,
|
|
5545
5508
|
agentId,
|
|
5546
|
-
...
|
|
5547
|
-
...
|
|
5509
|
+
...compact({ sessionId: session?.id }),
|
|
5510
|
+
...compact({ metadata: body.metadata }),
|
|
5548
5511
|
getTool: (toolName) => runAgent.getTool(toolName)
|
|
5549
5512
|
})
|
|
5550
5513
|
),
|
|
5551
5514
|
questionRuntime.createHook({
|
|
5552
5515
|
runId,
|
|
5553
5516
|
agentId,
|
|
5554
|
-
...
|
|
5555
|
-
...
|
|
5517
|
+
...compact({ sessionId: session?.id }),
|
|
5518
|
+
...compact({ metadata: body.metadata })
|
|
5556
5519
|
})
|
|
5557
5520
|
);
|
|
5558
5521
|
if (effectiveHook !== void 0) {
|
|
@@ -5625,7 +5588,7 @@ function createStudioApp(options) {
|
|
|
5625
5588
|
registerSessionRoutes(app, {
|
|
5626
5589
|
agentMap,
|
|
5627
5590
|
sessionStore: stores.sessions,
|
|
5628
|
-
...
|
|
5591
|
+
...compact({ traceStore: stores.traces })
|
|
5629
5592
|
});
|
|
5630
5593
|
}
|
|
5631
5594
|
if (stores.traces !== void 0) {
|
|
@@ -5645,8 +5608,8 @@ function createStudioApp(options) {
|
|
|
5645
5608
|
},
|
|
5646
5609
|
close() {
|
|
5647
5610
|
},
|
|
5648
|
-
...
|
|
5649
|
-
...
|
|
5611
|
+
...compact({ sessionStore: stores.sessions }),
|
|
5612
|
+
...compact({ traceStore: stores.traces })
|
|
5650
5613
|
};
|
|
5651
5614
|
}
|
|
5652
5615
|
function normalizePromptMessage(message) {
|
|
@@ -5790,11 +5753,11 @@ var SqliteSessionStore = class {
|
|
|
5790
5753
|
return {
|
|
5791
5754
|
id: input.id,
|
|
5792
5755
|
agentId: input.agentId,
|
|
5793
|
-
...
|
|
5756
|
+
...compact({ title: input.title }),
|
|
5794
5757
|
createdAt: now,
|
|
5795
5758
|
updatedAt: now,
|
|
5796
5759
|
messageCount: 0,
|
|
5797
|
-
...
|
|
5760
|
+
...compact({ metadata: input.metadata })
|
|
5798
5761
|
};
|
|
5799
5762
|
}
|
|
5800
5763
|
getSession(id) {
|
|
@@ -5980,14 +5943,14 @@ var SqliteSessionStore = class {
|
|
|
5980
5943
|
const entry = {
|
|
5981
5944
|
id: globalThis.crypto.randomUUID(),
|
|
5982
5945
|
sessionId: input.sessionId,
|
|
5983
|
-
...
|
|
5946
|
+
...compact({ runId: input.runId }),
|
|
5984
5947
|
sequence,
|
|
5985
5948
|
timestamp: now,
|
|
5986
5949
|
level: input.level,
|
|
5987
5950
|
category: input.category,
|
|
5988
5951
|
event: input.event,
|
|
5989
5952
|
message: input.message,
|
|
5990
|
-
...
|
|
5953
|
+
...compact({ metadata: input.metadata })
|
|
5991
5954
|
};
|
|
5992
5955
|
db.prepare(
|
|
5993
5956
|
`INSERT INTO anvia_studio_session_logs (
|
|
@@ -6061,14 +6024,14 @@ var SqliteSessionStore = class {
|
|
|
6061
6024
|
const entry = {
|
|
6062
6025
|
id: globalThis.crypto.randomUUID(),
|
|
6063
6026
|
pipelineId: input.pipelineId,
|
|
6064
|
-
...
|
|
6027
|
+
...compact({ runId: input.runId }),
|
|
6065
6028
|
sequence,
|
|
6066
6029
|
timestamp: now,
|
|
6067
6030
|
level: input.level,
|
|
6068
6031
|
category: input.category,
|
|
6069
6032
|
event: input.event,
|
|
6070
6033
|
message: input.message,
|
|
6071
|
-
...
|
|
6034
|
+
...compact({ metadata: input.metadata })
|
|
6072
6035
|
};
|
|
6073
6036
|
db.prepare(
|
|
6074
6037
|
`INSERT INTO anvia_studio_pipeline_logs (
|
|
@@ -6186,12 +6149,12 @@ var SqliteSessionStore = class {
|
|
|
6186
6149
|
pipelineId: input.pipelineId,
|
|
6187
6150
|
status: input.status,
|
|
6188
6151
|
input: input.input,
|
|
6189
|
-
...
|
|
6190
|
-
...
|
|
6191
|
-
...
|
|
6152
|
+
...compact({ output: input.output }),
|
|
6153
|
+
...compact({ error: input.error }),
|
|
6154
|
+
...compact({ metadata: input.metadata }),
|
|
6192
6155
|
startedAt: input.startedAt,
|
|
6193
|
-
...
|
|
6194
|
-
...
|
|
6156
|
+
...compact({ endedAt: input.endedAt }),
|
|
6157
|
+
...compact({ durationMs: input.durationMs })
|
|
6195
6158
|
};
|
|
6196
6159
|
}
|
|
6197
6160
|
getPipelineRun(options) {
|
|
@@ -6622,11 +6585,11 @@ function toSessionSummary(row) {
|
|
|
6622
6585
|
return {
|
|
6623
6586
|
id: row.id,
|
|
6624
6587
|
agentId: row.agent_id,
|
|
6625
|
-
...
|
|
6588
|
+
...compact({ title: row.title ?? void 0 }),
|
|
6626
6589
|
createdAt: row.created_at,
|
|
6627
6590
|
updatedAt: row.updated_at,
|
|
6628
6591
|
messageCount: row.message_count,
|
|
6629
|
-
...
|
|
6592
|
+
...compact({ metadata })
|
|
6630
6593
|
};
|
|
6631
6594
|
}
|
|
6632
6595
|
function toSessionLog(row) {
|
|
@@ -6634,14 +6597,14 @@ function toSessionLog(row) {
|
|
|
6634
6597
|
return {
|
|
6635
6598
|
id: row.id,
|
|
6636
6599
|
sessionId: row.session_id,
|
|
6637
|
-
...
|
|
6600
|
+
...compact({ runId: row.run_id ?? void 0 }),
|
|
6638
6601
|
sequence: row.sequence,
|
|
6639
6602
|
timestamp: row.timestamp,
|
|
6640
6603
|
level: row.level,
|
|
6641
6604
|
category: row.category,
|
|
6642
6605
|
event: row.event,
|
|
6643
6606
|
message: row.message,
|
|
6644
|
-
...
|
|
6607
|
+
...compact({ metadata })
|
|
6645
6608
|
};
|
|
6646
6609
|
}
|
|
6647
6610
|
function toPipelineLog(row) {
|
|
@@ -6649,14 +6612,14 @@ function toPipelineLog(row) {
|
|
|
6649
6612
|
return {
|
|
6650
6613
|
id: row.id,
|
|
6651
6614
|
pipelineId: row.pipeline_id,
|
|
6652
|
-
...
|
|
6615
|
+
...compact({ runId: row.run_id ?? void 0 }),
|
|
6653
6616
|
sequence: row.sequence,
|
|
6654
6617
|
timestamp: row.timestamp,
|
|
6655
6618
|
level: row.level,
|
|
6656
6619
|
category: row.category,
|
|
6657
6620
|
event: row.event,
|
|
6658
6621
|
message: row.message,
|
|
6659
|
-
...
|
|
6622
|
+
...compact({ metadata })
|
|
6660
6623
|
};
|
|
6661
6624
|
}
|
|
6662
6625
|
function toPipelineRun(row) {
|
|
@@ -6668,12 +6631,12 @@ function toPipelineRun(row) {
|
|
|
6668
6631
|
pipelineId: row.pipeline_id,
|
|
6669
6632
|
status: row.status,
|
|
6670
6633
|
input: JSON.parse(row.input_json),
|
|
6671
|
-
...
|
|
6672
|
-
...
|
|
6673
|
-
...
|
|
6634
|
+
...compact({ output }),
|
|
6635
|
+
...compact({ error }),
|
|
6636
|
+
...compact({ metadata }),
|
|
6674
6637
|
startedAt: row.started_at,
|
|
6675
|
-
...
|
|
6676
|
-
...
|
|
6638
|
+
...compact({ endedAt: row.ended_at ?? void 0 }),
|
|
6639
|
+
...compact({ durationMs: row.duration_ms ?? void 0 })
|
|
6677
6640
|
};
|
|
6678
6641
|
}
|
|
6679
6642
|
function messageParts(message) {
|
|
@@ -6699,7 +6662,7 @@ function messageFromRows(row, partRows) {
|
|
|
6699
6662
|
if (row.role === "assistant") {
|
|
6700
6663
|
return {
|
|
6701
6664
|
role: "assistant",
|
|
6702
|
-
...
|
|
6665
|
+
...compact({ id: row.message_id ?? void 0 }),
|
|
6703
6666
|
content: parts
|
|
6704
6667
|
};
|
|
6705
6668
|
}
|
|
@@ -6747,8 +6710,8 @@ function toTrace(row) {
|
|
|
6747
6710
|
const input = parseJsonValue(row.input_json);
|
|
6748
6711
|
return {
|
|
6749
6712
|
...toTraceSummary(row),
|
|
6750
|
-
...
|
|
6751
|
-
...
|
|
6713
|
+
...compact({ trace }),
|
|
6714
|
+
...compact({ input }),
|
|
6752
6715
|
observations: parseJsonArray(row.observations_json)
|
|
6753
6716
|
};
|
|
6754
6717
|
}
|
|
@@ -6760,15 +6723,15 @@ function toTraceSummary(row) {
|
|
|
6760
6723
|
return {
|
|
6761
6724
|
id: row.id,
|
|
6762
6725
|
sessionId: row.session_id,
|
|
6763
|
-
...
|
|
6726
|
+
...compact({ name: row.name ?? void 0 }),
|
|
6764
6727
|
status: row.status,
|
|
6765
6728
|
startedAt: row.started_at,
|
|
6766
|
-
...
|
|
6767
|
-
...
|
|
6768
|
-
...
|
|
6769
|
-
...
|
|
6770
|
-
...
|
|
6771
|
-
...
|
|
6729
|
+
...compact({ endedAt: row.ended_at ?? void 0 }),
|
|
6730
|
+
...compact({ durationMs: row.duration_ms ?? void 0 }),
|
|
6731
|
+
...compact({ output: row.output ?? void 0 }),
|
|
6732
|
+
...compact({ error }),
|
|
6733
|
+
...compact({ usage }),
|
|
6734
|
+
...compact({ metadata }),
|
|
6772
6735
|
observationCount: observations.length
|
|
6773
6736
|
};
|
|
6774
6737
|
}
|
|
@@ -6798,10 +6761,29 @@ function serializeJsonError2(error) {
|
|
|
6798
6761
|
}
|
|
6799
6762
|
return String(error);
|
|
6800
6763
|
}
|
|
6764
|
+
|
|
6765
|
+
// src/types.ts
|
|
6766
|
+
function traceSummary3(trace) {
|
|
6767
|
+
return compact({
|
|
6768
|
+
id: trace.id,
|
|
6769
|
+
sessionId: trace.sessionId,
|
|
6770
|
+
name: trace.name,
|
|
6771
|
+
status: trace.status,
|
|
6772
|
+
startedAt: trace.startedAt,
|
|
6773
|
+
endedAt: trace.endedAt,
|
|
6774
|
+
durationMs: trace.durationMs,
|
|
6775
|
+
output: trace.output,
|
|
6776
|
+
error: trace.error,
|
|
6777
|
+
usage: trace.usage,
|
|
6778
|
+
metadata: trace.metadata,
|
|
6779
|
+
observationCount: trace.observations.length
|
|
6780
|
+
});
|
|
6781
|
+
}
|
|
6801
6782
|
export {
|
|
6802
6783
|
Studio,
|
|
6803
6784
|
StudioTraceObserver,
|
|
6804
6785
|
createInMemoryStudioStore,
|
|
6805
|
-
createSqliteSessionStore
|
|
6786
|
+
createSqliteSessionStore,
|
|
6787
|
+
traceSummary3 as traceSummary
|
|
6806
6788
|
};
|
|
6807
6789
|
//# sourceMappingURL=index.js.map
|