@anvia/studio 0.8.1 → 1.0.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -19
- package/dist/index.d.ts +37 -60
- package/dist/index.js +1000 -724
- package/dist/index.js.map +1 -1
- package/dist/ui/assets/{ArrowClockwise.es-CSN-gjxO.js → ArrowClockwise.es-DMJj7Hv0.js} +2 -2
- package/dist/ui/assets/{ArrowClockwise.es-CSN-gjxO.js.map → ArrowClockwise.es-DMJj7Hv0.js.map} +1 -1
- package/dist/ui/assets/{agents-page-CkNSbqAj.js → agents-page-CbQpO3Tg.js} +2 -2
- package/dist/ui/assets/agents-page-CbQpO3Tg.js.map +1 -0
- package/dist/ui/assets/{badge-RJJoRC4P.js → badge-BIWy1K8W.js} +1 -1
- package/dist/ui/assets/{badge-RJJoRC4P.js.map → badge-BIWy1K8W.js.map} +1 -1
- package/dist/ui/assets/index-DizotQot.js +119 -0
- package/dist/ui/assets/index-DizotQot.js.map +1 -0
- package/dist/ui/assets/{input-BOUv3rgO.js → input-BTHDDFpv.js} +1 -1
- package/dist/ui/assets/{input-BOUv3rgO.js.map → input-BTHDDFpv.js.map} +1 -1
- package/dist/ui/assets/{knowledge-page-Cot_uYcE.js → knowledge-page-C8zg8uTL.js} +2 -2
- package/dist/ui/assets/{knowledge-page-Cot_uYcE.js.map → knowledge-page-C8zg8uTL.js.map} +1 -1
- package/dist/ui/assets/{mcps-page-BSO6ork4.js → mcps-page-gNYeqSPB.js} +2 -2
- package/dist/ui/assets/{mcps-page-BSO6ork4.js.map → mcps-page-gNYeqSPB.js.map} +1 -1
- package/dist/ui/assets/{memory-page-CG84G--r.js → memory-page-BLrfOqyU.js} +4 -4
- package/dist/ui/assets/memory-page-BLrfOqyU.js.map +1 -0
- package/dist/ui/assets/pipelines-page-hTEhFZGg.js +8 -0
- package/dist/ui/assets/pipelines-page-hTEhFZGg.js.map +1 -0
- package/dist/ui/assets/{renderers-B8gvjR2u.js → renderers-DC_-TD_X.js} +3 -3
- package/dist/ui/assets/{renderers-B8gvjR2u.js.map → renderers-DC_-TD_X.js.map} +1 -1
- package/dist/ui/assets/{sandboxes-page-D910dyFO.js → sandboxes-page-DtPnuza7.js} +2 -2
- package/dist/ui/assets/{sandboxes-page-D910dyFO.js.map → sandboxes-page-DtPnuza7.js.map} +1 -1
- package/dist/ui/assets/{sessions-page-CSN2vSKZ.js → sessions-page-DBzoP7MV.js} +2 -2
- package/dist/ui/assets/{sessions-page-CSN2vSKZ.js.map → sessions-page-DBzoP7MV.js.map} +1 -1
- package/dist/ui/assets/{status-page-CgRNt0wi.js → status-page-Bf1lq444.js} +2 -2
- package/dist/ui/assets/{status-page-CgRNt0wi.js.map → status-page-Bf1lq444.js.map} +1 -1
- package/dist/ui/assets/tool-runner-BbUlfPEO.js +2 -0
- package/dist/ui/assets/{tool-runner-BZN-PZJU.js.map → tool-runner-BbUlfPEO.js.map} +1 -1
- package/dist/ui/assets/{tools-page-DRv7aklU.js → tools-page-BgUz-79v.js} +2 -2
- package/dist/ui/assets/{tools-page-DRv7aklU.js.map → tools-page-BgUz-79v.js.map} +1 -1
- package/dist/ui/assets/trace-browser-qfYPcdR2.js +10 -0
- package/dist/ui/assets/trace-browser-qfYPcdR2.js.map +1 -0
- package/dist/ui/assets/{transcript-item-ZNkQEaCw.js → transcript-item-HFuuqmKM.js} +3 -3
- package/dist/ui/assets/{transcript-item-ZNkQEaCw.js.map → transcript-item-HFuuqmKM.js.map} +1 -1
- package/dist/ui/index.html +1 -2
- package/package.json +12 -11
- package/dist/ui/assets/agents-page-CkNSbqAj.js.map +0 -1
- package/dist/ui/assets/chunk-ADH7NNCS-DM6fsnDI.js +0 -2
- package/dist/ui/assets/chunk-ADH7NNCS-DM6fsnDI.js.map +0 -1
- package/dist/ui/assets/index-Bh7RLPBw.js +0 -56
- package/dist/ui/assets/index-Bh7RLPBw.js.map +0 -1
- package/dist/ui/assets/memory-page-CG84G--r.js.map +0 -1
- package/dist/ui/assets/pipelines-page-Hbf5ffUH.js +0 -8
- package/dist/ui/assets/pipelines-page-Hbf5ffUH.js.map +0 -1
- package/dist/ui/assets/tool-runner-BZN-PZJU.js +0 -2
- package/dist/ui/assets/trace-browser-B07coNNE.js +0 -10
- package/dist/ui/assets/trace-browser-B07coNNE.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/runtime/studio.ts
|
|
2
|
-
import { Agent as
|
|
2
|
+
import { Agent, getAgentToolState as getAgentToolState3 } from "@anvia/core/internal/agent";
|
|
3
3
|
import { Pipeline } from "@anvia/core/pipeline";
|
|
4
4
|
import { serve } from "@hono/node-server";
|
|
5
5
|
import { Hono as HonoApp } from "hono";
|
|
@@ -178,7 +178,12 @@ var StudioRunTraceObserver = class {
|
|
|
178
178
|
async end(args) {
|
|
179
179
|
await this.save("success", {
|
|
180
180
|
endedAt: /* @__PURE__ */ new Date(),
|
|
181
|
-
output: args.output,
|
|
181
|
+
output: args.status === "completed" ? traceOutput(args.output) : args.text,
|
|
182
|
+
result: {
|
|
183
|
+
status: args.status,
|
|
184
|
+
text: args.text,
|
|
185
|
+
...args.status === "completed" ? { output: toJsonValue(args.output) } : { stage: args.stage }
|
|
186
|
+
},
|
|
182
187
|
usage: args.usage,
|
|
183
188
|
messages: toJsonValue(args.messages)
|
|
184
189
|
});
|
|
@@ -198,11 +203,13 @@ var StudioRunTraceObserver = class {
|
|
|
198
203
|
return;
|
|
199
204
|
}
|
|
200
205
|
const metadata = traceMetadata(this.props.args, result.messages);
|
|
206
|
+
if (result.result !== void 0) metadata.result = result.result;
|
|
201
207
|
const trace = {
|
|
202
208
|
id: this.props.id,
|
|
209
|
+
runId: this.props.args.runId,
|
|
203
210
|
sessionId,
|
|
204
211
|
status,
|
|
205
|
-
trace: this.trace,
|
|
212
|
+
trace: { observer: "studio", ...this.trace },
|
|
206
213
|
startedAt: this.startedAt.toISOString(),
|
|
207
214
|
endedAt: result.endedAt.toISOString(),
|
|
208
215
|
durationMs: durationMs(this.startedAt, result.endedAt),
|
|
@@ -281,15 +288,14 @@ var ChildAgentToolTraceAccumulator = class {
|
|
|
281
288
|
}
|
|
282
289
|
if (child.type === "tool_call" && isRecord(child.toolCall)) {
|
|
283
290
|
const toolCall = child.toolCall;
|
|
284
|
-
const
|
|
285
|
-
const
|
|
286
|
-
const callId = typeof toolCall.callId === "string" ? toolCall.callId : typeof toolCall.id === "string" ? toolCall.id : void 0;
|
|
291
|
+
const toolName = typeof toolCall.toolName === "string" ? toolCall.toolName : "tool";
|
|
292
|
+
const callId = typeof toolCall.toolCallId === "string" ? toolCall.toolCallId : typeof toolCall.callId === "string" ? toolCall.callId : void 0;
|
|
287
293
|
const start = {
|
|
288
294
|
startedAt: /* @__PURE__ */ new Date(),
|
|
289
295
|
agentId,
|
|
290
296
|
childTurn,
|
|
291
297
|
toolName,
|
|
292
|
-
input: toJsonValue(
|
|
298
|
+
input: toJsonValue("input" in toolCall ? toolCall.input : {}),
|
|
293
299
|
completed: false
|
|
294
300
|
};
|
|
295
301
|
if (agentName !== void 0) start.agentName = agentName;
|
|
@@ -427,6 +433,7 @@ function traceObservation(props) {
|
|
|
427
433
|
}
|
|
428
434
|
function traceMetadata(args, messages) {
|
|
429
435
|
return compactJsonObject({
|
|
436
|
+
runId: args.runId,
|
|
430
437
|
agentName: args.agentName,
|
|
431
438
|
agentDescription: args.agentDescription,
|
|
432
439
|
maxTurns: args.maxTurns,
|
|
@@ -441,14 +448,12 @@ function generationMetadata(args, endArgs) {
|
|
|
441
448
|
const request = args.request;
|
|
442
449
|
const response = endArgs?.response;
|
|
443
450
|
const rawResponse = isRecord(response?.rawResponse) ? response.rawResponse : void 0;
|
|
444
|
-
const
|
|
451
|
+
const modelId = args.modelInfo?.modelId ?? stringValue(rawResponse?.model) ?? "unknown";
|
|
445
452
|
const providerResponse = providerResponseSummary(rawResponse);
|
|
446
453
|
const usage = response?.usage;
|
|
447
454
|
return compactJsonObject({
|
|
448
455
|
provider: args.modelInfo?.provider,
|
|
449
|
-
|
|
450
|
-
requestedModel: request.model,
|
|
451
|
-
defaultModel: args.modelInfo?.defaultModel,
|
|
456
|
+
modelId,
|
|
452
457
|
messageId: response?.messageId,
|
|
453
458
|
usage,
|
|
454
459
|
toolCount: request.tools.length,
|
|
@@ -458,15 +463,13 @@ function generationMetadata(args, endArgs) {
|
|
|
458
463
|
temperature: request.temperature,
|
|
459
464
|
maxTokens: request.maxTokens,
|
|
460
465
|
toolChoice: request.toolChoice,
|
|
461
|
-
|
|
466
|
+
providerOptionKeys: isRecord(request.providerOptions) ? Object.keys(request.providerOptions).sort() : void 0,
|
|
462
467
|
hasOutputSchema: request.outputSchema !== void 0,
|
|
463
468
|
firstDeltaMs: endArgs?.firstDeltaMs,
|
|
464
469
|
providerResponse,
|
|
465
470
|
modelInfo: compactJsonObject({
|
|
466
471
|
provider: args.modelInfo?.provider,
|
|
467
|
-
|
|
468
|
-
requestedModel: request.model,
|
|
469
|
-
defaultModel: args.modelInfo?.defaultModel,
|
|
472
|
+
modelId,
|
|
470
473
|
capabilities: args.modelInfo?.capabilities
|
|
471
474
|
}),
|
|
472
475
|
modelCall: compactJsonObject({
|
|
@@ -492,7 +495,6 @@ function generationMetadata(args, endArgs) {
|
|
|
492
495
|
}
|
|
493
496
|
function completionRequestSummary(request) {
|
|
494
497
|
return compactJsonObject({
|
|
495
|
-
model: request.model,
|
|
496
498
|
instructions: request.instructions === void 0 ? void 0 : { present: true },
|
|
497
499
|
messageCount: request.chatHistory.length,
|
|
498
500
|
documentCount: request.documents.length,
|
|
@@ -502,7 +504,7 @@ function completionRequestSummary(request) {
|
|
|
502
504
|
temperature: request.temperature,
|
|
503
505
|
maxTokens: request.maxTokens,
|
|
504
506
|
toolChoice: request.toolChoice,
|
|
505
|
-
|
|
507
|
+
providerOptionKeys: isRecord(request.providerOptions) ? Object.keys(request.providerOptions).sort() : void 0,
|
|
506
508
|
hasOutputSchema: request.outputSchema !== void 0
|
|
507
509
|
});
|
|
508
510
|
}
|
|
@@ -539,7 +541,6 @@ function toolMetadata(args, skipped, result) {
|
|
|
539
541
|
argumentBytes: byteLength(args.args),
|
|
540
542
|
resultBytes: result === void 0 ? void 0 : byteLength(result),
|
|
541
543
|
hasCallSignature: args.toolCall.signature !== void 0,
|
|
542
|
-
hasAdditionalParams: args.toolCall.additionalParams !== void 0,
|
|
543
544
|
toolDescription: args.toolDefinition?.description,
|
|
544
545
|
parameterKeys: Object.keys(properties).sort(),
|
|
545
546
|
requiredParameterKeys: required,
|
|
@@ -557,8 +558,7 @@ function toolMetadata(args, skipped, result) {
|
|
|
557
558
|
mcpServerName: args.toolMetadata?.mcpServerName,
|
|
558
559
|
argumentBytes: byteLength(args.args),
|
|
559
560
|
resultBytes: result === void 0 ? void 0 : byteLength(result),
|
|
560
|
-
hasCallSignature: args.toolCall.signature !== void 0
|
|
561
|
-
hasAdditionalParams: args.toolCall.additionalParams !== void 0
|
|
561
|
+
hasCallSignature: args.toolCall.signature !== void 0
|
|
562
562
|
})
|
|
563
563
|
});
|
|
564
564
|
}
|
|
@@ -575,6 +575,16 @@ function parseOrString(value) {
|
|
|
575
575
|
return value;
|
|
576
576
|
}
|
|
577
577
|
}
|
|
578
|
+
function traceOutput(value) {
|
|
579
|
+
if (typeof value === "string") {
|
|
580
|
+
return value;
|
|
581
|
+
}
|
|
582
|
+
try {
|
|
583
|
+
return JSON.stringify(toJsonValue(value));
|
|
584
|
+
} catch {
|
|
585
|
+
return String(value);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
578
588
|
function isRecord(value) {
|
|
579
589
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
580
590
|
}
|
|
@@ -874,70 +884,31 @@ function escapeHtml(value) {
|
|
|
874
884
|
return value.replaceAll("&", "&").replaceAll('"', """).replaceAll("<", "<").replaceAll(">", ">");
|
|
875
885
|
}
|
|
876
886
|
|
|
887
|
+
// src/runtime/agent-context.ts
|
|
888
|
+
import { isVectorContext } from "@anvia/core/agent";
|
|
889
|
+
function staticContextDocuments(agent) {
|
|
890
|
+
return agent.context.filter((input) => !isVectorContext(input));
|
|
891
|
+
}
|
|
892
|
+
function vectorContexts(agent) {
|
|
893
|
+
return agent.context.filter(isVectorContext);
|
|
894
|
+
}
|
|
895
|
+
|
|
877
896
|
// src/runtime/agent-runs.ts
|
|
878
|
-
import {
|
|
897
|
+
import {
|
|
898
|
+
withInternalAgentRunOptions
|
|
899
|
+
} from "@anvia/core/internal/agent";
|
|
879
900
|
|
|
880
901
|
// src/runtime/agent-utils.ts
|
|
881
902
|
import {
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
903
|
+
createResolvedAgent,
|
|
904
|
+
getResolvedAgentOptions
|
|
905
|
+
} from "@anvia/core/internal/agent";
|
|
885
906
|
function cloneAgent(agent, overrides = {}) {
|
|
886
|
-
return
|
|
887
|
-
|
|
888
|
-
name: agent.name,
|
|
889
|
-
description: agent.description,
|
|
890
|
-
model: agent.model,
|
|
891
|
-
instructions: agent.instructions,
|
|
892
|
-
staticContext: agent.staticContext,
|
|
893
|
-
temperature: agent.temperature,
|
|
894
|
-
maxTokens: agent.maxTokens,
|
|
895
|
-
additionalParams: agent.additionalParams,
|
|
896
|
-
toolSet: agent.toolSet,
|
|
897
|
-
toolChoice: agent.toolChoice,
|
|
898
|
-
defaultMaxTurns: agent.defaultMaxTurns,
|
|
899
|
-
hook: agent.hook,
|
|
900
|
-
outputSchema: agent.outputSchema,
|
|
901
|
-
observers: agent.observers,
|
|
902
|
-
approvals: agent.approvals,
|
|
903
|
-
dynamicContexts: agent.dynamicContexts,
|
|
904
|
-
dynamicTools: agent.dynamicTools,
|
|
905
|
-
middlewares: agent.middlewares,
|
|
906
|
-
memory: agent.memory,
|
|
907
|
-
eventStore: agent.eventStore,
|
|
907
|
+
return createResolvedAgent({
|
|
908
|
+
...getResolvedAgentOptions(agent),
|
|
908
909
|
...overrides
|
|
909
910
|
});
|
|
910
911
|
}
|
|
911
|
-
function composeHooks(first, second) {
|
|
912
|
-
if (first === void 0) {
|
|
913
|
-
return second;
|
|
914
|
-
}
|
|
915
|
-
if (second === void 0) {
|
|
916
|
-
return first;
|
|
917
|
-
}
|
|
918
|
-
return createHook({
|
|
919
|
-
async onCompletionCall(args) {
|
|
920
|
-
const firstAction = await first.onCompletionCall?.(args);
|
|
921
|
-
return firstAction?.type === "terminate" ? firstAction : await second.onCompletionCall?.(args) ?? void 0;
|
|
922
|
-
},
|
|
923
|
-
async onCompletionResponse(args) {
|
|
924
|
-
const firstAction = await first.onCompletionResponse?.(args);
|
|
925
|
-
return firstAction?.type === "terminate" ? firstAction : await second.onCompletionResponse?.(args) ?? void 0;
|
|
926
|
-
},
|
|
927
|
-
async onToolCall(args) {
|
|
928
|
-
const firstAction = await first.onToolCall?.(args);
|
|
929
|
-
if (firstAction?.type === "skip" || firstAction?.type === "terminate" || firstAction?.type === "approval_request") {
|
|
930
|
-
return firstAction;
|
|
931
|
-
}
|
|
932
|
-
const secondAction = await second.onToolCall?.(args);
|
|
933
|
-
return secondAction ?? firstAction ?? void 0;
|
|
934
|
-
},
|
|
935
|
-
async onToolResult(args) {
|
|
936
|
-
const firstAction = await first.onToolResult?.(args);
|
|
937
|
-
return firstAction?.type === "terminate" ? firstAction : await second.onToolResult?.(args) ?? void 0;
|
|
938
|
-
}
|
|
939
|
-
});
|
|
940
|
-
}
|
|
941
912
|
|
|
942
913
|
// src/runtime/errors.ts
|
|
943
914
|
function serializeError(error) {
|
|
@@ -952,7 +923,8 @@ function serializeError(error) {
|
|
|
952
923
|
|
|
953
924
|
// src/runtime/type-guards.ts
|
|
954
925
|
import {
|
|
955
|
-
isJsonValue as isCoreJsonValue
|
|
926
|
+
isJsonValue as isCoreJsonValue,
|
|
927
|
+
isMessage
|
|
956
928
|
} from "@anvia/core/completion";
|
|
957
929
|
function isObject(value) {
|
|
958
930
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -963,26 +935,16 @@ function isJsonObject(value) {
|
|
|
963
935
|
function isJsonValue(value) {
|
|
964
936
|
return isCoreJsonValue(value);
|
|
965
937
|
}
|
|
966
|
-
function isMessageInput(value) {
|
|
967
|
-
return typeof value === "string" || isMessage(value);
|
|
968
|
-
}
|
|
969
|
-
function isMessage(value) {
|
|
970
|
-
if (!isObject(value) || typeof value.role !== "string") {
|
|
971
|
-
return false;
|
|
972
|
-
}
|
|
973
|
-
if (value.role === "system") {
|
|
974
|
-
return typeof value.content === "string";
|
|
975
|
-
}
|
|
976
|
-
if (value.role === "user" || value.role === "assistant" || value.role === "tool") {
|
|
977
|
-
return Array.isArray(value.content);
|
|
978
|
-
}
|
|
979
|
-
return false;
|
|
980
|
-
}
|
|
981
938
|
function isAgentTraceOptions(value) {
|
|
982
939
|
if (!isObject(value)) {
|
|
983
940
|
return false;
|
|
984
941
|
}
|
|
985
|
-
|
|
942
|
+
if (!Object.keys(value).every(
|
|
943
|
+
(key) => ["name", "userId", "sessionId", "metadata", "tags", "version", "traceId"].includes(key)
|
|
944
|
+
)) {
|
|
945
|
+
return false;
|
|
946
|
+
}
|
|
947
|
+
return optionalString(value.name) && optionalString(value.userId) && optionalString(value.sessionId) && optionalString(value.version) && optionalString(value.traceId) && optionalStringArray(value.tags) && (value.metadata === void 0 || isJsonObject(value.metadata));
|
|
986
948
|
}
|
|
987
949
|
function isNonNegativeInteger(value) {
|
|
988
950
|
return Number.isInteger(value) && typeof value === "number" && value >= 0;
|
|
@@ -993,15 +955,9 @@ function isPositiveInteger(value) {
|
|
|
993
955
|
function optionalString(value) {
|
|
994
956
|
return value === void 0 || typeof value === "string";
|
|
995
957
|
}
|
|
996
|
-
function optionalBoolean(value) {
|
|
997
|
-
return value === void 0 || typeof value === "boolean";
|
|
998
|
-
}
|
|
999
958
|
function optionalStringArray(value) {
|
|
1000
959
|
return value === void 0 || Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
1001
960
|
}
|
|
1002
|
-
function optionalObject(value) {
|
|
1003
|
-
return value === void 0 || isObject(value);
|
|
1004
|
-
}
|
|
1005
961
|
|
|
1006
962
|
// src/runtime/http.ts
|
|
1007
963
|
function errorResponse(c, status, code, message, details) {
|
|
@@ -1051,8 +1007,8 @@ function createStudioModelRegistry(config) {
|
|
|
1051
1007
|
id,
|
|
1052
1008
|
staticModels
|
|
1053
1009
|
};
|
|
1054
|
-
if (provider.
|
|
1055
|
-
runtimeProvider.
|
|
1010
|
+
if (provider.defaultModelId !== void 0) {
|
|
1011
|
+
runtimeProvider.defaultModelId = normalizeModelId(provider.defaultModelId);
|
|
1056
1012
|
}
|
|
1057
1013
|
providers.set(id, runtimeProvider);
|
|
1058
1014
|
}
|
|
@@ -1061,8 +1017,10 @@ function createStudioModelRegistry(config) {
|
|
|
1061
1017
|
agentPolicies: normalizeAgentPolicies(config.agents ?? {}),
|
|
1062
1018
|
modelCache: /* @__PURE__ */ new Map()
|
|
1063
1019
|
};
|
|
1064
|
-
if (config.
|
|
1065
|
-
Object.assign(registry, {
|
|
1020
|
+
if (config.defaultModelRef !== void 0) {
|
|
1021
|
+
Object.assign(registry, {
|
|
1022
|
+
defaultModelRef: normalizeModelRef(config.defaultModelRef)
|
|
1023
|
+
});
|
|
1066
1024
|
}
|
|
1067
1025
|
return registry;
|
|
1068
1026
|
}
|
|
@@ -1079,7 +1037,7 @@ function studioModelsConfig(registry, agents) {
|
|
|
1079
1037
|
models
|
|
1080
1038
|
};
|
|
1081
1039
|
if (provider.name !== void 0) config2.name = provider.name;
|
|
1082
|
-
if (provider.
|
|
1040
|
+
if (provider.defaultModelId !== void 0) config2.defaultModelId = provider.defaultModelId;
|
|
1083
1041
|
if (provider.metadata !== void 0) config2.metadata = provider.metadata;
|
|
1084
1042
|
return config2;
|
|
1085
1043
|
});
|
|
@@ -1091,7 +1049,7 @@ function studioModelsConfig(registry, agents) {
|
|
|
1091
1049
|
providers,
|
|
1092
1050
|
agents: agentsConfig
|
|
1093
1051
|
};
|
|
1094
|
-
if (registry.
|
|
1052
|
+
if (registry.defaultModelRef !== void 0) config.defaultModelRef = registry.defaultModelRef;
|
|
1095
1053
|
return config;
|
|
1096
1054
|
}
|
|
1097
1055
|
function registerModelRoutes(app, props) {
|
|
@@ -1105,8 +1063,8 @@ function registerModelRoutes(app, props) {
|
|
|
1105
1063
|
const response = {
|
|
1106
1064
|
providers
|
|
1107
1065
|
};
|
|
1108
|
-
if (props.registry.
|
|
1109
|
-
response.
|
|
1066
|
+
if (props.registry.defaultModelRef !== void 0) {
|
|
1067
|
+
response.defaultModelRef = props.registry.defaultModelRef;
|
|
1110
1068
|
}
|
|
1111
1069
|
return c.json(response);
|
|
1112
1070
|
});
|
|
@@ -1139,7 +1097,7 @@ function resolveStudioModel(registry, input) {
|
|
|
1139
1097
|
if (registry === void 0) {
|
|
1140
1098
|
return { warnings: [] };
|
|
1141
1099
|
}
|
|
1142
|
-
const selectedRef = normalizeOptionalModelRef(input.request.model) ?? sessionModelRef(input.sessionMetadata) ?? registry.agentPolicies.get(input.agent.id)?.
|
|
1100
|
+
const selectedRef = normalizeOptionalModelRef(input.request.model) ?? sessionModelRef(input.sessionMetadata) ?? registry.agentPolicies.get(input.agent.id)?.defaultModelRef ?? registry.defaultModelRef;
|
|
1143
1101
|
if (selectedRef === void 0) {
|
|
1144
1102
|
return { warnings: [] };
|
|
1145
1103
|
}
|
|
@@ -1151,7 +1109,7 @@ function resolveStudioModel(registry, input) {
|
|
|
1151
1109
|
}
|
|
1152
1110
|
let model = registry.modelCache.get(selectedRef);
|
|
1153
1111
|
if (model === void 0) {
|
|
1154
|
-
model = provider.createCompletionModel(modelId);
|
|
1112
|
+
model = provider.createCompletionModel({ modelId });
|
|
1155
1113
|
registry.modelCache.set(selectedRef, model);
|
|
1156
1114
|
}
|
|
1157
1115
|
const metadata = provider.staticModels.get(modelId);
|
|
@@ -1169,12 +1127,7 @@ function normalizeOptionalModelRef(ref) {
|
|
|
1169
1127
|
return ref === void 0 ? void 0 : normalizeModelRef(ref);
|
|
1170
1128
|
}
|
|
1171
1129
|
function normalizeModelRef(ref) {
|
|
1172
|
-
|
|
1173
|
-
const trimmed = ref.trim();
|
|
1174
|
-
const parsed = parseModelRef(trimmed);
|
|
1175
|
-
return `${parsed.providerId}:${parsed.modelId}`;
|
|
1176
|
-
}
|
|
1177
|
-
return `${normalizeProviderId(ref.provider)}:${normalizeModelId(ref.model)}`;
|
|
1130
|
+
return `${normalizeProviderId(ref.providerId)}:${normalizeModelId(ref.modelId)}`;
|
|
1178
1131
|
}
|
|
1179
1132
|
function parseModelRef(ref) {
|
|
1180
1133
|
const index = ref.indexOf(":");
|
|
@@ -1217,12 +1170,12 @@ async function agentModelsCatalog(registry, agent) {
|
|
|
1217
1170
|
return [];
|
|
1218
1171
|
}
|
|
1219
1172
|
});
|
|
1220
|
-
const
|
|
1173
|
+
const defaultModelRef = policy?.defaultModelRef ?? registry.defaultModelRef;
|
|
1221
1174
|
const summary = {
|
|
1222
1175
|
agentId: agent.id,
|
|
1223
1176
|
models: [...models, ...exactPolicyModels]
|
|
1224
1177
|
};
|
|
1225
|
-
if (
|
|
1178
|
+
if (defaultModelRef !== void 0) summary.defaultModelRef = defaultModelRef;
|
|
1226
1179
|
if (warnings.length > 0) summary.warnings = warnings;
|
|
1227
1180
|
return summary;
|
|
1228
1181
|
}
|
|
@@ -1260,7 +1213,7 @@ async function providerCatalog(provider) {
|
|
|
1260
1213
|
models: [...models.values()].sort((left, right) => left.ref.localeCompare(right.ref))
|
|
1261
1214
|
};
|
|
1262
1215
|
if (provider.name !== void 0) catalog.name = provider.name;
|
|
1263
|
-
if (provider.
|
|
1216
|
+
if (provider.defaultModelId !== void 0) catalog.defaultModelId = provider.defaultModelId;
|
|
1264
1217
|
if (provider.metadata !== void 0) catalog.metadata = provider.metadata;
|
|
1265
1218
|
if (warning !== void 0) catalog.warning = warning;
|
|
1266
1219
|
return catalog;
|
|
@@ -1294,19 +1247,33 @@ function normalizeAgentPolicies(policies) {
|
|
|
1294
1247
|
return new Map(
|
|
1295
1248
|
Object.entries(policies).map(([agentId, policy]) => {
|
|
1296
1249
|
const normalized = {};
|
|
1297
|
-
if (policy.
|
|
1250
|
+
if (policy.defaultModelRef !== void 0) {
|
|
1251
|
+
normalized.defaultModelRef = normalizeModelRef(policy.defaultModelRef);
|
|
1252
|
+
}
|
|
1298
1253
|
if (policy.allowed !== void 0) {
|
|
1299
|
-
normalized.allowed = policy.allowed.map(
|
|
1300
|
-
(
|
|
1301
|
-
|
|
1254
|
+
normalized.allowed = policy.allowed.map((entry) => {
|
|
1255
|
+
if (typeof entry === "string") {
|
|
1256
|
+
return normalizeWildcardModelRef(entry);
|
|
1257
|
+
}
|
|
1258
|
+
return normalizeModelRef(entry);
|
|
1259
|
+
});
|
|
1302
1260
|
}
|
|
1303
1261
|
return [agentId.trim(), normalized];
|
|
1304
1262
|
})
|
|
1305
1263
|
);
|
|
1306
1264
|
}
|
|
1265
|
+
function normalizeWildcardModelRef(ref) {
|
|
1266
|
+
const normalized = ref.trim();
|
|
1267
|
+
if (!normalized.endsWith(":*")) {
|
|
1268
|
+
throw new ModelSelectionError(`Invalid wildcard model reference: ${ref}`);
|
|
1269
|
+
}
|
|
1270
|
+
return `${normalizeProviderId(normalized.slice(0, -2))}:*`;
|
|
1271
|
+
}
|
|
1307
1272
|
function publicPolicy(policy) {
|
|
1308
1273
|
const config = {};
|
|
1309
|
-
if (policy.
|
|
1274
|
+
if (policy.defaultModelRef !== void 0) {
|
|
1275
|
+
config.defaultModelRef = policy.defaultModelRef;
|
|
1276
|
+
}
|
|
1310
1277
|
if (policy.allowed !== void 0) config.allowed = policy.allowed;
|
|
1311
1278
|
return config;
|
|
1312
1279
|
}
|
|
@@ -1337,15 +1304,13 @@ function modelWarnings(ref, model, request) {
|
|
|
1337
1304
|
function requestModalities(request) {
|
|
1338
1305
|
const modalities = /* @__PURE__ */ new Set(["text"]);
|
|
1339
1306
|
for (const message of requestMessages(request)) {
|
|
1340
|
-
if (typeof message === "string") {
|
|
1341
|
-
continue;
|
|
1342
|
-
}
|
|
1343
1307
|
if (message.role === "user" || message.role === "assistant") {
|
|
1308
|
+
if (typeof message.content === "string") continue;
|
|
1344
1309
|
for (const content of message.content) {
|
|
1345
1310
|
if (content.type === "image") {
|
|
1346
1311
|
modalities.add("image");
|
|
1347
1312
|
}
|
|
1348
|
-
if (content.type === "
|
|
1313
|
+
if (content.type === "file") {
|
|
1349
1314
|
modalities.add("document");
|
|
1350
1315
|
}
|
|
1351
1316
|
}
|
|
@@ -1354,7 +1319,7 @@ function requestModalities(request) {
|
|
|
1354
1319
|
return modalities;
|
|
1355
1320
|
}
|
|
1356
1321
|
function requestMessages(request) {
|
|
1357
|
-
return
|
|
1322
|
+
return request.messages;
|
|
1358
1323
|
}
|
|
1359
1324
|
function normalizeProviderId(id) {
|
|
1360
1325
|
const trimmed = id.trim();
|
|
@@ -1372,7 +1337,7 @@ function normalizeModelId(id) {
|
|
|
1372
1337
|
}
|
|
1373
1338
|
|
|
1374
1339
|
// src/runtime/streams.ts
|
|
1375
|
-
import {
|
|
1340
|
+
import { createClientStreamResponse, createEventStreamResponse } from "@anvia/server";
|
|
1376
1341
|
var studioJsonlHeaders = {
|
|
1377
1342
|
"cache-control": "no-cache, no-transform",
|
|
1378
1343
|
connection: "keep-alive",
|
|
@@ -1381,7 +1346,15 @@ var studioJsonlHeaders = {
|
|
|
1381
1346
|
"x-accel-buffering": "no"
|
|
1382
1347
|
};
|
|
1383
1348
|
function streamStudioJsonl(events) {
|
|
1384
|
-
return
|
|
1349
|
+
return createEventStreamResponse({
|
|
1350
|
+
events: withStudioStreamErrors(events),
|
|
1351
|
+
format: "jsonl",
|
|
1352
|
+
headers: studioJsonlHeaders
|
|
1353
|
+
});
|
|
1354
|
+
}
|
|
1355
|
+
function streamStudioClient(options) {
|
|
1356
|
+
return createClientStreamResponse({
|
|
1357
|
+
events: options.events,
|
|
1385
1358
|
format: "jsonl",
|
|
1386
1359
|
headers: studioJsonlHeaders
|
|
1387
1360
|
});
|
|
@@ -1400,8 +1373,9 @@ function withStudioStreamErrors(events) {
|
|
|
1400
1373
|
const next = await iterator.next();
|
|
1401
1374
|
if (next.done === true) {
|
|
1402
1375
|
done = true;
|
|
1376
|
+
return next;
|
|
1403
1377
|
}
|
|
1404
|
-
return next;
|
|
1378
|
+
return { done: false, value: serializeStreamError(next.value) };
|
|
1405
1379
|
} catch (error) {
|
|
1406
1380
|
done = true;
|
|
1407
1381
|
return {
|
|
@@ -1419,6 +1393,12 @@ function withStudioStreamErrors(events) {
|
|
|
1419
1393
|
}
|
|
1420
1394
|
};
|
|
1421
1395
|
}
|
|
1396
|
+
function serializeStreamError(event) {
|
|
1397
|
+
if (typeof event !== "object" || event === null || !("type" in event) || event.type !== "error" || !("error" in event)) {
|
|
1398
|
+
return event;
|
|
1399
|
+
}
|
|
1400
|
+
return { ...event, error: serializeError(event.error) };
|
|
1401
|
+
}
|
|
1422
1402
|
function studioStreamError(error) {
|
|
1423
1403
|
return {
|
|
1424
1404
|
type: "error",
|
|
@@ -1435,6 +1415,7 @@ function traceSummary(trace) {
|
|
|
1435
1415
|
startedAt: trace.startedAt,
|
|
1436
1416
|
observationCount: trace.observations.length
|
|
1437
1417
|
};
|
|
1418
|
+
if (trace.runId !== void 0) summary.runId = trace.runId;
|
|
1438
1419
|
if (trace.name !== void 0) summary.name = trace.name;
|
|
1439
1420
|
if (trace.endedAt !== void 0) summary.endedAt = trace.endedAt;
|
|
1440
1421
|
if (trace.durationMs !== void 0) summary.durationMs = trace.durationMs;
|
|
@@ -1626,6 +1607,15 @@ function isEventType(value) {
|
|
|
1626
1607
|
return value === "session_log" || value === "pipeline_log" || value === "trace";
|
|
1627
1608
|
}
|
|
1628
1609
|
|
|
1610
|
+
// src/runtime/runs.ts
|
|
1611
|
+
import {
|
|
1612
|
+
customAgentEventsToClientStream
|
|
1613
|
+
} from "@anvia/client";
|
|
1614
|
+
import {
|
|
1615
|
+
isJsonValue as isJsonValue2,
|
|
1616
|
+
parseMessages
|
|
1617
|
+
} from "@anvia/core/completion";
|
|
1618
|
+
|
|
1629
1619
|
// src/runtime/transcript.ts
|
|
1630
1620
|
function renumberTranscript(entries) {
|
|
1631
1621
|
return entries.map((entry, entryId) => ({ ...entry, entryId }));
|
|
@@ -1639,7 +1629,8 @@ function transcriptFromMessages(messages) {
|
|
|
1639
1629
|
if (message.role === "user") {
|
|
1640
1630
|
const attachments = attachmentsFromMessage(message);
|
|
1641
1631
|
let textEntryAdded = false;
|
|
1642
|
-
|
|
1632
|
+
const contents2 = typeof message.content === "string" ? [{ type: "text", text: message.content }] : message.content;
|
|
1633
|
+
for (const content of contents2) {
|
|
1643
1634
|
if (content.type === "text") {
|
|
1644
1635
|
const entry = {
|
|
1645
1636
|
entryId: transcript.length,
|
|
@@ -1668,17 +1659,16 @@ function transcriptFromMessages(messages) {
|
|
|
1668
1659
|
transcript.push({
|
|
1669
1660
|
entryId: transcript.length,
|
|
1670
1661
|
kind: "tool",
|
|
1671
|
-
toolName:
|
|
1672
|
-
callId: content.callId ?? content.
|
|
1673
|
-
result: content.
|
|
1674
|
-
|
|
1675
|
-
).join("\n"),
|
|
1676
|
-
structuredResult: content.content
|
|
1662
|
+
toolName: content.toolName,
|
|
1663
|
+
callId: content.callId ?? content.toolCallId,
|
|
1664
|
+
result: toolResultText(content.output),
|
|
1665
|
+
...content.output.type === "content" ? { structuredResult: content.output.value } : {}
|
|
1677
1666
|
});
|
|
1678
1667
|
}
|
|
1679
1668
|
continue;
|
|
1680
1669
|
}
|
|
1681
|
-
|
|
1670
|
+
const contents = typeof message.content === "string" ? [{ type: "text", text: message.content }] : message.content;
|
|
1671
|
+
for (const content of contents) {
|
|
1682
1672
|
if (content.type === "text") {
|
|
1683
1673
|
appendAssistantTranscriptText(transcript, content.text);
|
|
1684
1674
|
} else if (content.type === "reasoning") {
|
|
@@ -1689,13 +1679,13 @@ function transcriptFromMessages(messages) {
|
|
|
1689
1679
|
};
|
|
1690
1680
|
if (content.id !== void 0) entry.reasoningId = content.id;
|
|
1691
1681
|
transcript.push(entry);
|
|
1692
|
-
} else if (content.type === "
|
|
1682
|
+
} else if (content.type === "tool-call") {
|
|
1693
1683
|
transcript.push({
|
|
1694
1684
|
entryId: transcript.length,
|
|
1695
1685
|
kind: "tool",
|
|
1696
|
-
toolName: content.
|
|
1697
|
-
callId: content.callId ?? content.
|
|
1698
|
-
args: formatJson(content.
|
|
1686
|
+
toolName: content.toolName,
|
|
1687
|
+
callId: content.callId ?? content.toolCallId,
|
|
1688
|
+
args: formatJson(content.input)
|
|
1699
1689
|
});
|
|
1700
1690
|
}
|
|
1701
1691
|
}
|
|
@@ -1706,28 +1696,37 @@ function attachmentsFromMessage(message) {
|
|
|
1706
1696
|
if (message.role !== "user" && message.role !== "assistant") {
|
|
1707
1697
|
return [];
|
|
1708
1698
|
}
|
|
1699
|
+
if (typeof message.content === "string") return [];
|
|
1709
1700
|
return message.content.flatMap((content) => {
|
|
1710
1701
|
if (content.type === "image") {
|
|
1711
1702
|
const attachment = { kind: "image" };
|
|
1712
|
-
if (content.
|
|
1713
|
-
attachment.data = content.
|
|
1714
|
-
attachment.mediaType = content.
|
|
1703
|
+
if (content.image.type === "data") {
|
|
1704
|
+
attachment.data = content.image.data;
|
|
1705
|
+
if (content.mediaType !== void 0) attachment.mediaType = content.mediaType;
|
|
1715
1706
|
} else {
|
|
1716
|
-
attachment.url = content.
|
|
1707
|
+
attachment.url = content.image.url;
|
|
1717
1708
|
}
|
|
1718
1709
|
return [attachment];
|
|
1719
1710
|
}
|
|
1720
|
-
if (content.type === "
|
|
1711
|
+
if (content.type === "file") {
|
|
1721
1712
|
const attachment = { kind: "document" };
|
|
1722
|
-
if (content.
|
|
1723
|
-
|
|
1724
|
-
if (content.
|
|
1725
|
-
if (content.
|
|
1713
|
+
if (content.filename !== void 0) attachment.name = content.filename;
|
|
1714
|
+
attachment.mediaType = content.mediaType;
|
|
1715
|
+
if (content.data.type === "data") attachment.data = content.data.data;
|
|
1716
|
+
if (content.data.type === "url") attachment.url = content.data.url;
|
|
1726
1717
|
return [attachment];
|
|
1727
1718
|
}
|
|
1728
1719
|
return [];
|
|
1729
1720
|
});
|
|
1730
1721
|
}
|
|
1722
|
+
function toolResultText(output) {
|
|
1723
|
+
if (output.type === "text" || output.type === "error-text") return output.value;
|
|
1724
|
+
if (output.type === "json" || output.type === "error-json") return formatJson(output.value);
|
|
1725
|
+
if (output.type === "execution-denied") return output.reason ?? "Execution denied";
|
|
1726
|
+
return output.value.map(
|
|
1727
|
+
(part) => part.type === "text" ? part.text : `[file:${part.mediaType}${part.filename === void 0 ? "" : `:${part.filename}`}]`
|
|
1728
|
+
).join("\n");
|
|
1729
|
+
}
|
|
1731
1730
|
function appendAssistantTranscriptText(transcript, text) {
|
|
1732
1731
|
const last = transcript.at(-1);
|
|
1733
1732
|
if (last?.kind === "message" && last.role === "assistant") {
|
|
@@ -1815,8 +1814,97 @@ async function* mergeRunAndApprovalEvents(runEvents, approvalEvents) {
|
|
|
1815
1814
|
approvalEvents.close();
|
|
1816
1815
|
}
|
|
1817
1816
|
}
|
|
1818
|
-
function streamAgentRunEvents(_c, events, options
|
|
1819
|
-
return
|
|
1817
|
+
function streamAgentRunEvents(_c, events, options) {
|
|
1818
|
+
return streamStudioClient({
|
|
1819
|
+
events: customAgentEventsToClientStream({
|
|
1820
|
+
events: withAgentRunCancellation(events, options.onCancel),
|
|
1821
|
+
runId: options.runId,
|
|
1822
|
+
mapCustomEvent: studioEventToClientEvent
|
|
1823
|
+
})
|
|
1824
|
+
});
|
|
1825
|
+
}
|
|
1826
|
+
function studioEventToClientEvent(event, context) {
|
|
1827
|
+
if (event.type === "tool_approval_request" || event.type === "tool_approval_result") {
|
|
1828
|
+
return {
|
|
1829
|
+
type: "tool_approval",
|
|
1830
|
+
runId: context.runId,
|
|
1831
|
+
...context.turn === void 0 ? {} : { turn: context.turn },
|
|
1832
|
+
...context.scope === void 0 ? {} : { scope: context.scope },
|
|
1833
|
+
approval: {
|
|
1834
|
+
id: event.approval.id,
|
|
1835
|
+
runId: event.approval.runId,
|
|
1836
|
+
agentId: event.approval.agentId,
|
|
1837
|
+
...event.approval.sessionId === void 0 ? {} : { sessionId: event.approval.sessionId },
|
|
1838
|
+
toolName: event.approval.toolName,
|
|
1839
|
+
...event.approval.callId === void 0 ? {} : { callId: event.approval.callId },
|
|
1840
|
+
internalCallId: event.approval.internalCallId,
|
|
1841
|
+
input: parseJsonOrString(event.approval.args),
|
|
1842
|
+
status: event.approval.status,
|
|
1843
|
+
requestedAt: event.approval.requestedAt,
|
|
1844
|
+
...event.approval.resolvedAt === void 0 ? {} : { resolvedAt: event.approval.resolvedAt },
|
|
1845
|
+
...event.approval.reason === void 0 ? {} : { reason: event.approval.reason }
|
|
1846
|
+
}
|
|
1847
|
+
};
|
|
1848
|
+
}
|
|
1849
|
+
if (event.type === "tool_question_request" || event.type === "tool_question_result") {
|
|
1850
|
+
return {
|
|
1851
|
+
type: "tool_question",
|
|
1852
|
+
runId: context.runId,
|
|
1853
|
+
...context.turn === void 0 ? {} : { turn: context.turn },
|
|
1854
|
+
...context.scope === void 0 ? {} : { scope: context.scope },
|
|
1855
|
+
question: {
|
|
1856
|
+
id: event.question.id,
|
|
1857
|
+
runId: event.question.runId,
|
|
1858
|
+
agentId: event.question.agentId,
|
|
1859
|
+
...event.question.sessionId === void 0 ? {} : { sessionId: event.question.sessionId },
|
|
1860
|
+
toolName: event.question.toolName,
|
|
1861
|
+
...event.question.callId === void 0 ? {} : { callId: event.question.callId },
|
|
1862
|
+
internalCallId: event.question.internalCallId,
|
|
1863
|
+
input: parseJsonOrString(event.question.args),
|
|
1864
|
+
questions: event.question.questions,
|
|
1865
|
+
status: event.question.status,
|
|
1866
|
+
requestedAt: event.question.requestedAt,
|
|
1867
|
+
...event.question.answeredAt === void 0 ? {} : { answeredAt: event.question.answeredAt },
|
|
1868
|
+
...event.question.cancelledAt === void 0 ? {} : { cancelledAt: event.question.cancelledAt },
|
|
1869
|
+
...event.question.answers === void 0 ? {} : { answers: event.question.answers }
|
|
1870
|
+
}
|
|
1871
|
+
};
|
|
1872
|
+
}
|
|
1873
|
+
if (event.type === "session_log" && isJsonValue2(event.log)) {
|
|
1874
|
+
return {
|
|
1875
|
+
type: "data",
|
|
1876
|
+
runId: context.runId,
|
|
1877
|
+
name: "studio.session_log",
|
|
1878
|
+
data: event.log,
|
|
1879
|
+
transient: true
|
|
1880
|
+
};
|
|
1881
|
+
}
|
|
1882
|
+
if (event.type === "pipeline_log" && isJsonValue2(event.log)) {
|
|
1883
|
+
return {
|
|
1884
|
+
type: "data",
|
|
1885
|
+
runId: context.runId,
|
|
1886
|
+
name: "studio.pipeline_log",
|
|
1887
|
+
data: event.log,
|
|
1888
|
+
transient: true
|
|
1889
|
+
};
|
|
1890
|
+
}
|
|
1891
|
+
if (event.type === "pipeline_final" && isJsonValue2(event.output)) {
|
|
1892
|
+
return {
|
|
1893
|
+
type: "data",
|
|
1894
|
+
runId: context.runId,
|
|
1895
|
+
name: "studio.pipeline_final",
|
|
1896
|
+
data: event.output
|
|
1897
|
+
};
|
|
1898
|
+
}
|
|
1899
|
+
return void 0;
|
|
1900
|
+
}
|
|
1901
|
+
function parseJsonOrString(value) {
|
|
1902
|
+
try {
|
|
1903
|
+
const parsed = JSON.parse(value);
|
|
1904
|
+
return isJsonValue2(parsed) ? parsed : value;
|
|
1905
|
+
} catch {
|
|
1906
|
+
return value;
|
|
1907
|
+
}
|
|
1820
1908
|
}
|
|
1821
1909
|
function withAgentRunCancellation(events, onCancel) {
|
|
1822
1910
|
const iterator = events[Symbol.asyncIterator]();
|
|
@@ -1936,10 +2024,10 @@ function createPersistedStreamingSessionTranscript(props) {
|
|
|
1936
2024
|
};
|
|
1937
2025
|
if (event.type === "error") saveInput.error = serializeError(event.error);
|
|
1938
2026
|
await saveTranscript(saveInput);
|
|
1939
|
-
const generatedMessages = event.type === "final" ? event.messages.slice(1) : [];
|
|
2027
|
+
const generatedMessages = event.type === "final" ? event.result.messages.slice(1) : [];
|
|
1940
2028
|
if (props.persistGeneratedMessages === true && generatedMessages.length > 0) {
|
|
1941
2029
|
await props.store.append({
|
|
1942
|
-
|
|
2030
|
+
scope: { sessionId: props.session.id },
|
|
1943
2031
|
runId: props.runId,
|
|
1944
2032
|
turn: 1,
|
|
1945
2033
|
messages: generatedMessages
|
|
@@ -2041,9 +2129,9 @@ function acceptTranscriptStreamEvent(transcript, event) {
|
|
|
2041
2129
|
transcript.push({
|
|
2042
2130
|
entryId: transcript.length,
|
|
2043
2131
|
kind: "tool",
|
|
2044
|
-
toolName: event.toolCall.
|
|
2045
|
-
callId: event.toolCall.callId ?? event.toolCall.
|
|
2046
|
-
args: formatJson(event.toolCall.
|
|
2132
|
+
toolName: event.toolCall.toolName,
|
|
2133
|
+
callId: event.toolCall.callId ?? event.toolCall.toolCallId,
|
|
2134
|
+
args: formatJson(event.toolCall.input)
|
|
2047
2135
|
});
|
|
2048
2136
|
}
|
|
2049
2137
|
if (event.type === "tool_result") {
|
|
@@ -2151,8 +2239,8 @@ function acceptTranscriptStreamEvent(transcript, event) {
|
|
|
2151
2239
|
matched.question = question;
|
|
2152
2240
|
}
|
|
2153
2241
|
}
|
|
2154
|
-
if (event.type === "final" && event.trace?.traceId !== void 0) {
|
|
2155
|
-
assignTranscriptTraceId(transcript, event.trace.traceId);
|
|
2242
|
+
if (event.type === "final" && event.result.trace?.traceId !== void 0) {
|
|
2243
|
+
assignTranscriptTraceId(transcript, event.result.trace.traceId);
|
|
2156
2244
|
}
|
|
2157
2245
|
if (event.type === "error") {
|
|
2158
2246
|
appendTranscriptAssistantError(transcript, errorText(event.error));
|
|
@@ -2224,9 +2312,9 @@ function childAgentTranscriptEvent(event) {
|
|
|
2224
2312
|
const entry = {
|
|
2225
2313
|
kind: "tool",
|
|
2226
2314
|
agentId: event.agentId,
|
|
2227
|
-
toolName: child.toolCall.
|
|
2228
|
-
callId: child.toolCall.callId ?? child.toolCall.
|
|
2229
|
-
args: formatJson(child.toolCall.
|
|
2315
|
+
toolName: child.toolCall.toolName,
|
|
2316
|
+
callId: child.toolCall.callId ?? child.toolCall.toolCallId,
|
|
2317
|
+
args: formatJson(child.toolCall.input)
|
|
2230
2318
|
};
|
|
2231
2319
|
if (event.agentName !== void 0) entry.agentName = event.agentName;
|
|
2232
2320
|
return entry;
|
|
@@ -2363,17 +2451,18 @@ function extractMessageText(message) {
|
|
|
2363
2451
|
if (message.role === "system") {
|
|
2364
2452
|
return message.content;
|
|
2365
2453
|
}
|
|
2454
|
+
if (typeof message.content === "string") {
|
|
2455
|
+
return message.content;
|
|
2456
|
+
}
|
|
2366
2457
|
return message.content.flatMap((item) => {
|
|
2367
2458
|
if (item.type === "text" || item.type === "reasoning") {
|
|
2368
2459
|
return [item.text];
|
|
2369
2460
|
}
|
|
2370
|
-
if (item.type === "
|
|
2371
|
-
return [`${item.
|
|
2461
|
+
if (item.type === "tool-call") {
|
|
2462
|
+
return [`${item.toolName}(${formatJson(item.input)})`];
|
|
2372
2463
|
}
|
|
2373
|
-
if (item.type === "
|
|
2374
|
-
return item.
|
|
2375
|
-
(result) => "text" in result ? result.text : `[image:${result.mediaType ?? "image/png"}]`
|
|
2376
|
-
);
|
|
2464
|
+
if (item.type === "tool-result") {
|
|
2465
|
+
return [toolResultOutputText(item.output)];
|
|
2377
2466
|
}
|
|
2378
2467
|
return [];
|
|
2379
2468
|
}).join("\n");
|
|
@@ -2382,23 +2471,26 @@ function optionalTranscriptAttachments(message) {
|
|
|
2382
2471
|
if (typeof message === "string" || message.role !== "user") {
|
|
2383
2472
|
return {};
|
|
2384
2473
|
}
|
|
2474
|
+
if (typeof message.content === "string") {
|
|
2475
|
+
return {};
|
|
2476
|
+
}
|
|
2385
2477
|
const attachments = message.content.flatMap((content) => {
|
|
2386
2478
|
if (content.type === "image") {
|
|
2387
2479
|
const attachment = { kind: "image" };
|
|
2388
|
-
if (content.
|
|
2389
|
-
attachment.data = content.
|
|
2390
|
-
attachment.mediaType = content.
|
|
2480
|
+
if (content.image.type === "data") {
|
|
2481
|
+
attachment.data = content.image.data;
|
|
2482
|
+
if (content.mediaType !== void 0) attachment.mediaType = content.mediaType;
|
|
2391
2483
|
} else {
|
|
2392
|
-
attachment.url = content.
|
|
2484
|
+
attachment.url = content.image.url;
|
|
2393
2485
|
}
|
|
2394
2486
|
return [attachment];
|
|
2395
2487
|
}
|
|
2396
|
-
if (content.type === "
|
|
2488
|
+
if (content.type === "file") {
|
|
2397
2489
|
const attachment = { kind: "document" };
|
|
2398
|
-
if (content.
|
|
2399
|
-
|
|
2400
|
-
if (content.
|
|
2401
|
-
if (content.
|
|
2490
|
+
if (content.filename !== void 0) attachment.name = content.filename;
|
|
2491
|
+
attachment.mediaType = content.mediaType;
|
|
2492
|
+
if (content.data.type === "data") attachment.data = content.data.data;
|
|
2493
|
+
if (content.data.type === "url") attachment.url = content.data.url;
|
|
2402
2494
|
return [attachment];
|
|
2403
2495
|
}
|
|
2404
2496
|
return [];
|
|
@@ -2415,32 +2507,27 @@ async function parseRunRequest(c) {
|
|
|
2415
2507
|
if (!isObject(body)) {
|
|
2416
2508
|
return { error: errorResponse(c, 400, "bad_request", "Request body must be an object") };
|
|
2417
2509
|
}
|
|
2418
|
-
|
|
2419
|
-
if ("error" in request) {
|
|
2420
|
-
return request;
|
|
2421
|
-
}
|
|
2422
|
-
return parseRunRequestOptions(c, body, request);
|
|
2423
|
-
}
|
|
2424
|
-
function parseLegacyRunRequestBody(c, body) {
|
|
2425
|
-
if (!isMessageInput(body.message)) {
|
|
2510
|
+
if ("message" in body || "history" in body) {
|
|
2426
2511
|
return {
|
|
2427
|
-
error: errorResponse(
|
|
2512
|
+
error: errorResponse(
|
|
2513
|
+
c,
|
|
2514
|
+
400,
|
|
2515
|
+
"bad_request",
|
|
2516
|
+
"Legacy message/history requests are not supported; use messages"
|
|
2517
|
+
)
|
|
2428
2518
|
};
|
|
2429
2519
|
}
|
|
2430
|
-
const request =
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
if ("history" in body) {
|
|
2434
|
-
if (!Array.isArray(body.history) || !body.history.every(isMessage)) {
|
|
2435
|
-
return { error: errorResponse(c, 400, "bad_request", "history must be a Message array") };
|
|
2436
|
-
}
|
|
2437
|
-
request.history = body.history;
|
|
2520
|
+
const request = parseRunRequestBody(c, body);
|
|
2521
|
+
if ("error" in request) {
|
|
2522
|
+
return request;
|
|
2438
2523
|
}
|
|
2439
|
-
return request;
|
|
2524
|
+
return parseRunRequestOptions(c, body, request);
|
|
2440
2525
|
}
|
|
2441
|
-
function
|
|
2442
|
-
|
|
2443
|
-
|
|
2526
|
+
function parseRunRequestBody(c, body) {
|
|
2527
|
+
let messages;
|
|
2528
|
+
try {
|
|
2529
|
+
messages = parseMessages(body.messages);
|
|
2530
|
+
} catch {
|
|
2444
2531
|
return {
|
|
2445
2532
|
error: errorResponse(c, 400, "bad_request", "messages must be a non-empty Message array")
|
|
2446
2533
|
};
|
|
@@ -2456,19 +2543,21 @@ function parseUiRunRequestBody(c, body) {
|
|
|
2456
2543
|
error: errorResponse(c, 400, "bad_request", "messages must be a non-empty Message array")
|
|
2457
2544
|
};
|
|
2458
2545
|
}
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2546
|
+
if (message.role !== "user") {
|
|
2547
|
+
return {
|
|
2548
|
+
error: errorResponse(c, 400, "bad_request", "The final message must be user-authored")
|
|
2549
|
+
};
|
|
2550
|
+
}
|
|
2551
|
+
return { messages };
|
|
2463
2552
|
}
|
|
2464
2553
|
function parseRunRequestOptions(c, body, request) {
|
|
2465
2554
|
if ("sessionId" in body) {
|
|
2466
2555
|
if (typeof body.sessionId !== "string" || body.sessionId.trim().length === 0) {
|
|
2467
2556
|
return { error: errorResponse(c, 400, "bad_request", "sessionId must be a string") };
|
|
2468
2557
|
}
|
|
2469
|
-
if (request.
|
|
2558
|
+
if (request.messages.length !== 1 || request.messages[0]?.role !== "user") {
|
|
2470
2559
|
return {
|
|
2471
|
-
error: errorResponse(c, 400, "bad_request", "sessionId
|
|
2560
|
+
error: errorResponse(c, 400, "bad_request", "sessionId requires exactly one user message")
|
|
2472
2561
|
};
|
|
2473
2562
|
}
|
|
2474
2563
|
request.sessionId = body.sessionId;
|
|
@@ -2496,12 +2585,10 @@ function parseRunRequestOptions(c, body, request) {
|
|
|
2496
2585
|
request.toolConcurrency = body.toolConcurrency;
|
|
2497
2586
|
}
|
|
2498
2587
|
if ("model" in body) {
|
|
2499
|
-
if (typeof body.model === "string") {
|
|
2500
|
-
request.model = body.model;
|
|
2501
|
-
} else if (isObject(body.model) && typeof body.model.provider === "string" && typeof body.model.model === "string") {
|
|
2588
|
+
if (isObject(body.model) && typeof body.model.providerId === "string" && typeof body.model.modelId === "string") {
|
|
2502
2589
|
request.model = {
|
|
2503
|
-
|
|
2504
|
-
|
|
2590
|
+
providerId: body.model.providerId,
|
|
2591
|
+
modelId: body.model.modelId
|
|
2505
2592
|
};
|
|
2506
2593
|
} else {
|
|
2507
2594
|
return {
|
|
@@ -2509,7 +2596,7 @@ function parseRunRequestOptions(c, body, request) {
|
|
|
2509
2596
|
c,
|
|
2510
2597
|
400,
|
|
2511
2598
|
"bad_request",
|
|
2512
|
-
"model must be a
|
|
2599
|
+
"model must be a { providerId, modelId } object"
|
|
2513
2600
|
)
|
|
2514
2601
|
};
|
|
2515
2602
|
}
|
|
@@ -2530,6 +2617,14 @@ function parseRunRequestOptions(c, body, request) {
|
|
|
2530
2617
|
}
|
|
2531
2618
|
return request;
|
|
2532
2619
|
}
|
|
2620
|
+
function toolResultOutputText(output) {
|
|
2621
|
+
if (output.type === "text" || output.type === "error-text") return output.value;
|
|
2622
|
+
if (output.type === "json" || output.type === "error-json") return formatJson(output.value);
|
|
2623
|
+
if (output.type === "execution-denied") return output.reason ?? "Execution denied";
|
|
2624
|
+
return output.value.map(
|
|
2625
|
+
(part) => part.type === "text" ? part.text : `[file:${part.mediaType}${part.filename === void 0 ? "" : `:${part.filename}`}]`
|
|
2626
|
+
).join("\n");
|
|
2627
|
+
}
|
|
2533
2628
|
|
|
2534
2629
|
// src/runtime/session-logs.ts
|
|
2535
2630
|
async function appendSessionLog(store, input) {
|
|
@@ -2664,6 +2759,25 @@ function memorySavedLog(props) {
|
|
|
2664
2759
|
metadata
|
|
2665
2760
|
};
|
|
2666
2761
|
}
|
|
2762
|
+
function memoryCompactedLog(props) {
|
|
2763
|
+
const metadata = {
|
|
2764
|
+
originalMessageCount: props.originalMessageCount,
|
|
2765
|
+
compactedMessageCount: props.compactedMessageCount,
|
|
2766
|
+
retainedMessageCount: props.retainedMessageCount,
|
|
2767
|
+
attempts: props.attempts
|
|
2768
|
+
};
|
|
2769
|
+
const usage = usageSummary(props.usage);
|
|
2770
|
+
if (usage !== void 0) metadata.usage = usage;
|
|
2771
|
+
return {
|
|
2772
|
+
sessionId: props.sessionId,
|
|
2773
|
+
runId: props.runId,
|
|
2774
|
+
level: "info",
|
|
2775
|
+
category: "memory",
|
|
2776
|
+
event: "memory.compacted",
|
|
2777
|
+
message: "Session memory compacted",
|
|
2778
|
+
metadata
|
|
2779
|
+
};
|
|
2780
|
+
}
|
|
2667
2781
|
function runFailedLog(sessionId, runId, error, startedAt) {
|
|
2668
2782
|
return {
|
|
2669
2783
|
sessionId,
|
|
@@ -2680,6 +2794,9 @@ function runFailedLog(sessionId, runId, error, startedAt) {
|
|
|
2680
2794
|
}
|
|
2681
2795
|
function logsFromStreamEvent(props) {
|
|
2682
2796
|
const { event, sessionId, runId } = props;
|
|
2797
|
+
if (event.type === "memory_compaction") {
|
|
2798
|
+
return [memoryCompactedLog({ sessionId, runId, ...event })];
|
|
2799
|
+
}
|
|
2683
2800
|
if (event.type === "turn_start") {
|
|
2684
2801
|
return [
|
|
2685
2802
|
{
|
|
@@ -2705,12 +2822,12 @@ function logsFromStreamEvent(props) {
|
|
|
2705
2822
|
level: "info",
|
|
2706
2823
|
category: "tool",
|
|
2707
2824
|
event: "tool.called",
|
|
2708
|
-
message: `Tool ${event.toolCall.
|
|
2825
|
+
message: `Tool ${event.toolCall.toolName} called`,
|
|
2709
2826
|
metadata: {
|
|
2710
2827
|
turn: event.turn,
|
|
2711
|
-
toolName: event.toolCall.
|
|
2712
|
-
callId: event.toolCall.callId ?? event.toolCall.
|
|
2713
|
-
argumentBytes: byteLength2(formatUnknown(event.toolCall.
|
|
2828
|
+
toolName: event.toolCall.toolName,
|
|
2829
|
+
callId: event.toolCall.callId ?? event.toolCall.toolCallId,
|
|
2830
|
+
argumentBytes: byteLength2(formatUnknown(event.toolCall.input))
|
|
2714
2831
|
}
|
|
2715
2832
|
}
|
|
2716
2833
|
];
|
|
@@ -2759,16 +2876,17 @@ function logsFromStreamEvent(props) {
|
|
|
2759
2876
|
];
|
|
2760
2877
|
}
|
|
2761
2878
|
if (event.type === "final") {
|
|
2879
|
+
const result = event.result;
|
|
2762
2880
|
return [
|
|
2763
2881
|
runCompletedLog({
|
|
2764
2882
|
sessionId,
|
|
2765
2883
|
runId,
|
|
2766
2884
|
durationMs: Date.now() - props.startedAt,
|
|
2767
|
-
usage:
|
|
2768
|
-
output:
|
|
2769
|
-
messageCount:
|
|
2885
|
+
usage: result.usage,
|
|
2886
|
+
output: result.text,
|
|
2887
|
+
messageCount: result.messages.length
|
|
2770
2888
|
}),
|
|
2771
|
-
memorySavedLog({ sessionId, runId, messageCount:
|
|
2889
|
+
memorySavedLog({ sessionId, runId, messageCount: result.messages.length })
|
|
2772
2890
|
];
|
|
2773
2891
|
}
|
|
2774
2892
|
if (event.type === "error") {
|
|
@@ -2880,16 +2998,16 @@ function childAgentLog(event, sessionId, runId) {
|
|
|
2880
2998
|
level: "debug",
|
|
2881
2999
|
category: "tool",
|
|
2882
3000
|
event: "child_tool.called",
|
|
2883
|
-
message: `Child agent ${event.agentName ?? event.agentId} called ${child.toolCall.
|
|
3001
|
+
message: `Child agent ${event.agentName ?? event.agentId} called ${child.toolCall.toolName}`,
|
|
2884
3002
|
metadata: {
|
|
2885
3003
|
parentToolName: event.toolName,
|
|
2886
3004
|
agentId: event.agentId,
|
|
2887
3005
|
hasAgentName: event.agentName !== void 0,
|
|
2888
3006
|
turn: event.turn,
|
|
2889
3007
|
childTurn: child.turn,
|
|
2890
|
-
toolName: child.toolCall.
|
|
2891
|
-
callId: child.toolCall.callId ?? child.toolCall.
|
|
2892
|
-
argumentBytes: byteLength2(formatUnknown(child.toolCall.
|
|
3008
|
+
toolName: child.toolCall.toolName,
|
|
3009
|
+
callId: child.toolCall.callId ?? child.toolCall.toolCallId,
|
|
3010
|
+
argumentBytes: byteLength2(formatUnknown(child.toolCall.input))
|
|
2893
3011
|
}
|
|
2894
3012
|
}
|
|
2895
3013
|
];
|
|
@@ -2940,14 +3058,16 @@ function childAgentLog(event, sessionId, runId) {
|
|
|
2940
3058
|
];
|
|
2941
3059
|
}
|
|
2942
3060
|
if (child.type === "final") {
|
|
3061
|
+
const result = child.result;
|
|
2943
3062
|
const metadata = {
|
|
2944
3063
|
parentToolName: event.toolName,
|
|
2945
3064
|
agentId: event.agentId,
|
|
2946
3065
|
hasAgentName: event.agentName !== void 0,
|
|
2947
|
-
outputBytes: byteLength2(
|
|
2948
|
-
messageCount:
|
|
3066
|
+
outputBytes: byteLength2(result.text),
|
|
3067
|
+
messageCount: result.messages.length,
|
|
3068
|
+
status: result.status
|
|
2949
3069
|
};
|
|
2950
|
-
const usage = usageSummary(
|
|
3070
|
+
const usage = usageSummary(result.usage);
|
|
2951
3071
|
if (usage !== void 0) metadata.usage = usage;
|
|
2952
3072
|
return [
|
|
2953
3073
|
{
|
|
@@ -3073,18 +3193,18 @@ async function prepareAgentRun(c, props) {
|
|
|
3073
3193
|
store: props.stores.sessions
|
|
3074
3194
|
});
|
|
3075
3195
|
const memoryMetadata = runMemoryMetadata(agentId, body, selectedModel, runId);
|
|
3076
|
-
const promptMessage =
|
|
3196
|
+
const promptMessage = body.messages.at(-1);
|
|
3077
3197
|
const sessionStore = props.stores.sessions;
|
|
3078
3198
|
const shouldPersistSessionMessages = session !== void 0 && sessionStore !== void 0 && !usesStoreAsAgentMemory(runAgent, sessionStore);
|
|
3079
3199
|
if (shouldPersistSessionMessages) {
|
|
3080
3200
|
await sessionStore.append({
|
|
3081
|
-
|
|
3201
|
+
scope: { sessionId: session.id, metadata: memoryMetadata },
|
|
3082
3202
|
runId,
|
|
3083
3203
|
turn: 1,
|
|
3084
3204
|
messages: [promptMessage]
|
|
3085
3205
|
});
|
|
3086
3206
|
}
|
|
3087
|
-
const
|
|
3207
|
+
const execution = createRunExecution({
|
|
3088
3208
|
agentId,
|
|
3089
3209
|
body,
|
|
3090
3210
|
memoryMetadata,
|
|
@@ -3097,7 +3217,10 @@ async function prepareAgentRun(c, props) {
|
|
|
3097
3217
|
agent,
|
|
3098
3218
|
body,
|
|
3099
3219
|
memoryMetadata,
|
|
3100
|
-
|
|
3220
|
+
execution,
|
|
3221
|
+
failureMessages: void 0,
|
|
3222
|
+
memoryCompactionLogged: false,
|
|
3223
|
+
options: createRunOptions(body, agentId, session, c.req.raw.signal),
|
|
3101
3224
|
runAgent,
|
|
3102
3225
|
runId,
|
|
3103
3226
|
runStartedAt,
|
|
@@ -3142,7 +3265,7 @@ async function recordRunReceived(props) {
|
|
|
3142
3265
|
sessionId: props.session.id,
|
|
3143
3266
|
runId: props.runId,
|
|
3144
3267
|
agentId: props.agentId,
|
|
3145
|
-
message: props.body.
|
|
3268
|
+
message: props.body.messages.at(-1),
|
|
3146
3269
|
stream: props.body.stream === true,
|
|
3147
3270
|
hasTrace: props.body.trace !== void 0
|
|
3148
3271
|
};
|
|
@@ -3189,23 +3312,38 @@ function runMemoryMetadata(agentId, body, selectedModel, runId) {
|
|
|
3189
3312
|
metadata.studioRunId = runId;
|
|
3190
3313
|
return metadata;
|
|
3191
3314
|
}
|
|
3192
|
-
function
|
|
3193
|
-
const
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3315
|
+
function createRunExecution(props) {
|
|
3316
|
+
const session = props.session;
|
|
3317
|
+
if (session !== void 0 && props.runAgent.memory !== void 0) {
|
|
3318
|
+
return {
|
|
3319
|
+
generate: (options) => props.runAgent.generate({
|
|
3320
|
+
prompt: props.promptMessage,
|
|
3321
|
+
session: { sessionId: session.id, metadata: props.memoryMetadata },
|
|
3322
|
+
...options
|
|
3323
|
+
}),
|
|
3324
|
+
stream: (options) => props.runAgent.stream({
|
|
3325
|
+
prompt: props.promptMessage,
|
|
3326
|
+
session: { sessionId: session.id, metadata: props.memoryMetadata },
|
|
3327
|
+
...options
|
|
3328
|
+
})
|
|
3329
|
+
};
|
|
3202
3330
|
}
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3331
|
+
const transcript = session !== void 0 ? [...session.messages, props.promptMessage] : props.body.messages;
|
|
3332
|
+
return {
|
|
3333
|
+
generate: (options) => props.runAgent.generate({ messages: transcript, ...options }),
|
|
3334
|
+
stream: (options) => props.runAgent.stream({ messages: transcript, ...options })
|
|
3335
|
+
};
|
|
3336
|
+
}
|
|
3337
|
+
function createRunOptions(body, agentId, session, abortSignal) {
|
|
3338
|
+
const options = { abortSignal };
|
|
3339
|
+
if (body.maxTurns !== void 0) options.maxTurns = body.maxTurns;
|
|
3340
|
+
if (body.toolConcurrency !== void 0) options.toolConcurrency = body.toolConcurrency;
|
|
3341
|
+
if (body.trace !== void 0) {
|
|
3342
|
+
options.trace = traceForRun(body.trace, agentId, session);
|
|
3343
|
+
} else if (session !== void 0) {
|
|
3344
|
+
options.trace = traceForRun(void 0, agentId, session);
|
|
3207
3345
|
}
|
|
3208
|
-
return
|
|
3346
|
+
return options;
|
|
3209
3347
|
}
|
|
3210
3348
|
function handleStreamingAgentRun(c, run, props) {
|
|
3211
3349
|
const runtimeEvents = new AsyncEventQueue();
|
|
@@ -3216,7 +3354,6 @@ function handleStreamingAgentRun(c, run, props) {
|
|
|
3216
3354
|
};
|
|
3217
3355
|
if (run.session !== void 0) approvalContext.sessionId = run.session.id;
|
|
3218
3356
|
if (run.body.metadata !== void 0) approvalContext.metadata = run.body.metadata;
|
|
3219
|
-
run.request.approvals(props.approvalRuntime.createApprovals(approvalContext));
|
|
3220
3357
|
const questionContext = {
|
|
3221
3358
|
runId: run.runId,
|
|
3222
3359
|
agentId: run.agentId,
|
|
@@ -3224,14 +3361,20 @@ function handleStreamingAgentRun(c, run, props) {
|
|
|
3224
3361
|
};
|
|
3225
3362
|
if (run.session !== void 0) questionContext.sessionId = run.session.id;
|
|
3226
3363
|
if (run.body.metadata !== void 0) questionContext.metadata = run.body.metadata;
|
|
3227
|
-
const effectiveHook =
|
|
3228
|
-
|
|
3229
|
-
|
|
3364
|
+
const effectiveHook = props.questionRuntime.createHook(questionContext);
|
|
3365
|
+
const streamOptions = withInternalAgentRunOptions(
|
|
3366
|
+
{ ...run.options },
|
|
3367
|
+
{ hook: effectiveHook, runId: run.runId }
|
|
3368
|
+
);
|
|
3369
|
+
const runStream = mergeRunAndApprovalEvents(
|
|
3370
|
+
resumeStreamingApprovals(
|
|
3371
|
+
run.runAgent,
|
|
3372
|
+
run.execution.stream(streamOptions),
|
|
3373
|
+
props.approvalRuntime,
|
|
3374
|
+
approvalContext
|
|
3375
|
+
),
|
|
3376
|
+
runtimeEvents
|
|
3230
3377
|
);
|
|
3231
|
-
if (effectiveHook !== void 0) {
|
|
3232
|
-
run.request.withHook(effectiveHook);
|
|
3233
|
-
}
|
|
3234
|
-
const runStream = mergeRunAndApprovalEvents(run.request.stream(), runtimeEvents);
|
|
3235
3378
|
let stream = runStream;
|
|
3236
3379
|
let persistedRun;
|
|
3237
3380
|
if (run.session !== void 0 && run.sessionStore !== void 0) {
|
|
@@ -3245,7 +3388,7 @@ function handleStreamingAgentRun(c, run, props) {
|
|
|
3245
3388
|
}),
|
|
3246
3389
|
store: run.sessionStore,
|
|
3247
3390
|
session: run.session,
|
|
3248
|
-
message: run.body.
|
|
3391
|
+
message: run.body.messages.at(-1),
|
|
3249
3392
|
runId: run.runId,
|
|
3250
3393
|
startedAt: run.runStartedAt,
|
|
3251
3394
|
persistGeneratedMessages: run.shouldPersistSessionMessages
|
|
@@ -3253,6 +3396,7 @@ function handleStreamingAgentRun(c, run, props) {
|
|
|
3253
3396
|
stream = persistedRun.events;
|
|
3254
3397
|
}
|
|
3255
3398
|
return streamAgentRunEvents(c, stream, {
|
|
3399
|
+
runId: run.runId,
|
|
3256
3400
|
onCancel: async () => {
|
|
3257
3401
|
props.approvalRuntime.cancelRun(run.runId);
|
|
3258
3402
|
props.questionRuntime.cancelRun(run.runId);
|
|
@@ -3274,8 +3418,14 @@ function handleStreamingAgentRun(c, run, props) {
|
|
|
3274
3418
|
}
|
|
3275
3419
|
async function handleBufferedAgentRun(c, run, props) {
|
|
3276
3420
|
try {
|
|
3277
|
-
await startBufferedSessionRun(run, props);
|
|
3278
|
-
|
|
3421
|
+
const runtimeOptions = await startBufferedSessionRun(run, props);
|
|
3422
|
+
let result = await run.execution.generate(runtimeOptions);
|
|
3423
|
+
const approvalContext = createApprovalContext(run);
|
|
3424
|
+
while (result.status === "approval_required") {
|
|
3425
|
+
const decision = await props.approvalRuntime.request(approvalContext, result.approval);
|
|
3426
|
+
result = await run.runAgent.resume(result, decision);
|
|
3427
|
+
}
|
|
3428
|
+
const response = result;
|
|
3279
3429
|
await completeBufferedSessionRun(run, response);
|
|
3280
3430
|
return c.json(response);
|
|
3281
3431
|
} catch (error) {
|
|
@@ -3294,19 +3444,55 @@ async function startBufferedSessionRun(run, props) {
|
|
|
3294
3444
|
};
|
|
3295
3445
|
if (run.session !== void 0) questionContext.sessionId = run.session.id;
|
|
3296
3446
|
if (run.body.metadata !== void 0) questionContext.metadata = run.body.metadata;
|
|
3297
|
-
const effectiveHook =
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3447
|
+
const effectiveHook = props.questionRuntime.createHook(questionContext);
|
|
3448
|
+
const internalOptions = {
|
|
3449
|
+
hook: effectiveHook,
|
|
3450
|
+
onFailure: ({ messages }) => {
|
|
3451
|
+
run.failureMessages = structuredClone(messages);
|
|
3452
|
+
},
|
|
3453
|
+
runId: run.runId
|
|
3454
|
+
};
|
|
3455
|
+
if (run.session !== void 0 && run.sessionStore !== void 0) {
|
|
3456
|
+
const sessionId = run.session.id;
|
|
3457
|
+
const sessionStore = run.sessionStore;
|
|
3458
|
+
internalOptions.onMemoryCompaction = async (compaction) => {
|
|
3459
|
+
await appendSessionLog(
|
|
3460
|
+
sessionStore,
|
|
3461
|
+
memoryCompactedLog({
|
|
3462
|
+
sessionId,
|
|
3463
|
+
runId: run.runId,
|
|
3464
|
+
...compaction
|
|
3465
|
+
})
|
|
3466
|
+
);
|
|
3467
|
+
run.memoryCompactionLogged = true;
|
|
3468
|
+
};
|
|
3469
|
+
}
|
|
3470
|
+
return withInternalAgentRunOptions({ ...run.options }, internalOptions);
|
|
3471
|
+
}
|
|
3472
|
+
function createApprovalContext(run, emit) {
|
|
3473
|
+
const context = {
|
|
3302
3474
|
runId: run.runId,
|
|
3303
3475
|
agentId: run.agentId
|
|
3304
3476
|
};
|
|
3305
|
-
if (run.session !== void 0)
|
|
3306
|
-
if (run.body.metadata !== void 0)
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3477
|
+
if (run.session !== void 0) context.sessionId = run.session.id;
|
|
3478
|
+
if (run.body.metadata !== void 0) context.metadata = run.body.metadata;
|
|
3479
|
+
if (emit !== void 0) context.emit = emit;
|
|
3480
|
+
return context;
|
|
3481
|
+
}
|
|
3482
|
+
async function* resumeStreamingApprovals(agent, initialStream, approvalRuntime, context) {
|
|
3483
|
+
let stream = initialStream;
|
|
3484
|
+
while (true) {
|
|
3485
|
+
let pending;
|
|
3486
|
+
for await (const event of stream) {
|
|
3487
|
+
if (event.type === "approval_required") {
|
|
3488
|
+
pending = event;
|
|
3489
|
+
break;
|
|
3490
|
+
}
|
|
3491
|
+
yield event;
|
|
3492
|
+
}
|
|
3493
|
+
if (pending === void 0) return;
|
|
3494
|
+
const decision = await approvalRuntime.request(context, pending.approval);
|
|
3495
|
+
stream = agent.resume(pending, decision);
|
|
3310
3496
|
}
|
|
3311
3497
|
}
|
|
3312
3498
|
async function completeBufferedSessionRun(run, response) {
|
|
@@ -3317,7 +3503,7 @@ async function completeBufferedSessionRun(run, response) {
|
|
|
3317
3503
|
const generatedMessages = response.messages.slice(1);
|
|
3318
3504
|
if (generatedMessages.length > 0) {
|
|
3319
3505
|
await run.sessionStore.append({
|
|
3320
|
-
|
|
3506
|
+
scope: { sessionId: run.session.id, metadata: run.memoryMetadata },
|
|
3321
3507
|
runId: run.runId,
|
|
3322
3508
|
turn: 1,
|
|
3323
3509
|
messages: generatedMessages
|
|
@@ -3330,10 +3516,21 @@ async function completeBufferedSessionRun(run, response) {
|
|
|
3330
3516
|
await run.sessionStore.saveSessionRunTranscript({
|
|
3331
3517
|
id: run.session.id,
|
|
3332
3518
|
runId: run.runId,
|
|
3333
|
-
...optionalTitle(run.body.
|
|
3519
|
+
...optionalTitle(run.body.messages.at(-1)),
|
|
3334
3520
|
transcript,
|
|
3335
3521
|
status: "success"
|
|
3336
3522
|
});
|
|
3523
|
+
if (response.memoryCompaction !== void 0 && !run.memoryCompactionLogged) {
|
|
3524
|
+
await appendSessionLog(
|
|
3525
|
+
run.sessionStore,
|
|
3526
|
+
memoryCompactedLog({
|
|
3527
|
+
sessionId: run.session.id,
|
|
3528
|
+
runId: run.runId,
|
|
3529
|
+
...response.memoryCompaction
|
|
3530
|
+
})
|
|
3531
|
+
);
|
|
3532
|
+
run.memoryCompactionLogged = true;
|
|
3533
|
+
}
|
|
3337
3534
|
await appendSessionLog(
|
|
3338
3535
|
run.sessionStore,
|
|
3339
3536
|
runCompletedLog({
|
|
@@ -3341,7 +3538,7 @@ async function completeBufferedSessionRun(run, response) {
|
|
|
3341
3538
|
runId: run.runId,
|
|
3342
3539
|
durationMs: durationMs2,
|
|
3343
3540
|
usage: response.usage,
|
|
3344
|
-
output: response.
|
|
3541
|
+
output: response.text,
|
|
3345
3542
|
messageCount: response.messages.length
|
|
3346
3543
|
})
|
|
3347
3544
|
);
|
|
@@ -3358,17 +3555,14 @@ async function failBufferedSessionRun(run, error) {
|
|
|
3358
3555
|
if (run.session === void 0 || run.sessionStore === void 0) {
|
|
3359
3556
|
return;
|
|
3360
3557
|
}
|
|
3361
|
-
const messages = await run.sessionStore.load({
|
|
3362
|
-
sessionId: run.session.id,
|
|
3363
|
-
metadata: run.memoryMetadata
|
|
3364
|
-
});
|
|
3365
3558
|
const durationMs2 = Date.now() - run.runStartedAt;
|
|
3366
|
-
const
|
|
3559
|
+
const messages = run.failureMessages ?? [run.body.messages.at(-1)];
|
|
3560
|
+
const transcript = transcriptFromMessages([...messages]);
|
|
3367
3561
|
assignTranscriptRunDuration(transcript, durationMs2);
|
|
3368
3562
|
await run.sessionStore.saveSessionRunTranscript({
|
|
3369
3563
|
id: run.session.id,
|
|
3370
3564
|
runId: run.runId,
|
|
3371
|
-
...optionalTitle(run.body.
|
|
3565
|
+
...optionalTitle(run.body.messages.at(-1)),
|
|
3372
3566
|
transcript,
|
|
3373
3567
|
status: "error",
|
|
3374
3568
|
error: serializeError(error)
|
|
@@ -3378,14 +3572,14 @@ async function failBufferedSessionRun(run, error) {
|
|
|
3378
3572
|
runFailedLog(run.session.id, run.runId, error, run.runStartedAt)
|
|
3379
3573
|
);
|
|
3380
3574
|
}
|
|
3381
|
-
function normalizePromptMessage(message) {
|
|
3382
|
-
return typeof message === "string" ? Message.user(message) : message;
|
|
3383
|
-
}
|
|
3384
3575
|
function usesStoreAsAgentMemory(agent, store) {
|
|
3385
3576
|
const memoryStore = agent.memory?.store;
|
|
3386
3577
|
return memoryStore !== void 0 && rawObservedStore(memoryStore) === rawObservedStore(store);
|
|
3387
3578
|
}
|
|
3388
3579
|
|
|
3580
|
+
// src/runtime/approvals.ts
|
|
3581
|
+
import { getAgentApprovalRequestDetails } from "@anvia/core/internal/agent";
|
|
3582
|
+
|
|
3389
3583
|
// src/runtime/query.ts
|
|
3390
3584
|
function optionalQueryString(value) {
|
|
3391
3585
|
const trimmed = value?.trim();
|
|
@@ -3491,22 +3685,11 @@ function createApprovalRuntime() {
|
|
|
3491
3685
|
const approvals = /* @__PURE__ */ new Map();
|
|
3492
3686
|
return {
|
|
3493
3687
|
approvals,
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
internalCallId: request.internalCallId,
|
|
3500
|
-
args: request.rawArgs
|
|
3501
|
-
};
|
|
3502
|
-
if (request.toolCallId !== void 0) approvalRequest.toolCallId = request.toolCallId;
|
|
3503
|
-
if (request.reason !== void 0) approvalRequest.reason = request.reason;
|
|
3504
|
-
if (request.rejectMessage !== void 0) {
|
|
3505
|
-
approvalRequest.rejectMessage = request.rejectMessage;
|
|
3506
|
-
}
|
|
3507
|
-
const decision = await requestApproval(approvals, context, approvalRequest);
|
|
3508
|
-
return approvalDecision(decision.approved, decision.reason);
|
|
3509
|
-
}
|
|
3688
|
+
async request(context, approval) {
|
|
3689
|
+
const decision = await requestApproval(approvals, context, approval);
|
|
3690
|
+
return decision.approved ? { approved: true, ...decision.reason === void 0 ? {} : { reason: decision.reason } } : {
|
|
3691
|
+
approved: false,
|
|
3692
|
+
...decision.reason === void 0 ? {} : { reason: decision.reason }
|
|
3510
3693
|
};
|
|
3511
3694
|
},
|
|
3512
3695
|
list(options) {
|
|
@@ -3567,14 +3750,15 @@ function createApprovalRuntime() {
|
|
|
3567
3750
|
};
|
|
3568
3751
|
}
|
|
3569
3752
|
async function requestApproval(approvals, context, request) {
|
|
3570
|
-
const id =
|
|
3753
|
+
const id = request.id;
|
|
3754
|
+
const details = getAgentApprovalRequestDetails(request);
|
|
3571
3755
|
const approval = {
|
|
3572
3756
|
id,
|
|
3573
3757
|
runId: context.runId,
|
|
3574
3758
|
agentId: context.agentId,
|
|
3575
3759
|
toolName: request.toolName,
|
|
3576
|
-
internalCallId: request.
|
|
3577
|
-
args: request.
|
|
3760
|
+
internalCallId: details?.internalCallId ?? request.id,
|
|
3761
|
+
args: details?.rawArgs ?? JSON.stringify(request.input) ?? "null",
|
|
3578
3762
|
status: "pending",
|
|
3579
3763
|
requestedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3580
3764
|
resolve: () => {
|
|
@@ -3583,7 +3767,7 @@ async function requestApproval(approvals, context, request) {
|
|
|
3583
3767
|
if (context.sessionId !== void 0) approval.sessionId = context.sessionId;
|
|
3584
3768
|
if (request.toolCallId !== void 0) approval.callId = request.toolCallId;
|
|
3585
3769
|
if (request.reason !== void 0) approval.reason = request.reason;
|
|
3586
|
-
if (
|
|
3770
|
+
if (details?.rejectMessage !== void 0) approval.rejectMessage = details.rejectMessage;
|
|
3587
3771
|
if (context.emit !== void 0) approval.emit = context.emit;
|
|
3588
3772
|
const decision = new Promise((resolve2) => {
|
|
3589
3773
|
approval.resolve = (decision2) => {
|
|
@@ -3594,7 +3778,7 @@ async function requestApproval(approvals, context, request) {
|
|
|
3594
3778
|
}
|
|
3595
3779
|
return;
|
|
3596
3780
|
}
|
|
3597
|
-
const reason = decision2.approved ? decision2.reason : decision2.reason ??
|
|
3781
|
+
const reason = decision2.approved ? decision2.reason : decision2.reason ?? details?.rejectMessage ?? "Rejected in Anvia Studio.";
|
|
3598
3782
|
const resolved = resolveApproval(
|
|
3599
3783
|
current,
|
|
3600
3784
|
decision2.approved ? "approved" : "rejected",
|
|
@@ -3712,242 +3896,8 @@ function isRecord2(value) {
|
|
|
3712
3896
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
3713
3897
|
}
|
|
3714
3898
|
|
|
3715
|
-
// src/runtime/tool-metadata.ts
|
|
3716
|
-
import { ToolSet } from "@anvia/core/tool";
|
|
3717
|
-
var MCP_TOOL_METADATA_KEY = /* @__PURE__ */ Symbol.for("anvia.mcp.tool.metadata");
|
|
3718
|
-
function agentToolItems(agent) {
|
|
3719
|
-
return [
|
|
3720
|
-
...agent.agent.toolSet.values().map((tool) => ({ tool, source: "static" })),
|
|
3721
|
-
...agent.agent.dynamicTools.flatMap((registration) => {
|
|
3722
|
-
const maybeToolSet = registration.index.toolSet;
|
|
3723
|
-
if (!(maybeToolSet instanceof ToolSet)) {
|
|
3724
|
-
return [];
|
|
3725
|
-
}
|
|
3726
|
-
return maybeToolSet.values().map((tool) => ({ tool, source: "dynamic" }));
|
|
3727
|
-
})
|
|
3728
|
-
];
|
|
3729
|
-
}
|
|
3730
|
-
function approvalMetadata(tool) {
|
|
3731
|
-
const approval = tool.approval;
|
|
3732
|
-
if (approval === void 0 || typeof approval !== "object" || approval === null) {
|
|
3733
|
-
return { required: false };
|
|
3734
|
-
}
|
|
3735
|
-
const policy = approval;
|
|
3736
|
-
const metadata = { required: true };
|
|
3737
|
-
if (typeof policy.reason === "string") metadata.reason = policy.reason;
|
|
3738
|
-
if (typeof policy.rejectMessage === "string") metadata.rejectMessage = policy.rejectMessage;
|
|
3739
|
-
return metadata;
|
|
3740
|
-
}
|
|
3741
|
-
function mcpServerName(tool) {
|
|
3742
|
-
const metadata = tool[MCP_TOOL_METADATA_KEY];
|
|
3743
|
-
if (typeof metadata !== "object" || metadata === null) {
|
|
3744
|
-
return void 0;
|
|
3745
|
-
}
|
|
3746
|
-
const serverName = metadata.serverName;
|
|
3747
|
-
return typeof serverName === "string" && serverName.length > 0 ? serverName : void 0;
|
|
3748
|
-
}
|
|
3749
|
-
function agentHasMcpTools(agent) {
|
|
3750
|
-
return agentToolItems(agent).some(({ tool }) => mcpServerName(tool) !== void 0);
|
|
3751
|
-
}
|
|
3752
|
-
|
|
3753
|
-
// src/runtime/config.ts
|
|
3754
|
-
function runnerId(options) {
|
|
3755
|
-
return options.id ?? "anvia-studio";
|
|
3756
|
-
}
|
|
3757
|
-
function agentConfig(agent) {
|
|
3758
|
-
const name = agent.name ?? agent.agent.name;
|
|
3759
|
-
const description = agent.description ?? agent.agent.description;
|
|
3760
|
-
const config = {
|
|
3761
|
-
id: agent.id,
|
|
3762
|
-
quickPrompts: agent.quickPrompts ?? []
|
|
3763
|
-
};
|
|
3764
|
-
if (name !== void 0) config.name = name;
|
|
3765
|
-
if (description !== void 0) config.description = description;
|
|
3766
|
-
if (agent.metadata !== void 0) config.metadata = agent.metadata;
|
|
3767
|
-
return config;
|
|
3768
|
-
}
|
|
3769
|
-
function agentRuntimeSummary(agent) {
|
|
3770
|
-
const tools = agentToolItems(agent);
|
|
3771
|
-
const name = agent.name ?? agent.agent.name;
|
|
3772
|
-
const description = agent.description ?? agent.agent.description;
|
|
3773
|
-
const summary = {
|
|
3774
|
-
id: agent.id,
|
|
3775
|
-
model: toJsonValue2(agent.agent.model),
|
|
3776
|
-
toolCount: tools.length,
|
|
3777
|
-
staticToolCount: tools.filter((item) => item.source === "static").length,
|
|
3778
|
-
dynamicToolCount: tools.filter((item) => item.source === "dynamic").length,
|
|
3779
|
-
approvalToolCount: tools.filter((item) => item.tool.approval !== void 0).length,
|
|
3780
|
-
mcpToolCount: tools.filter((item) => mcpServerName(item.tool) !== void 0).length,
|
|
3781
|
-
staticContextCount: agent.agent.staticContext.length,
|
|
3782
|
-
dynamicContextCount: agent.agent.dynamicContexts.length,
|
|
3783
|
-
observerCount: agent.agent.observers.length,
|
|
3784
|
-
hasMemory: agent.agent.memory !== void 0,
|
|
3785
|
-
hasHook: agent.agent.hook !== void 0,
|
|
3786
|
-
hasOutputSchema: agent.agent.outputSchema !== void 0
|
|
3787
|
-
};
|
|
3788
|
-
if (name !== void 0) summary.name = name;
|
|
3789
|
-
if (description !== void 0) summary.description = description;
|
|
3790
|
-
if (agent.agent.defaultMaxTurns !== void 0) {
|
|
3791
|
-
summary.defaultMaxTurns = agent.agent.defaultMaxTurns;
|
|
3792
|
-
}
|
|
3793
|
-
if (agent.metadata !== void 0) summary.metadata = agent.metadata;
|
|
3794
|
-
return summary;
|
|
3795
|
-
}
|
|
3796
|
-
function pipelineConfig(pipeline) {
|
|
3797
|
-
const graph = pipeline.pipeline.graph();
|
|
3798
|
-
const stageNodes = graph.nodes.filter((node) => node.kind !== "input" && node.kind !== "output");
|
|
3799
|
-
const config = {
|
|
3800
|
-
id: pipeline.id,
|
|
3801
|
-
stageCount: stageNodes.length,
|
|
3802
|
-
edgeCount: graph.edges.length,
|
|
3803
|
-
hasParallelStages: graph.nodes.some((node) => node.kind === "parallel"),
|
|
3804
|
-
agentCount: graph.nodes.filter((node) => node.kind === "agent").length,
|
|
3805
|
-
extractorCount: graph.nodes.filter((node) => node.kind === "extractor").length
|
|
3806
|
-
};
|
|
3807
|
-
if (pipeline.name !== void 0) config.name = pipeline.name;
|
|
3808
|
-
if (pipeline.description !== void 0) config.description = pipeline.description;
|
|
3809
|
-
if (pipeline.metadata !== void 0) config.metadata = pipeline.metadata;
|
|
3810
|
-
return config;
|
|
3811
|
-
}
|
|
3812
|
-
function buildConfig(options, agents, pipelines, stores, sandboxCount = 0) {
|
|
3813
|
-
const models = options.models === void 0 ? void 0 : studioModelsConfig(createStudioModelRegistry(options.models), agents);
|
|
3814
|
-
const config = {
|
|
3815
|
-
id: runnerId(options),
|
|
3816
|
-
agents: agents.map(agentConfig),
|
|
3817
|
-
pipelines: pipelines.map(pipelineConfig),
|
|
3818
|
-
evals: options.evals.map(evalConfig),
|
|
3819
|
-
chat: {
|
|
3820
|
-
quickPrompts: Object.fromEntries(agents.map((agent) => [agent.id, agent.quickPrompts ?? []]))
|
|
3821
|
-
},
|
|
3822
|
-
capabilities: capabilityConfig(options, agents, pipelines, stores, sandboxCount),
|
|
3823
|
-
unsupportedCapabilities: unsupportedCapabilities(stores)
|
|
3824
|
-
};
|
|
3825
|
-
if (options.name !== void 0) config.name = options.name;
|
|
3826
|
-
if (options.description !== void 0) config.description = options.description;
|
|
3827
|
-
if (options.version !== void 0) config.version = options.version;
|
|
3828
|
-
if (models !== void 0) config.models = models;
|
|
3829
|
-
return config;
|
|
3830
|
-
}
|
|
3831
|
-
function capabilityConfig(_options, agents, pipelines, stores, sandboxCount = 0) {
|
|
3832
|
-
const capabilities = {
|
|
3833
|
-
agents: { enabled: true },
|
|
3834
|
-
observability: { enabled: true },
|
|
3835
|
-
status: { enabled: true }
|
|
3836
|
-
};
|
|
3837
|
-
if (stores.sessions !== void 0) {
|
|
3838
|
-
capabilities.sessions = { enabled: true };
|
|
3839
|
-
}
|
|
3840
|
-
if (stores.sessions !== void 0 || agents.some((agent) => agent.agent.memory !== void 0)) {
|
|
3841
|
-
capabilities.memory = { enabled: true };
|
|
3842
|
-
}
|
|
3843
|
-
if (stores.traces !== void 0) {
|
|
3844
|
-
capabilities.traces = { enabled: true };
|
|
3845
|
-
}
|
|
3846
|
-
if (pipelines.length > 0) {
|
|
3847
|
-
capabilities.pipelines = { enabled: true };
|
|
3848
|
-
}
|
|
3849
|
-
if (_options.evals.length > 0) {
|
|
3850
|
-
capabilities.evals = { enabled: true };
|
|
3851
|
-
}
|
|
3852
|
-
if (agents.some(
|
|
3853
|
-
(agent) => agent.agent.toolSet.values().length > 0 || agent.agent.dynamicTools.length > 0
|
|
3854
|
-
)) {
|
|
3855
|
-
capabilities.tools = { enabled: true };
|
|
3856
|
-
}
|
|
3857
|
-
if (agents.some(agentHasMcpTools)) {
|
|
3858
|
-
capabilities.mcps = { enabled: true };
|
|
3859
|
-
}
|
|
3860
|
-
if (sandboxCount > 0) {
|
|
3861
|
-
capabilities.sandboxes = { enabled: true };
|
|
3862
|
-
}
|
|
3863
|
-
if (agents.some(
|
|
3864
|
-
(agent) => agent.agent.hook !== void 0 || agent.agent.toolSet.values().some((tool) => tool.approval)
|
|
3865
|
-
)) {
|
|
3866
|
-
capabilities.approvals = { enabled: true };
|
|
3867
|
-
}
|
|
3868
|
-
if (agents.some(
|
|
3869
|
-
(agent) => agent.agent.staticContext.length > 0 || agent.agent.dynamicContexts.length > 0 || agent.agent.dynamicTools.length > 0
|
|
3870
|
-
)) {
|
|
3871
|
-
capabilities.knowledge = { enabled: true };
|
|
3872
|
-
}
|
|
3873
|
-
return capabilities;
|
|
3874
|
-
}
|
|
3875
|
-
function unsupportedCapabilities(stores) {
|
|
3876
|
-
const capabilities = [];
|
|
3877
|
-
if (stores.sessions === void 0) capabilities.push("sessions");
|
|
3878
|
-
if (stores.traces === void 0) capabilities.push("traces");
|
|
3879
|
-
return capabilities;
|
|
3880
|
-
}
|
|
3881
|
-
function toJsonValue2(value) {
|
|
3882
|
-
return serializeUnknown(value);
|
|
3883
|
-
}
|
|
3884
|
-
|
|
3885
|
-
// src/runtime/evals.ts
|
|
3886
|
-
import { runEvalSuite } from "@anvia/core/evals";
|
|
3887
|
-
function registerEvalRoutes(app, props) {
|
|
3888
|
-
app.get(
|
|
3889
|
-
"/evals",
|
|
3890
|
-
(c) => c.json({
|
|
3891
|
-
evals: props.evals.map(evalConfig)
|
|
3892
|
-
})
|
|
3893
|
-
);
|
|
3894
|
-
app.get("/evals/:evalId", (c) => {
|
|
3895
|
-
const suite = props.evalMap.get(c.req.param("evalId"));
|
|
3896
|
-
if (suite === void 0) {
|
|
3897
|
-
return errorResponse(c, 404, "not_found", "Eval suite not found");
|
|
3898
|
-
}
|
|
3899
|
-
return c.json(evalConfig(suite));
|
|
3900
|
-
});
|
|
3901
|
-
app.post("/evals/:evalId/runs", async (c) => {
|
|
3902
|
-
const suite = props.evalMap.get(c.req.param("evalId"));
|
|
3903
|
-
if (suite === void 0) {
|
|
3904
|
-
return errorResponse(c, 404, "not_found", "Eval suite not found");
|
|
3905
|
-
}
|
|
3906
|
-
const body = await parseEvalRunRequest(c);
|
|
3907
|
-
if ("error" in body) {
|
|
3908
|
-
return body.error;
|
|
3909
|
-
}
|
|
3910
|
-
const runId = globalThis.crypto.randomUUID();
|
|
3911
|
-
const startedAt = Date.now();
|
|
3912
|
-
const runOptions = { ...suite };
|
|
3913
|
-
if (body.concurrency !== void 0) runOptions.concurrency = body.concurrency;
|
|
3914
|
-
const result = await runEvalSuite(runOptions);
|
|
3915
|
-
const endedAt = Date.now();
|
|
3916
|
-
const jsonResult = toJsonValue(result);
|
|
3917
|
-
const response = {
|
|
3918
|
-
runId,
|
|
3919
|
-
suiteId: suite.id ?? suite.name,
|
|
3920
|
-
startedAt: new Date(startedAt).toISOString(),
|
|
3921
|
-
endedAt: new Date(endedAt).toISOString(),
|
|
3922
|
-
durationMs: endedAt - startedAt,
|
|
3923
|
-
result: isJsonObject(jsonResult) ? jsonResult : { value: jsonResult }
|
|
3924
|
-
};
|
|
3925
|
-
return c.json(response);
|
|
3926
|
-
});
|
|
3927
|
-
}
|
|
3928
|
-
async function parseEvalRunRequest(c) {
|
|
3929
|
-
let body = {};
|
|
3930
|
-
try {
|
|
3931
|
-
body = await c.req.json();
|
|
3932
|
-
} catch {
|
|
3933
|
-
body = {};
|
|
3934
|
-
}
|
|
3935
|
-
if (!isObject(body)) {
|
|
3936
|
-
return { error: errorResponse(c, 400, "bad_request", "Request body must be an object") };
|
|
3937
|
-
}
|
|
3938
|
-
const request = {};
|
|
3939
|
-
if ("concurrency" in body) {
|
|
3940
|
-
if (!isPositiveInteger(body.concurrency)) {
|
|
3941
|
-
return {
|
|
3942
|
-
error: errorResponse(c, 400, "bad_request", "concurrency must be a positive integer")
|
|
3943
|
-
};
|
|
3944
|
-
}
|
|
3945
|
-
request.concurrency = body.concurrency;
|
|
3946
|
-
}
|
|
3947
|
-
return request;
|
|
3948
|
-
}
|
|
3949
|
-
|
|
3950
3899
|
// src/runtime/knowledge.ts
|
|
3900
|
+
import { getAgentToolState } from "@anvia/core/internal/agent";
|
|
3951
3901
|
function registerKnowledgeRoutes(app, props) {
|
|
3952
3902
|
app.get("/knowledge", async (c) => {
|
|
3953
3903
|
const limit = parseLimit(c.req.query("limit"));
|
|
@@ -3984,12 +3934,17 @@ function registerKnowledgeRoutes(app, props) {
|
|
|
3984
3934
|
return c.json(page);
|
|
3985
3935
|
});
|
|
3986
3936
|
}
|
|
3937
|
+
function agentHasKnowledge(agent) {
|
|
3938
|
+
const toolIndexes = getAgentToolState(agent.agent).toolIndexes;
|
|
3939
|
+
return agent.agent.context.length > 0 || toolIndexes.length > 0;
|
|
3940
|
+
}
|
|
3987
3941
|
async function agentKnowledgeConfig(agent) {
|
|
3988
3942
|
const agentName = agent.name ?? agent.agent.name;
|
|
3943
|
+
const staticContext = staticContextDocuments(agent.agent);
|
|
3989
3944
|
const config = {
|
|
3990
3945
|
agentId: agent.id,
|
|
3991
3946
|
sources: await knowledgeSources(agent),
|
|
3992
|
-
staticContext:
|
|
3947
|
+
staticContext: staticContext.map((document) => {
|
|
3993
3948
|
const item = { id: document.id, text: document.text };
|
|
3994
3949
|
if (document.additionalProps !== void 0) {
|
|
3995
3950
|
item.additionalProps = jsonObjectFromRecord(document.additionalProps);
|
|
@@ -4001,51 +3956,54 @@ async function agentKnowledgeConfig(agent) {
|
|
|
4001
3956
|
return config;
|
|
4002
3957
|
}
|
|
4003
3958
|
async function knowledgeSources(agent) {
|
|
3959
|
+
const toolIndexes = getAgentToolState(agent.agent).toolIndexes;
|
|
3960
|
+
const staticContext = staticContextDocuments(agent.agent);
|
|
3961
|
+
const indexedContext = vectorContexts(agent.agent);
|
|
4004
3962
|
const sources = [
|
|
4005
3963
|
{
|
|
4006
3964
|
sourceId: staticSourceId(),
|
|
4007
3965
|
kind: "static_context",
|
|
4008
3966
|
label: "Static context",
|
|
4009
|
-
count:
|
|
3967
|
+
count: staticContext.length,
|
|
4010
3968
|
inspectable: true,
|
|
4011
|
-
itemCount:
|
|
3969
|
+
itemCount: staticContext.length
|
|
4012
3970
|
}
|
|
4013
3971
|
];
|
|
4014
3972
|
const dynamicContextSources = await Promise.all(
|
|
4015
|
-
|
|
4016
|
-
const inspect = inspectFn(
|
|
4017
|
-
const count = await inspectableCount(inspect,
|
|
3973
|
+
indexedContext.map(async (vectorContext, index) => {
|
|
3974
|
+
const inspect = inspectFn(vectorContext.store);
|
|
3975
|
+
const count = await inspectableCount(inspect, vectorContext.filter);
|
|
4018
3976
|
const source = {
|
|
4019
3977
|
sourceId: dynamicContextSourceId(index),
|
|
4020
3978
|
kind: "dynamic_context",
|
|
4021
3979
|
label: `Dynamic context ${index + 1}`,
|
|
4022
3980
|
count: 1,
|
|
4023
3981
|
registrationIndex: index,
|
|
4024
|
-
topK:
|
|
3982
|
+
topK: vectorContext.topK,
|
|
4025
3983
|
inspectable: inspect !== void 0
|
|
4026
3984
|
};
|
|
4027
|
-
if (
|
|
4028
|
-
source.
|
|
3985
|
+
if (vectorContext.minScore !== void 0) {
|
|
3986
|
+
source.minScore = vectorContext.minScore;
|
|
4029
3987
|
}
|
|
4030
3988
|
if (count !== void 0) source.itemCount = count;
|
|
4031
3989
|
return source;
|
|
4032
3990
|
})
|
|
4033
3991
|
);
|
|
4034
3992
|
const dynamicToolSources = await Promise.all(
|
|
4035
|
-
|
|
4036
|
-
const inspect = inspectFn(
|
|
4037
|
-
const count = await inspectableCount(inspect,
|
|
3993
|
+
toolIndexes.map(async (toolIndex, index) => {
|
|
3994
|
+
const inspect = inspectFn(toolIndex);
|
|
3995
|
+
const count = await inspectableCount(inspect, toolIndex.filter);
|
|
4038
3996
|
const source = {
|
|
4039
3997
|
sourceId: dynamicToolsSourceId(index),
|
|
4040
3998
|
kind: "dynamic_tools",
|
|
4041
3999
|
label: `Dynamic tools ${index + 1}`,
|
|
4042
4000
|
count: 1,
|
|
4043
4001
|
registrationIndex: index,
|
|
4044
|
-
topK:
|
|
4002
|
+
topK: toolIndex.topK,
|
|
4045
4003
|
inspectable: inspect !== void 0
|
|
4046
4004
|
};
|
|
4047
|
-
if (
|
|
4048
|
-
source.
|
|
4005
|
+
if (toolIndex.minScore !== void 0) {
|
|
4006
|
+
source.minScore = toolIndex.minScore;
|
|
4049
4007
|
}
|
|
4050
4008
|
if (count !== void 0) source.itemCount = count;
|
|
4051
4009
|
return source;
|
|
@@ -4064,20 +4022,20 @@ async function knowledgeItemsPage(agent, sourceId, request) {
|
|
|
4064
4022
|
if (sourceId === staticSourceId()) {
|
|
4065
4023
|
return staticKnowledgeItemsPage(agent, request);
|
|
4066
4024
|
}
|
|
4067
|
-
const
|
|
4068
|
-
if (
|
|
4069
|
-
const
|
|
4070
|
-
if (
|
|
4025
|
+
const vectorContextIndex = dynamicSourceIndex(sourceId, "dynamic_context");
|
|
4026
|
+
if (vectorContextIndex !== void 0) {
|
|
4027
|
+
const vectorContext = vectorContexts(agent.agent)[vectorContextIndex];
|
|
4028
|
+
if (vectorContext === void 0) {
|
|
4071
4029
|
return void 0;
|
|
4072
4030
|
}
|
|
4073
|
-
const inspect = inspectFn(
|
|
4031
|
+
const inspect = inspectFn(vectorContext.store);
|
|
4074
4032
|
if (inspect === void 0) {
|
|
4075
4033
|
return nonInspectablePage(agent.id, sourceId, "dynamic_context");
|
|
4076
4034
|
}
|
|
4077
4035
|
const page = await inspect({
|
|
4078
4036
|
limit: request.limit,
|
|
4079
4037
|
cursor: request.cursor,
|
|
4080
|
-
filter:
|
|
4038
|
+
filter: vectorContext.filter
|
|
4081
4039
|
});
|
|
4082
4040
|
const result = {
|
|
4083
4041
|
agentId: agent.id,
|
|
@@ -4092,18 +4050,18 @@ async function knowledgeItemsPage(agent, sourceId, request) {
|
|
|
4092
4050
|
}
|
|
4093
4051
|
const dynamicToolsIndex = dynamicSourceIndex(sourceId, "dynamic_tools");
|
|
4094
4052
|
if (dynamicToolsIndex !== void 0) {
|
|
4095
|
-
const
|
|
4096
|
-
if (
|
|
4053
|
+
const toolIndex = getAgentToolState(agent.agent).toolIndexes[dynamicToolsIndex];
|
|
4054
|
+
if (toolIndex === void 0) {
|
|
4097
4055
|
return void 0;
|
|
4098
4056
|
}
|
|
4099
|
-
const inspect = inspectFn(
|
|
4057
|
+
const inspect = inspectFn(toolIndex);
|
|
4100
4058
|
if (inspect === void 0) {
|
|
4101
4059
|
return nonInspectablePage(agent.id, sourceId, "dynamic_tools");
|
|
4102
4060
|
}
|
|
4103
4061
|
const page = await inspect({
|
|
4104
4062
|
limit: request.limit,
|
|
4105
4063
|
cursor: request.cursor,
|
|
4106
|
-
filter:
|
|
4064
|
+
filter: toolIndex.filter
|
|
4107
4065
|
});
|
|
4108
4066
|
const result = {
|
|
4109
4067
|
agentId: agent.id,
|
|
@@ -4118,16 +4076,17 @@ async function knowledgeItemsPage(agent, sourceId, request) {
|
|
|
4118
4076
|
}
|
|
4119
4077
|
return void 0;
|
|
4120
4078
|
}
|
|
4121
|
-
function inspectFn(
|
|
4122
|
-
if (!isRecord3(
|
|
4079
|
+
function inspectFn(store) {
|
|
4080
|
+
if (!isRecord3(store) || typeof store.inspect !== "function") {
|
|
4123
4081
|
return void 0;
|
|
4124
4082
|
}
|
|
4125
|
-
const inspect =
|
|
4126
|
-
return (request) => inspect.call(
|
|
4083
|
+
const inspect = store.inspect;
|
|
4084
|
+
return (request) => inspect.call(store, request);
|
|
4127
4085
|
}
|
|
4128
4086
|
function staticKnowledgeItemsPage(agent, request) {
|
|
4087
|
+
const staticContext = staticContextDocuments(agent.agent);
|
|
4129
4088
|
const start = Math.max(0, Math.trunc(Number(request.cursor ?? "0")));
|
|
4130
|
-
const page =
|
|
4089
|
+
const page = staticContext.slice(start, start + request.limit);
|
|
4131
4090
|
const nextOffset = start + page.length;
|
|
4132
4091
|
const result = {
|
|
4133
4092
|
agentId: agent.id,
|
|
@@ -4145,9 +4104,9 @@ function staticKnowledgeItemsPage(agent, request) {
|
|
|
4145
4104
|
}
|
|
4146
4105
|
return item;
|
|
4147
4106
|
}),
|
|
4148
|
-
totalCount:
|
|
4107
|
+
totalCount: staticContext.length
|
|
4149
4108
|
};
|
|
4150
|
-
if (nextOffset <
|
|
4109
|
+
if (nextOffset < staticContext.length) result.nextCursor = String(nextOffset);
|
|
4151
4110
|
return result;
|
|
4152
4111
|
}
|
|
4153
4112
|
function nonInspectablePage(agentId, sourceId, kind) {
|
|
@@ -4275,65 +4234,299 @@ function queryFromGenerationInput(value) {
|
|
|
4275
4234
|
}
|
|
4276
4235
|
}
|
|
4277
4236
|
}
|
|
4278
|
-
return void 0;
|
|
4237
|
+
return void 0;
|
|
4238
|
+
}
|
|
4239
|
+
function messageText(value) {
|
|
4240
|
+
if (typeof value === "string") {
|
|
4241
|
+
return value.trim();
|
|
4242
|
+
}
|
|
4243
|
+
if (!isRecord3(value)) {
|
|
4244
|
+
return "";
|
|
4245
|
+
}
|
|
4246
|
+
if (typeof value.text === "string") {
|
|
4247
|
+
return value.text.trim();
|
|
4248
|
+
}
|
|
4249
|
+
if (typeof value.content === "string") {
|
|
4250
|
+
return value.content.trim();
|
|
4251
|
+
}
|
|
4252
|
+
if (Array.isArray(value.content)) {
|
|
4253
|
+
return value.content.map(contentText).filter(Boolean).join("\n").trim();
|
|
4254
|
+
}
|
|
4255
|
+
return "";
|
|
4256
|
+
}
|
|
4257
|
+
function contentText(value) {
|
|
4258
|
+
if (typeof value === "string") {
|
|
4259
|
+
return value.trim();
|
|
4260
|
+
}
|
|
4261
|
+
if (!isRecord3(value)) {
|
|
4262
|
+
return "";
|
|
4263
|
+
}
|
|
4264
|
+
if (typeof value.text === "string") {
|
|
4265
|
+
return value.text.trim();
|
|
4266
|
+
}
|
|
4267
|
+
return "";
|
|
4268
|
+
}
|
|
4269
|
+
function evidenceDocument(value) {
|
|
4270
|
+
if (!isRecord3(value)) {
|
|
4271
|
+
return [];
|
|
4272
|
+
}
|
|
4273
|
+
const id = typeof value.id === "string" ? value.id : void 0;
|
|
4274
|
+
const text = typeof value.text === "string" ? value.text : void 0;
|
|
4275
|
+
const additionalProps = isRecord3(value.additionalProps) ? jsonObjectFromRecord(value.additionalProps) : void 0;
|
|
4276
|
+
if (id === void 0 && text === void 0 && additionalProps === void 0) {
|
|
4277
|
+
return [];
|
|
4278
|
+
}
|
|
4279
|
+
const document = {};
|
|
4280
|
+
if (id !== void 0) document.id = id;
|
|
4281
|
+
if (text !== void 0) document.text = text;
|
|
4282
|
+
if (additionalProps !== void 0) document.additionalProps = additionalProps;
|
|
4283
|
+
return [document];
|
|
4284
|
+
}
|
|
4285
|
+
function evidenceToolName(value) {
|
|
4286
|
+
if (!isRecord3(value) || typeof value.name !== "string") {
|
|
4287
|
+
return [];
|
|
4288
|
+
}
|
|
4289
|
+
return [value.name];
|
|
4290
|
+
}
|
|
4291
|
+
function jsonObjectFromRecord(value) {
|
|
4292
|
+
return compactJsonObject(value);
|
|
4293
|
+
}
|
|
4294
|
+
function isRecord3(value) {
|
|
4295
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4296
|
+
}
|
|
4297
|
+
|
|
4298
|
+
// src/runtime/tool-metadata.ts
|
|
4299
|
+
import { getAgentToolState as getAgentToolState2 } from "@anvia/core/internal/agent";
|
|
4300
|
+
import { isMcpTool } from "@anvia/core/mcp";
|
|
4301
|
+
function agentToolItems(agent) {
|
|
4302
|
+
const state = getAgentToolState2(agent.agent);
|
|
4303
|
+
const items = state.staticTools.map((tool) => ({ tool, source: "static" }));
|
|
4304
|
+
const names = new Set(items.map(({ tool }) => tool.name));
|
|
4305
|
+
for (const index of state.toolIndexes) {
|
|
4306
|
+
for (const tool of index.tools) {
|
|
4307
|
+
if (!names.has(tool.name)) {
|
|
4308
|
+
names.add(tool.name);
|
|
4309
|
+
items.push({ tool, source: "dynamic" });
|
|
4310
|
+
}
|
|
4311
|
+
}
|
|
4312
|
+
}
|
|
4313
|
+
return items;
|
|
4314
|
+
}
|
|
4315
|
+
function approvalMetadata(tool) {
|
|
4316
|
+
const approval = tool.requiresApproval;
|
|
4317
|
+
if (approval === void 0 || approval === false) {
|
|
4318
|
+
return { required: false };
|
|
4319
|
+
}
|
|
4320
|
+
if (typeof approval !== "object" || approval === null) {
|
|
4321
|
+
return { required: true };
|
|
4322
|
+
}
|
|
4323
|
+
const policy = approval;
|
|
4324
|
+
const metadata = { required: true };
|
|
4325
|
+
if (typeof policy.reason === "string") metadata.reason = policy.reason;
|
|
4326
|
+
return metadata;
|
|
4327
|
+
}
|
|
4328
|
+
function toolRequiresApproval(tool) {
|
|
4329
|
+
const approval = tool.requiresApproval;
|
|
4330
|
+
return approval !== void 0 && approval !== false;
|
|
4331
|
+
}
|
|
4332
|
+
function mcpServerName(tool) {
|
|
4333
|
+
return isMcpTool(tool) ? tool.mcp.serverName : void 0;
|
|
4334
|
+
}
|
|
4335
|
+
function agentHasMcpServers(agent) {
|
|
4336
|
+
return agent.agent.mcpServers.length > 0;
|
|
4337
|
+
}
|
|
4338
|
+
|
|
4339
|
+
// src/runtime/config.ts
|
|
4340
|
+
function runnerId(options) {
|
|
4341
|
+
return options.id ?? "anvia-studio";
|
|
4342
|
+
}
|
|
4343
|
+
function agentConfig(agent) {
|
|
4344
|
+
const name = agent.name ?? agent.agent.name;
|
|
4345
|
+
const description = agent.description ?? agent.agent.description;
|
|
4346
|
+
const config = {
|
|
4347
|
+
id: agent.id,
|
|
4348
|
+
quickPrompts: agent.quickPrompts ?? []
|
|
4349
|
+
};
|
|
4350
|
+
if (name !== void 0) config.name = name;
|
|
4351
|
+
if (description !== void 0) config.description = description;
|
|
4352
|
+
if (agent.metadata !== void 0) config.metadata = agent.metadata;
|
|
4353
|
+
return config;
|
|
4354
|
+
}
|
|
4355
|
+
function agentRuntimeSummary(agent) {
|
|
4356
|
+
const tools = agentToolItems(agent);
|
|
4357
|
+
const staticContext = staticContextDocuments(agent.agent);
|
|
4358
|
+
const indexedContext = vectorContexts(agent.agent);
|
|
4359
|
+
const name = agent.name ?? agent.agent.name;
|
|
4360
|
+
const description = agent.description ?? agent.agent.description;
|
|
4361
|
+
const summary = {
|
|
4362
|
+
id: agent.id,
|
|
4363
|
+
model: toJsonValue2(agent.agent.model),
|
|
4364
|
+
toolCount: tools.length,
|
|
4365
|
+
staticToolCount: tools.filter((item) => item.source === "static").length,
|
|
4366
|
+
dynamicToolCount: tools.filter((item) => item.source === "dynamic").length,
|
|
4367
|
+
approvalToolCount: tools.filter((item) => toolRequiresApproval(item.tool)).length,
|
|
4368
|
+
mcpToolCount: tools.filter((item) => mcpServerName(item.tool) !== void 0).length,
|
|
4369
|
+
staticContextCount: staticContext.length,
|
|
4370
|
+
dynamicContextCount: indexedContext.length,
|
|
4371
|
+
observerCount: Object.keys(agent.agent.observability?.observers ?? {}).length,
|
|
4372
|
+
hasMemory: agent.agent.memory !== void 0,
|
|
4373
|
+
hasLifecycle: agent.agent.lifecycle !== void 0,
|
|
4374
|
+
hasOutputSchema: agent.agent.outputSchema !== void 0
|
|
4375
|
+
};
|
|
4376
|
+
if (name !== void 0) summary.name = name;
|
|
4377
|
+
if (description !== void 0) summary.description = description;
|
|
4378
|
+
if (agent.agent.defaultMaxTurns !== void 0) {
|
|
4379
|
+
summary.defaultMaxTurns = agent.agent.defaultMaxTurns;
|
|
4380
|
+
}
|
|
4381
|
+
if (agent.metadata !== void 0) summary.metadata = agent.metadata;
|
|
4382
|
+
return summary;
|
|
4279
4383
|
}
|
|
4280
|
-
function
|
|
4281
|
-
|
|
4282
|
-
|
|
4384
|
+
function pipelineConfig(pipeline) {
|
|
4385
|
+
const graph = pipeline.pipeline.graph();
|
|
4386
|
+
const stageNodes = graph.nodes.filter((node) => node.kind !== "input" && node.kind !== "output");
|
|
4387
|
+
const config = {
|
|
4388
|
+
id: pipeline.id,
|
|
4389
|
+
stageCount: stageNodes.length,
|
|
4390
|
+
edgeCount: graph.edges.length,
|
|
4391
|
+
hasParallelStages: graph.nodes.some((node) => node.kind === "parallel"),
|
|
4392
|
+
agentCount: graph.nodes.filter((node) => node.kind === "agent").length,
|
|
4393
|
+
extractorCount: graph.nodes.filter((node) => node.kind === "extractor").length
|
|
4394
|
+
};
|
|
4395
|
+
if (pipeline.name !== void 0) config.name = pipeline.name;
|
|
4396
|
+
if (pipeline.description !== void 0) config.description = pipeline.description;
|
|
4397
|
+
if (pipeline.metadata !== void 0) config.metadata = pipeline.metadata;
|
|
4398
|
+
return config;
|
|
4399
|
+
}
|
|
4400
|
+
function buildConfig(options, agents, pipelines, stores, sandboxCount = 0) {
|
|
4401
|
+
const models = options.models === void 0 ? void 0 : studioModelsConfig(createStudioModelRegistry(options.models), agents);
|
|
4402
|
+
const config = {
|
|
4403
|
+
id: runnerId(options),
|
|
4404
|
+
agents: agents.map(agentConfig),
|
|
4405
|
+
pipelines: pipelines.map(pipelineConfig),
|
|
4406
|
+
evals: options.evals.map(evalConfig),
|
|
4407
|
+
chat: {
|
|
4408
|
+
quickPrompts: Object.fromEntries(agents.map((agent) => [agent.id, agent.quickPrompts ?? []]))
|
|
4409
|
+
},
|
|
4410
|
+
capabilities: capabilityConfig(options, agents, pipelines, stores, sandboxCount),
|
|
4411
|
+
unsupportedCapabilities: unsupportedCapabilities(stores)
|
|
4412
|
+
};
|
|
4413
|
+
if (options.name !== void 0) config.name = options.name;
|
|
4414
|
+
if (options.description !== void 0) config.description = options.description;
|
|
4415
|
+
if (options.version !== void 0) config.version = options.version;
|
|
4416
|
+
if (models !== void 0) config.models = models;
|
|
4417
|
+
return config;
|
|
4418
|
+
}
|
|
4419
|
+
function capabilityConfig(_options, agents, pipelines, stores, sandboxCount = 0) {
|
|
4420
|
+
const capabilities = {
|
|
4421
|
+
agents: { enabled: true },
|
|
4422
|
+
observability: { enabled: true },
|
|
4423
|
+
status: { enabled: true }
|
|
4424
|
+
};
|
|
4425
|
+
if (stores.sessions !== void 0) {
|
|
4426
|
+
capabilities.sessions = { enabled: true };
|
|
4283
4427
|
}
|
|
4284
|
-
if (
|
|
4285
|
-
|
|
4428
|
+
if (stores.sessions !== void 0 || agents.some((agent) => agent.agent.memory !== void 0)) {
|
|
4429
|
+
capabilities.memory = { enabled: true };
|
|
4286
4430
|
}
|
|
4287
|
-
if (
|
|
4288
|
-
|
|
4431
|
+
if (stores.traces !== void 0) {
|
|
4432
|
+
capabilities.traces = { enabled: true };
|
|
4289
4433
|
}
|
|
4290
|
-
if (
|
|
4291
|
-
|
|
4434
|
+
if (pipelines.length > 0) {
|
|
4435
|
+
capabilities.pipelines = { enabled: true };
|
|
4292
4436
|
}
|
|
4293
|
-
if (
|
|
4294
|
-
|
|
4437
|
+
if (_options.evals.length > 0) {
|
|
4438
|
+
capabilities.evals = { enabled: true };
|
|
4295
4439
|
}
|
|
4296
|
-
|
|
4297
|
-
}
|
|
4298
|
-
function contentText(value) {
|
|
4299
|
-
if (typeof value === "string") {
|
|
4300
|
-
return value.trim();
|
|
4440
|
+
if (agents.some((agent) => agent.agent.tools.length > 0)) {
|
|
4441
|
+
capabilities.tools = { enabled: true };
|
|
4301
4442
|
}
|
|
4302
|
-
if (
|
|
4303
|
-
|
|
4443
|
+
if (agents.some(agentHasMcpServers)) {
|
|
4444
|
+
capabilities.mcps = { enabled: true };
|
|
4304
4445
|
}
|
|
4305
|
-
if (
|
|
4306
|
-
|
|
4446
|
+
if (sandboxCount > 0) {
|
|
4447
|
+
capabilities.sandboxes = { enabled: true };
|
|
4307
4448
|
}
|
|
4308
|
-
|
|
4309
|
-
}
|
|
4310
|
-
function evidenceDocument(value) {
|
|
4311
|
-
if (!isRecord3(value)) {
|
|
4312
|
-
return [];
|
|
4449
|
+
if (agents.some((agent) => agent.agent.tools.some(toolRequiresApproval))) {
|
|
4450
|
+
capabilities.approvals = { enabled: true };
|
|
4313
4451
|
}
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
const additionalProps = isRecord3(value.additionalProps) ? jsonObjectFromRecord(value.additionalProps) : void 0;
|
|
4317
|
-
if (id === void 0 && text === void 0 && additionalProps === void 0) {
|
|
4318
|
-
return [];
|
|
4452
|
+
if (agents.some(agentHasKnowledge)) {
|
|
4453
|
+
capabilities.knowledge = { enabled: true };
|
|
4319
4454
|
}
|
|
4320
|
-
|
|
4321
|
-
if (id !== void 0) document.id = id;
|
|
4322
|
-
if (text !== void 0) document.text = text;
|
|
4323
|
-
if (additionalProps !== void 0) document.additionalProps = additionalProps;
|
|
4324
|
-
return [document];
|
|
4455
|
+
return capabilities;
|
|
4325
4456
|
}
|
|
4326
|
-
function
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
return
|
|
4457
|
+
function unsupportedCapabilities(stores) {
|
|
4458
|
+
const capabilities = [];
|
|
4459
|
+
if (stores.sessions === void 0) capabilities.push("sessions");
|
|
4460
|
+
if (stores.traces === void 0) capabilities.push("traces");
|
|
4461
|
+
return capabilities;
|
|
4331
4462
|
}
|
|
4332
|
-
function
|
|
4333
|
-
return
|
|
4463
|
+
function toJsonValue2(value) {
|
|
4464
|
+
return serializeUnknown(value);
|
|
4334
4465
|
}
|
|
4335
|
-
|
|
4336
|
-
|
|
4466
|
+
|
|
4467
|
+
// src/runtime/evals.ts
|
|
4468
|
+
import { runEvalSuite } from "@anvia/core/evals";
|
|
4469
|
+
function registerEvalRoutes(app, props) {
|
|
4470
|
+
app.get(
|
|
4471
|
+
"/evals",
|
|
4472
|
+
(c) => c.json({
|
|
4473
|
+
evals: props.evals.map(evalConfig)
|
|
4474
|
+
})
|
|
4475
|
+
);
|
|
4476
|
+
app.get("/evals/:evalId", (c) => {
|
|
4477
|
+
const suite = props.evalMap.get(c.req.param("evalId"));
|
|
4478
|
+
if (suite === void 0) {
|
|
4479
|
+
return errorResponse(c, 404, "not_found", "Eval suite not found");
|
|
4480
|
+
}
|
|
4481
|
+
return c.json(evalConfig(suite));
|
|
4482
|
+
});
|
|
4483
|
+
app.post("/evals/:evalId/runs", async (c) => {
|
|
4484
|
+
const suite = props.evalMap.get(c.req.param("evalId"));
|
|
4485
|
+
if (suite === void 0) {
|
|
4486
|
+
return errorResponse(c, 404, "not_found", "Eval suite not found");
|
|
4487
|
+
}
|
|
4488
|
+
const body = await parseEvalRunRequest(c);
|
|
4489
|
+
if ("error" in body) {
|
|
4490
|
+
return body.error;
|
|
4491
|
+
}
|
|
4492
|
+
const runId = globalThis.crypto.randomUUID();
|
|
4493
|
+
const startedAt = Date.now();
|
|
4494
|
+
const runOptions = { ...suite };
|
|
4495
|
+
if (body.concurrency !== void 0) runOptions.concurrency = body.concurrency;
|
|
4496
|
+
const result = await runEvalSuite(runOptions);
|
|
4497
|
+
const endedAt = Date.now();
|
|
4498
|
+
const jsonResult = toJsonValue(result);
|
|
4499
|
+
const response = {
|
|
4500
|
+
runId,
|
|
4501
|
+
suiteId: suite.id ?? suite.name,
|
|
4502
|
+
startedAt: new Date(startedAt).toISOString(),
|
|
4503
|
+
endedAt: new Date(endedAt).toISOString(),
|
|
4504
|
+
durationMs: endedAt - startedAt,
|
|
4505
|
+
result: isJsonObject(jsonResult) ? jsonResult : { value: jsonResult }
|
|
4506
|
+
};
|
|
4507
|
+
return c.json(response);
|
|
4508
|
+
});
|
|
4509
|
+
}
|
|
4510
|
+
async function parseEvalRunRequest(c) {
|
|
4511
|
+
let body = {};
|
|
4512
|
+
try {
|
|
4513
|
+
body = await c.req.json();
|
|
4514
|
+
} catch {
|
|
4515
|
+
body = {};
|
|
4516
|
+
}
|
|
4517
|
+
if (!isObject(body)) {
|
|
4518
|
+
return { error: errorResponse(c, 400, "bad_request", "Request body must be an object") };
|
|
4519
|
+
}
|
|
4520
|
+
const request = {};
|
|
4521
|
+
if ("concurrency" in body) {
|
|
4522
|
+
if (!isPositiveInteger(body.concurrency)) {
|
|
4523
|
+
return {
|
|
4524
|
+
error: errorResponse(c, 400, "bad_request", "concurrency must be a positive integer")
|
|
4525
|
+
};
|
|
4526
|
+
}
|
|
4527
|
+
request.concurrency = body.concurrency;
|
|
4528
|
+
}
|
|
4529
|
+
return request;
|
|
4337
4530
|
}
|
|
4338
4531
|
|
|
4339
4532
|
// src/runtime/mcps.ts
|
|
@@ -4351,43 +4544,29 @@ function registerMcpRoutes(app, props) {
|
|
|
4351
4544
|
});
|
|
4352
4545
|
}
|
|
4353
4546
|
async function agentMcpMetadata(agent) {
|
|
4354
|
-
|
|
4355
|
-
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
|
|
4375
|
-
|
|
4376
|
-
|
|
4377
|
-
return [...servers.entries()].map(([name, tools]) => {
|
|
4378
|
-
const sortedTools = tools.sort((left, right) => {
|
|
4379
|
-
if (left.source !== right.source) {
|
|
4380
|
-
return left.source === "static" ? -1 : 1;
|
|
4381
|
-
}
|
|
4382
|
-
return left.name.localeCompare(right.name);
|
|
4383
|
-
});
|
|
4384
|
-
return {
|
|
4385
|
-
agentId: agent.id,
|
|
4386
|
-
name,
|
|
4387
|
-
toolCount: sortedTools.length,
|
|
4388
|
-
tools: sortedTools
|
|
4389
|
-
};
|
|
4390
|
-
}).sort((left, right) => left.name.localeCompare(right.name));
|
|
4547
|
+
return Promise.all(
|
|
4548
|
+
agent.agent.mcpServers.map(async (server) => {
|
|
4549
|
+
const tools = await Promise.all(
|
|
4550
|
+
server.tools.map(async (tool) => {
|
|
4551
|
+
const definition = await tool.definition("");
|
|
4552
|
+
return {
|
|
4553
|
+
name: definition.name,
|
|
4554
|
+
description: definition.description,
|
|
4555
|
+
parameters: definition.parameters,
|
|
4556
|
+
source: "static",
|
|
4557
|
+
approval: approvalMetadata(tool)
|
|
4558
|
+
};
|
|
4559
|
+
})
|
|
4560
|
+
);
|
|
4561
|
+
const sortedTools = tools.sort((left, right) => left.name.localeCompare(right.name));
|
|
4562
|
+
return {
|
|
4563
|
+
agentId: agent.id,
|
|
4564
|
+
name: server.name,
|
|
4565
|
+
toolCount: sortedTools.length,
|
|
4566
|
+
tools: sortedTools
|
|
4567
|
+
};
|
|
4568
|
+
})
|
|
4569
|
+
).then((servers) => servers.sort((left, right) => left.name.localeCompare(right.name)));
|
|
4391
4570
|
}
|
|
4392
4571
|
|
|
4393
4572
|
// src/runtime/memory.ts
|
|
@@ -4609,7 +4788,7 @@ function agentMemorySource(ref, label, agentId, storeKindValue, inspector) {
|
|
|
4609
4788
|
).slice(0, options.limit);
|
|
4610
4789
|
},
|
|
4611
4790
|
async getConversation(conversationRef) {
|
|
4612
|
-
const conversation = await inspector.getConversation(conversationRef);
|
|
4791
|
+
const conversation = await inspector.getConversation({ ref: conversationRef });
|
|
4613
4792
|
return conversation === void 0 ? void 0 : inspectorConversationDetail(conversation, summary.agentIds);
|
|
4614
4793
|
}
|
|
4615
4794
|
};
|
|
@@ -4832,12 +5011,12 @@ function pipelineRunFailedLog(pipelineId, runId, error, startedAt) {
|
|
|
4832
5011
|
}
|
|
4833
5012
|
};
|
|
4834
5013
|
}
|
|
4835
|
-
function pipelineStageLog(
|
|
5014
|
+
function pipelineStageLog(event, studioPipelineId = event.pipelineId) {
|
|
4836
5015
|
const category = stageCategory(event.node);
|
|
4837
5016
|
if (event.type === "stage_started") {
|
|
4838
5017
|
return {
|
|
4839
|
-
pipelineId,
|
|
4840
|
-
runId,
|
|
5018
|
+
pipelineId: studioPipelineId,
|
|
5019
|
+
runId: event.runId,
|
|
4841
5020
|
level: "debug",
|
|
4842
5021
|
category,
|
|
4843
5022
|
event: `${event.node.kind}.started`,
|
|
@@ -4847,8 +5026,8 @@ function pipelineStageLog(pipelineId, runId, event) {
|
|
|
4847
5026
|
}
|
|
4848
5027
|
if (event.type === "stage_completed") {
|
|
4849
5028
|
return {
|
|
4850
|
-
pipelineId,
|
|
4851
|
-
runId,
|
|
5029
|
+
pipelineId: studioPipelineId,
|
|
5030
|
+
runId: event.runId,
|
|
4852
5031
|
level: "debug",
|
|
4853
5032
|
category,
|
|
4854
5033
|
event: `${event.node.kind}.completed`,
|
|
@@ -4860,8 +5039,8 @@ function pipelineStageLog(pipelineId, runId, event) {
|
|
|
4860
5039
|
};
|
|
4861
5040
|
}
|
|
4862
5041
|
return {
|
|
4863
|
-
pipelineId,
|
|
4864
|
-
runId,
|
|
5042
|
+
pipelineId: studioPipelineId,
|
|
5043
|
+
runId: event.runId,
|
|
4865
5044
|
level: "error",
|
|
4866
5045
|
category,
|
|
4867
5046
|
event: `${event.node.kind}.failed`,
|
|
@@ -4888,6 +5067,7 @@ function stageCategory(node) {
|
|
|
4888
5067
|
function nodeMetadata(node) {
|
|
4889
5068
|
const metadata = {
|
|
4890
5069
|
nodeId: node.id,
|
|
5070
|
+
nodePath: [...node.path],
|
|
4891
5071
|
kind: node.kind,
|
|
4892
5072
|
label: node.label
|
|
4893
5073
|
};
|
|
@@ -5049,17 +5229,24 @@ async function executePipelineRun(c, props, pipeline, body) {
|
|
|
5049
5229
|
if (body.metadata !== void 0) streamOptions.metadata = body.metadata;
|
|
5050
5230
|
if (props.logStore !== void 0) streamOptions.logStore = props.logStore;
|
|
5051
5231
|
if (props.runStore !== void 0) streamOptions.runStore = props.runStore;
|
|
5232
|
+
streamOptions.abortSignal = c.req.raw.signal;
|
|
5052
5233
|
return streamPipelineRun(c, streamOptions);
|
|
5053
5234
|
}
|
|
5054
5235
|
try {
|
|
5055
5236
|
await appendPipelineLog(props.logStore, pipelineRunStartedLog(pipeline, runId));
|
|
5056
|
-
const
|
|
5237
|
+
const result = await pipeline.pipeline.run({
|
|
5238
|
+
input: body.input,
|
|
5239
|
+
runId,
|
|
5240
|
+
metadata: body.metadata,
|
|
5241
|
+
abortSignal: c.req.raw.signal,
|
|
5057
5242
|
observer: {
|
|
5058
5243
|
async onEvent(event) {
|
|
5059
|
-
await appendPipelineLog(props.logStore, pipelineStageLog(pipeline.id
|
|
5244
|
+
await appendPipelineLog(props.logStore, pipelineStageLog(event, pipeline.id));
|
|
5060
5245
|
}
|
|
5061
|
-
}
|
|
5246
|
+
},
|
|
5247
|
+
failOnObserverError: true
|
|
5062
5248
|
});
|
|
5249
|
+
const output = result.output;
|
|
5063
5250
|
const jsonOutput = toJsonValue(output);
|
|
5064
5251
|
const endedAt = Date.now();
|
|
5065
5252
|
const successRecord = {
|
|
@@ -5124,19 +5311,24 @@ function streamPipelineRun(_c, props) {
|
|
|
5124
5311
|
async function* pipelineRunEvents(props) {
|
|
5125
5312
|
yield* emitPipelineLog(props.logStore, pipelineRunStartedLog(props.pipeline, props.runId));
|
|
5126
5313
|
const events = new AsyncEventQueue();
|
|
5127
|
-
const run = props.pipeline.pipeline.run(
|
|
5314
|
+
const run = props.pipeline.pipeline.run({
|
|
5315
|
+
input: props.input,
|
|
5316
|
+
runId: props.runId,
|
|
5317
|
+
metadata: props.metadata,
|
|
5318
|
+
abortSignal: props.abortSignal,
|
|
5128
5319
|
observer: {
|
|
5129
5320
|
async onEvent(event) {
|
|
5130
5321
|
const log = await appendPipelineLog(
|
|
5131
5322
|
props.logStore,
|
|
5132
|
-
pipelineStageLog(props.pipeline.id
|
|
5323
|
+
pipelineStageLog(event, props.pipeline.id)
|
|
5133
5324
|
);
|
|
5134
5325
|
if (log !== void 0) {
|
|
5135
5326
|
events.push({ type: "pipeline_log", log });
|
|
5136
5327
|
}
|
|
5137
5328
|
}
|
|
5138
|
-
}
|
|
5139
|
-
|
|
5329
|
+
},
|
|
5330
|
+
failOnObserverError: true
|
|
5331
|
+
}).then(async ({ output }) => {
|
|
5140
5332
|
const jsonOutput = toJsonValue(output);
|
|
5141
5333
|
const endedAt = Date.now();
|
|
5142
5334
|
const successRecord = {
|
|
@@ -5290,7 +5482,7 @@ function parsePipelineLogAfter(value) {
|
|
|
5290
5482
|
}
|
|
5291
5483
|
|
|
5292
5484
|
// src/runtime/questions.ts
|
|
5293
|
-
import { createHook
|
|
5485
|
+
import { createHook } from "@anvia/core/internal/agent";
|
|
5294
5486
|
import { parseToolArgs } from "@anvia/core/tool";
|
|
5295
5487
|
function registerQuestionRoutes(app, questions) {
|
|
5296
5488
|
app.get("/questions", (c) => {
|
|
@@ -5383,7 +5575,7 @@ function createQuestionRuntime() {
|
|
|
5383
5575
|
return {
|
|
5384
5576
|
questions,
|
|
5385
5577
|
createHook(context) {
|
|
5386
|
-
return
|
|
5578
|
+
return createHook({
|
|
5387
5579
|
async onToolCall({ toolName, toolCallId, internalCallId, args, tool: control }) {
|
|
5388
5580
|
if (toolName !== "ask_question") {
|
|
5389
5581
|
return control.run();
|
|
@@ -6140,6 +6332,16 @@ function createInMemoryStudioStore() {
|
|
|
6140
6332
|
}
|
|
6141
6333
|
var InMemoryStudioStore = class {
|
|
6142
6334
|
kind = "memory";
|
|
6335
|
+
compaction = {
|
|
6336
|
+
snapshot: ({ scope }) => {
|
|
6337
|
+
const messages = this.sessions.get(scope.sessionId)?.messages ?? [];
|
|
6338
|
+
return Promise.resolve({
|
|
6339
|
+
revision: memoryRevision(messages),
|
|
6340
|
+
messages: cloneMessages(messages)
|
|
6341
|
+
});
|
|
6342
|
+
},
|
|
6343
|
+
replacePrefix: (options) => this.replaceCompactionPrefix(options)
|
|
6344
|
+
};
|
|
6143
6345
|
sessions = /* @__PURE__ */ new Map();
|
|
6144
6346
|
traces = /* @__PURE__ */ new Map();
|
|
6145
6347
|
pipelineLogs = /* @__PURE__ */ new Map();
|
|
@@ -6181,20 +6383,20 @@ var InMemoryStudioStore = class {
|
|
|
6181
6383
|
session.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
6182
6384
|
return materializeSession(session);
|
|
6183
6385
|
}
|
|
6184
|
-
load(
|
|
6185
|
-
return Promise.resolve(this.sessions.get(
|
|
6386
|
+
load({ scope }) {
|
|
6387
|
+
return Promise.resolve(cloneMessages(this.sessions.get(scope.sessionId)?.messages ?? []));
|
|
6186
6388
|
}
|
|
6187
6389
|
append(input) {
|
|
6188
|
-
const session = this.sessions.get(input.
|
|
6390
|
+
const session = this.sessions.get(input.scope.sessionId);
|
|
6189
6391
|
if (session !== void 0) {
|
|
6190
|
-
session.messages.push(...input.messages);
|
|
6392
|
+
session.messages.push(...cloneMessages(input.messages));
|
|
6191
6393
|
session.messageCount = session.messages.length;
|
|
6192
6394
|
session.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
6193
6395
|
}
|
|
6194
6396
|
return Promise.resolve();
|
|
6195
6397
|
}
|
|
6196
|
-
clear(
|
|
6197
|
-
const session = this.sessions.get(
|
|
6398
|
+
clear({ scope }) {
|
|
6399
|
+
const session = this.sessions.get(scope.sessionId);
|
|
6198
6400
|
if (session !== void 0) {
|
|
6199
6401
|
session.messages = [];
|
|
6200
6402
|
session.runs = [];
|
|
@@ -6205,13 +6407,26 @@ var InMemoryStudioStore = class {
|
|
|
6205
6407
|
}
|
|
6206
6408
|
async recordError(input) {
|
|
6207
6409
|
await this.saveSessionRunTranscript({
|
|
6208
|
-
id: input.
|
|
6209
|
-
runId: studioRunId(input.
|
|
6410
|
+
id: input.scope.sessionId,
|
|
6411
|
+
runId: studioRunId(input.scope) ?? input.runId,
|
|
6210
6412
|
transcript: transcriptFromMessages(input.messages),
|
|
6211
6413
|
status: "error",
|
|
6212
6414
|
error: serializeJsonError(input.error)
|
|
6213
6415
|
});
|
|
6214
6416
|
}
|
|
6417
|
+
replaceCompactionPrefix(input) {
|
|
6418
|
+
if (!Number.isSafeInteger(input.messageCount) || input.messageCount < 1) {
|
|
6419
|
+
throw new RangeError("messageCount must be a positive integer.");
|
|
6420
|
+
}
|
|
6421
|
+
const session = this.sessions.get(input.scope.sessionId);
|
|
6422
|
+
if (session === void 0 || memoryRevision(session.messages) !== input.revision || input.messageCount > session.messages.length) {
|
|
6423
|
+
return Promise.resolve({ status: "conflict" });
|
|
6424
|
+
}
|
|
6425
|
+
session.messages.splice(0, input.messageCount, structuredClone(input.replacement));
|
|
6426
|
+
session.messageCount = session.messages.length;
|
|
6427
|
+
session.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
6428
|
+
return Promise.resolve({ status: "committed" });
|
|
6429
|
+
}
|
|
6215
6430
|
saveSessionRunTranscript(input) {
|
|
6216
6431
|
const session = this.sessions.get(input.id);
|
|
6217
6432
|
if (session === void 0) {
|
|
@@ -6337,18 +6552,24 @@ function sessionSummary(session) {
|
|
|
6337
6552
|
function materializeSession(session) {
|
|
6338
6553
|
return {
|
|
6339
6554
|
...sessionSummary(session),
|
|
6340
|
-
messages:
|
|
6555
|
+
messages: cloneMessages(session.messages),
|
|
6341
6556
|
transcript: renumberTranscript(session.runs.flatMap((run) => run.transcript))
|
|
6342
6557
|
};
|
|
6343
6558
|
}
|
|
6559
|
+
function cloneMessages(messages) {
|
|
6560
|
+
return structuredClone([...messages]);
|
|
6561
|
+
}
|
|
6344
6562
|
function traceAgentId(trace) {
|
|
6345
6563
|
const nestedMetadata = trace.metadata?.metadata;
|
|
6346
6564
|
return isJsonObject(nestedMetadata) && typeof nestedMetadata.agentId === "string" ? nestedMetadata.agentId : void 0;
|
|
6347
6565
|
}
|
|
6348
|
-
function studioRunId(
|
|
6349
|
-
const value =
|
|
6566
|
+
function studioRunId(scope) {
|
|
6567
|
+
const value = scope.metadata?.studioRunId;
|
|
6350
6568
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
6351
6569
|
}
|
|
6570
|
+
function memoryRevision(messages) {
|
|
6571
|
+
return JSON.stringify(messages);
|
|
6572
|
+
}
|
|
6352
6573
|
function serializeJsonError(error) {
|
|
6353
6574
|
if (error instanceof Error) {
|
|
6354
6575
|
return {
|
|
@@ -6820,7 +7041,7 @@ function waitForShutdown(signal) {
|
|
|
6820
7041
|
});
|
|
6821
7042
|
}
|
|
6822
7043
|
function studioOptionsFromTargets(targets, options) {
|
|
6823
|
-
const agents = targets.filter((target) => target instanceof
|
|
7044
|
+
const agents = targets.filter((target) => target instanceof Agent);
|
|
6824
7045
|
const pipelines = targets.filter(
|
|
6825
7046
|
// biome-ignore lint/suspicious/noExplicitAny: Studio accepts heterogeneous user pipelines.
|
|
6826
7047
|
(target) => target instanceof Pipeline
|
|
@@ -6873,13 +7094,13 @@ function uniqueAgentId(baseId, ids) {
|
|
|
6873
7094
|
}
|
|
6874
7095
|
function agentMetadata(agent) {
|
|
6875
7096
|
const metadata = {
|
|
6876
|
-
staticContextCount: agent.
|
|
6877
|
-
dynamicContextCount: agent.
|
|
6878
|
-
dynamicToolCount: agent.
|
|
7097
|
+
staticContextCount: staticContextDocuments(agent).length,
|
|
7098
|
+
dynamicContextCount: vectorContexts(agent).length,
|
|
7099
|
+
dynamicToolCount: getAgentToolState3(agent).toolIndexes.length,
|
|
7100
|
+
hasLifecycle: agent.lifecycle !== void 0,
|
|
6879
7101
|
hasOutputSchema: agent.outputSchema !== void 0,
|
|
6880
|
-
|
|
6881
|
-
|
|
6882
|
-
approvalToolCount: agent.toolSet.values().filter((tool) => tool.approval !== void 0).length
|
|
7102
|
+
observerCount: Object.keys(agent.observability?.observers ?? {}).length,
|
|
7103
|
+
approvalToolCount: agent.tools.filter(toolRequiresApproval).length
|
|
6883
7104
|
};
|
|
6884
7105
|
if (agent.defaultMaxTurns !== void 0) metadata.defaultMaxTurns = agent.defaultMaxTurns;
|
|
6885
7106
|
return metadata;
|
|
@@ -7009,30 +7230,37 @@ function createStudioApp(options) {
|
|
|
7009
7230
|
return studio;
|
|
7010
7231
|
}
|
|
7011
7232
|
function withStudioTraceObserver(studioAgent, traceStore) {
|
|
7012
|
-
if (traceStore === void 0
|
|
7013
|
-
|
|
7233
|
+
if (traceStore === void 0) return studioAgent;
|
|
7234
|
+
const existing = studioAgent.agent.observability;
|
|
7235
|
+
const studioObserver = existing?.observers.studio;
|
|
7236
|
+
if (studioObserver !== void 0 && !(studioObserver instanceof StudioTraceObserver)) {
|
|
7237
|
+
throw new TypeError('Studio reserves the observer name "studio" for local trace persistence.');
|
|
7238
|
+
}
|
|
7239
|
+
for (const [name, observer] of Object.entries(existing?.observers ?? {})) {
|
|
7240
|
+
if (observer instanceof StudioTraceObserver && name !== "studio") {
|
|
7241
|
+
throw new TypeError('StudioTraceObserver must be registered with the name "studio".');
|
|
7242
|
+
}
|
|
7014
7243
|
}
|
|
7015
7244
|
return {
|
|
7016
7245
|
...studioAgent,
|
|
7017
7246
|
agent: cloneAgent(studioAgent.agent, {
|
|
7018
|
-
|
|
7019
|
-
|
|
7020
|
-
|
|
7021
|
-
|
|
7247
|
+
observability: {
|
|
7248
|
+
observers: {
|
|
7249
|
+
...existing?.observers ?? {},
|
|
7250
|
+
studio: studioObserver ?? new StudioTraceObserver({ store: traceStore })
|
|
7251
|
+
},
|
|
7252
|
+
primaryTrace: "studio",
|
|
7253
|
+
errorPolicy: existing?.errorPolicy ?? "ignore"
|
|
7254
|
+
}
|
|
7022
7255
|
})
|
|
7023
7256
|
};
|
|
7024
7257
|
}
|
|
7025
|
-
function hasStudioTraceObserver(agent) {
|
|
7026
|
-
return agent.observers.some(
|
|
7027
|
-
(registration) => registration.observer instanceof StudioTraceObserver
|
|
7028
|
-
);
|
|
7029
|
-
}
|
|
7030
7258
|
|
|
7031
7259
|
// src/storage/sqlite-store.ts
|
|
7032
7260
|
import { mkdirSync } from "fs";
|
|
7033
7261
|
import { createRequire } from "module";
|
|
7034
7262
|
import { dirname, resolve } from "path";
|
|
7035
|
-
import { isJsonValue as
|
|
7263
|
+
import { isJsonValue as isJsonValue3 } from "@anvia/core/completion";
|
|
7036
7264
|
var DatabaseSync;
|
|
7037
7265
|
function createSqliteSessionStore(options = {}) {
|
|
7038
7266
|
return new SqliteSessionStore(options.path ?? ":memory:");
|
|
@@ -7043,6 +7271,13 @@ var SqliteSessionStore = class {
|
|
|
7043
7271
|
}
|
|
7044
7272
|
path;
|
|
7045
7273
|
kind = "sqlite";
|
|
7274
|
+
compaction = {
|
|
7275
|
+
snapshot: ({ scope }) => {
|
|
7276
|
+
const messages = this.listSessionMessages(scope.sessionId);
|
|
7277
|
+
return Promise.resolve({ revision: memoryRevision2(messages), messages });
|
|
7278
|
+
},
|
|
7279
|
+
replacePrefix: (options) => this.replaceCompactionPrefix(options)
|
|
7280
|
+
};
|
|
7046
7281
|
db;
|
|
7047
7282
|
listSessions(options) {
|
|
7048
7283
|
const db = this.database();
|
|
@@ -7114,8 +7349,8 @@ var SqliteSessionStore = class {
|
|
|
7114
7349
|
}
|
|
7115
7350
|
return this.getSession(id);
|
|
7116
7351
|
}
|
|
7117
|
-
load(
|
|
7118
|
-
const session = this.getSession(
|
|
7352
|
+
load({ scope }) {
|
|
7353
|
+
const session = this.getSession(scope.sessionId);
|
|
7119
7354
|
return Promise.resolve(session?.messages ?? []);
|
|
7120
7355
|
}
|
|
7121
7356
|
append(input) {
|
|
@@ -7126,20 +7361,20 @@ var SqliteSessionStore = class {
|
|
|
7126
7361
|
`SELECT id, agent_id, title, metadata_json, created_at, updated_at
|
|
7127
7362
|
FROM anvia_studio_sessions
|
|
7128
7363
|
WHERE id = $id`
|
|
7129
|
-
).get({ $id: input.
|
|
7364
|
+
).get({ $id: input.scope.sessionId });
|
|
7130
7365
|
if (row === void 0) {
|
|
7131
7366
|
db.exec("ROLLBACK");
|
|
7132
7367
|
return Promise.resolve();
|
|
7133
7368
|
}
|
|
7134
7369
|
const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
7135
|
-
const nextIndex = this.nextMessageIndex(input.
|
|
7136
|
-
this.insertMessages(input.
|
|
7370
|
+
const nextIndex = this.nextMessageIndex(input.scope.sessionId);
|
|
7371
|
+
this.insertMessages(input.scope.sessionId, input.messages, nextIndex, updatedAt);
|
|
7137
7372
|
db.prepare(
|
|
7138
7373
|
`UPDATE anvia_studio_sessions
|
|
7139
7374
|
SET updated_at = $updatedAt
|
|
7140
7375
|
WHERE id = $id`
|
|
7141
7376
|
).run({
|
|
7142
|
-
$id: input.
|
|
7377
|
+
$id: input.scope.sessionId,
|
|
7143
7378
|
$updatedAt: updatedAt
|
|
7144
7379
|
});
|
|
7145
7380
|
db.exec("COMMIT");
|
|
@@ -7151,7 +7386,7 @@ var SqliteSessionStore = class {
|
|
|
7151
7386
|
throw error;
|
|
7152
7387
|
}
|
|
7153
7388
|
}
|
|
7154
|
-
clear(
|
|
7389
|
+
clear({ scope }) {
|
|
7155
7390
|
const db = this.database();
|
|
7156
7391
|
const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
7157
7392
|
try {
|
|
@@ -7161,14 +7396,14 @@ var SqliteSessionStore = class {
|
|
|
7161
7396
|
SET updated_at = $updatedAt
|
|
7162
7397
|
WHERE id = $id`
|
|
7163
7398
|
).run({
|
|
7164
|
-
$id:
|
|
7399
|
+
$id: scope.sessionId,
|
|
7165
7400
|
$updatedAt: updatedAt
|
|
7166
7401
|
});
|
|
7167
7402
|
db.prepare("DELETE FROM anvia_studio_session_messages WHERE session_id = $id").run({
|
|
7168
|
-
$id:
|
|
7403
|
+
$id: scope.sessionId
|
|
7169
7404
|
});
|
|
7170
7405
|
db.prepare("DELETE FROM anvia_studio_session_runs WHERE session_id = $id").run({
|
|
7171
|
-
$id:
|
|
7406
|
+
$id: scope.sessionId
|
|
7172
7407
|
});
|
|
7173
7408
|
db.exec("COMMIT");
|
|
7174
7409
|
return Promise.resolve();
|
|
@@ -7180,17 +7415,51 @@ var SqliteSessionStore = class {
|
|
|
7180
7415
|
}
|
|
7181
7416
|
}
|
|
7182
7417
|
async recordError(input) {
|
|
7183
|
-
const runId = studioRunId2(input.
|
|
7184
|
-
const existing = this.getSessionRun(input.
|
|
7418
|
+
const runId = studioRunId2(input.scope) ?? input.runId;
|
|
7419
|
+
const existing = this.getSessionRun(input.scope.sessionId, runId);
|
|
7185
7420
|
const transcript = existing === void 0 || parseJsonArray(existing.transcript_json).length === 0 ? transcriptFromMessages(input.messages) : parseJsonArray(existing.transcript_json);
|
|
7186
7421
|
await this.saveSessionRunTranscript({
|
|
7187
|
-
id: input.
|
|
7422
|
+
id: input.scope.sessionId,
|
|
7188
7423
|
runId,
|
|
7189
7424
|
transcript,
|
|
7190
7425
|
status: "error",
|
|
7191
7426
|
error: serializeJsonError2(input.error)
|
|
7192
7427
|
});
|
|
7193
7428
|
}
|
|
7429
|
+
replaceCompactionPrefix(input) {
|
|
7430
|
+
if (!Number.isSafeInteger(input.messageCount) || input.messageCount < 1) {
|
|
7431
|
+
throw new RangeError("messageCount must be a positive integer.");
|
|
7432
|
+
}
|
|
7433
|
+
const db = this.database();
|
|
7434
|
+
try {
|
|
7435
|
+
db.exec("BEGIN IMMEDIATE");
|
|
7436
|
+
const messages = this.listSessionMessages(input.scope.sessionId);
|
|
7437
|
+
if (memoryRevision2(messages) !== input.revision || input.messageCount > messages.length || this.getSessionRow(input.scope.sessionId) === void 0) {
|
|
7438
|
+
db.exec("ROLLBACK");
|
|
7439
|
+
return Promise.resolve({ status: "conflict" });
|
|
7440
|
+
}
|
|
7441
|
+
db.prepare("DELETE FROM anvia_studio_session_messages WHERE session_id = $id").run({
|
|
7442
|
+
$id: input.scope.sessionId
|
|
7443
|
+
});
|
|
7444
|
+
const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
7445
|
+
this.insertMessages(
|
|
7446
|
+
input.scope.sessionId,
|
|
7447
|
+
[input.replacement, ...messages.slice(input.messageCount)],
|
|
7448
|
+
0,
|
|
7449
|
+
updatedAt
|
|
7450
|
+
);
|
|
7451
|
+
db.prepare(
|
|
7452
|
+
`UPDATE anvia_studio_sessions
|
|
7453
|
+
SET updated_at = $updatedAt
|
|
7454
|
+
WHERE id = $id`
|
|
7455
|
+
).run({ $id: input.scope.sessionId, $updatedAt: updatedAt });
|
|
7456
|
+
db.exec("COMMIT");
|
|
7457
|
+
return Promise.resolve({ status: "committed" });
|
|
7458
|
+
} catch (error) {
|
|
7459
|
+
if (db.isTransaction) db.exec("ROLLBACK");
|
|
7460
|
+
throw error;
|
|
7461
|
+
}
|
|
7462
|
+
}
|
|
7194
7463
|
saveSessionRunTranscript(input) {
|
|
7195
7464
|
const db = this.database();
|
|
7196
7465
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -7886,7 +8155,7 @@ var SqliteSessionStore = class {
|
|
|
7886
8155
|
);
|
|
7887
8156
|
messages.forEach((message, messageOffset) => {
|
|
7888
8157
|
const messageIndex = startIndex + messageOffset;
|
|
7889
|
-
if (message.metadata !== void 0 && !
|
|
8158
|
+
if (message.metadata !== void 0 && !isJsonValue3(message.metadata)) {
|
|
7890
8159
|
throw new TypeError("Studio message metadata must be a strict JSON value.");
|
|
7891
8160
|
}
|
|
7892
8161
|
insertMessage.run({
|
|
@@ -7987,6 +8256,9 @@ function messageParts(message) {
|
|
|
7987
8256
|
if (message.role === "system") {
|
|
7988
8257
|
return [{ type: "text", value: { type: "text", text: message.content } }];
|
|
7989
8258
|
}
|
|
8259
|
+
if (typeof message.content === "string") {
|
|
8260
|
+
return [{ type: "text", value: { type: "text", text: message.content } }];
|
|
8261
|
+
}
|
|
7990
8262
|
return message.content.map((content) => ({
|
|
7991
8263
|
type: content.type,
|
|
7992
8264
|
value: content
|
|
@@ -7995,40 +8267,40 @@ function messageParts(message) {
|
|
|
7995
8267
|
function messageFromRows(row, partRows) {
|
|
7996
8268
|
const parts = partRows.map((partRow) => JSON.parse(partRow.part_json));
|
|
7997
8269
|
const metadata = parseJsonValue(row.metadata_json);
|
|
7998
|
-
if (metadata !== void 0 && !
|
|
7999
|
-
throw new TypeError("Stored Studio message metadata is not a strict JSON
|
|
8270
|
+
if (metadata !== void 0 && (!isJsonValue3(metadata) || typeof metadata !== "object" || metadata === null || Array.isArray(metadata))) {
|
|
8271
|
+
throw new TypeError("Stored Studio message metadata is not a strict JSON object.");
|
|
8000
8272
|
}
|
|
8001
8273
|
if (row.role === "system") {
|
|
8002
8274
|
const message = {
|
|
8003
8275
|
role: "system",
|
|
8004
|
-
content: systemContentFromParts(parts)
|
|
8276
|
+
content: systemContentFromParts(parts),
|
|
8277
|
+
...metadata === void 0 ? {} : { metadata }
|
|
8005
8278
|
};
|
|
8006
|
-
if (metadata !== void 0) message.metadata = metadata;
|
|
8007
8279
|
return message;
|
|
8008
8280
|
}
|
|
8009
8281
|
if (row.role === "user") {
|
|
8010
8282
|
const message = {
|
|
8011
8283
|
role: "user",
|
|
8012
|
-
content: parts
|
|
8284
|
+
content: parts,
|
|
8285
|
+
...metadata === void 0 ? {} : { metadata }
|
|
8013
8286
|
};
|
|
8014
|
-
if (metadata !== void 0) message.metadata = metadata;
|
|
8015
8287
|
return message;
|
|
8016
8288
|
}
|
|
8017
8289
|
if (row.role === "assistant") {
|
|
8018
8290
|
const message = {
|
|
8019
8291
|
role: "assistant",
|
|
8020
|
-
content: parts
|
|
8292
|
+
content: parts,
|
|
8293
|
+
...row.message_id === null ? {} : { id: row.message_id },
|
|
8294
|
+
...metadata === void 0 ? {} : { metadata }
|
|
8021
8295
|
};
|
|
8022
|
-
if (row.message_id !== null) message.id = row.message_id;
|
|
8023
|
-
if (metadata !== void 0) message.metadata = metadata;
|
|
8024
8296
|
return message;
|
|
8025
8297
|
}
|
|
8026
8298
|
if (row.role === "tool") {
|
|
8027
8299
|
const message = {
|
|
8028
8300
|
role: "tool",
|
|
8029
|
-
content: parts
|
|
8301
|
+
content: parts,
|
|
8302
|
+
...metadata === void 0 ? {} : { metadata }
|
|
8030
8303
|
};
|
|
8031
|
-
if (metadata !== void 0) message.metadata = metadata;
|
|
8032
8304
|
return message;
|
|
8033
8305
|
}
|
|
8034
8306
|
throw new Error(`Unsupported stored message role: ${row.role}`);
|
|
@@ -8100,6 +8372,7 @@ function toTraceSummary(row) {
|
|
|
8100
8372
|
if (error !== void 0) summary.error = error;
|
|
8101
8373
|
if (usage !== void 0) summary.usage = usage;
|
|
8102
8374
|
if (metadata !== void 0) summary.metadata = metadata;
|
|
8375
|
+
if (typeof metadata?.runId === "string") summary.runId = metadata.runId;
|
|
8103
8376
|
return summary;
|
|
8104
8377
|
}
|
|
8105
8378
|
function parseJsonArray(value) {
|
|
@@ -8112,10 +8385,13 @@ function parseJsonValue(value) {
|
|
|
8112
8385
|
}
|
|
8113
8386
|
return JSON.parse(value);
|
|
8114
8387
|
}
|
|
8115
|
-
function studioRunId2(
|
|
8116
|
-
const value =
|
|
8388
|
+
function studioRunId2(scope) {
|
|
8389
|
+
const value = scope.metadata?.studioRunId;
|
|
8117
8390
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
8118
8391
|
}
|
|
8392
|
+
function memoryRevision2(messages) {
|
|
8393
|
+
return JSON.stringify(messages);
|
|
8394
|
+
}
|
|
8119
8395
|
function serializeJsonError2(error) {
|
|
8120
8396
|
if (error instanceof Error) {
|
|
8121
8397
|
return {
|