@anvia/studio 0.5.7 → 0.5.9
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 +10 -4
- package/dist/index.js +2006 -1988
- package/dist/index.js.map +1 -1
- package/dist/ui/assets/{ArrowClockwise.es-BmQVpKSP.js → ArrowClockwise.es-cF7OPZy5.js} +2 -2
- package/dist/ui/assets/{ArrowClockwise.es-BmQVpKSP.js.map → ArrowClockwise.es-cF7OPZy5.js.map} +1 -1
- package/dist/ui/assets/{Path.es-_A9Dgf5g.js → Path.es-D-NB-Xon.js} +2 -2
- package/dist/ui/assets/{Path.es-_A9Dgf5g.js.map → Path.es-D-NB-Xon.js.map} +1 -1
- package/dist/ui/assets/{Play.es-CD4VDp0t.js → Play.es-BoMnJL28.js} +2 -2
- package/dist/ui/assets/{Play.es-CD4VDp0t.js.map → Play.es-BoMnJL28.js.map} +1 -1
- package/dist/ui/assets/{evals-page-D7c1f_3g.js → evals-page-Cx4Ycr-Y.js} +2 -2
- package/dist/ui/assets/{evals-page-D7c1f_3g.js.map → evals-page-Cx4Ycr-Y.js.map} +1 -1
- package/dist/ui/assets/index-rc2RWnWD.js +54 -0
- package/dist/ui/assets/index-rc2RWnWD.js.map +1 -0
- package/dist/ui/assets/{knowledge-page-BC58KH0x.js → knowledge-page-DASnGzYP.js} +2 -2
- package/dist/ui/assets/{knowledge-page-BC58KH0x.js.map → knowledge-page-DASnGzYP.js.map} +1 -1
- package/dist/ui/assets/{mcps-page-q6-GgvSQ.js → mcps-page-B7VAqsoU.js} +2 -2
- package/dist/ui/assets/{mcps-page-q6-GgvSQ.js.map → mcps-page-B7VAqsoU.js.map} +1 -1
- package/dist/ui/assets/{memory-page-DzYytliI.js → memory-page-BCv19Tw_.js} +2 -2
- package/dist/ui/assets/{memory-page-DzYytliI.js.map → memory-page-BCv19Tw_.js.map} +1 -1
- package/dist/ui/assets/{pipelines-page-waqYX8YQ.js → pipelines-page-Byb_JYxi.js} +2 -2
- package/dist/ui/assets/{pipelines-page-waqYX8YQ.js.map → pipelines-page-Byb_JYxi.js.map} +1 -1
- package/dist/ui/assets/{renderers-DBx9o89u.js → renderers-C8RHOlPz.js} +2 -2
- package/dist/ui/assets/{renderers-DBx9o89u.js.map → renderers-C8RHOlPz.js.map} +1 -1
- package/dist/ui/assets/{sessions-page-DrD_19ku.js → sessions-page-CV8GZKjN.js} +2 -2
- package/dist/ui/assets/{sessions-page-DrD_19ku.js.map → sessions-page-CV8GZKjN.js.map} +1 -1
- package/dist/ui/assets/{status-page-4-V7jY6F.js → status-page-a6SMAcLu.js} +2 -2
- package/dist/ui/assets/{status-page-4-V7jY6F.js.map → status-page-a6SMAcLu.js.map} +1 -1
- package/dist/ui/assets/{tools-page-DuyWVX2b.js → tools-page-Dpj7hI8q.js} +2 -2
- package/dist/ui/assets/{tools-page-DuyWVX2b.js.map → tools-page-Dpj7hI8q.js.map} +1 -1
- package/dist/ui/assets/{trace-browser-DwQWfo7X.js → trace-browser-dvGDi7ji.js} +2 -2
- package/dist/ui/assets/{trace-browser-DwQWfo7X.js.map → trace-browser-dvGDi7ji.js.map} +1 -1
- package/dist/ui/assets/{transcript-item-BJyZu-ue.js → transcript-item-GmOQdc53.js} +2 -2
- package/dist/ui/assets/{transcript-item-BJyZu-ue.js.map → transcript-item-GmOQdc53.js.map} +1 -1
- package/dist/ui/index.html +1 -1
- package/package.json +4 -4
- package/dist/ui/assets/index-ZVqWotd2.js +0 -55
- package/dist/ui/assets/index-ZVqWotd2.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -4,7 +4,6 @@ import {
|
|
|
4
4
|
} from "@anvia/core/agent";
|
|
5
5
|
import { Message } from "@anvia/core/completion";
|
|
6
6
|
import { Agent } from "@anvia/core/internal/agent";
|
|
7
|
-
import { resolveMemoryOptions } from "@anvia/core/memory";
|
|
8
7
|
import { Pipeline } from "@anvia/core/pipeline";
|
|
9
8
|
import { serve } from "@hono/node-server";
|
|
10
9
|
import { Hono as HonoApp } from "hono";
|
|
@@ -695,7 +694,7 @@ function renderLegacyStudioUiShell(props) {
|
|
|
695
694
|
'<meta charset="utf-8">',
|
|
696
695
|
'<meta name="viewport" content="width=device-width, initial-scale=1">',
|
|
697
696
|
`<title>${title}</title>`,
|
|
698
|
-
'<script>(()=>{try{if(
|
|
697
|
+
'<script>(()=>{try{if(localStorage.getItem("anvia-studio-theme")==="light"){document.documentElement.classList.remove("dark")}}catch{}})();</script>',
|
|
699
698
|
`<link rel="icon" type="image/png" href="${escapeHtml(props.compatUiPath)}/assets/logo.png">`,
|
|
700
699
|
`<link rel="stylesheet" href="${escapeHtml(props.stylesheet)}">`,
|
|
701
700
|
"</head>",
|
|
@@ -1146,1827 +1145,780 @@ function isJsonValue(value) {
|
|
|
1146
1145
|
return isJsonObject(value) && Object.values(value).every(isJsonValue);
|
|
1147
1146
|
}
|
|
1148
1147
|
|
|
1149
|
-
// src/
|
|
1150
|
-
import {
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1148
|
+
// src/runtime/tool-metadata.ts
|
|
1149
|
+
import { ToolSet } from "@anvia/core/tool";
|
|
1150
|
+
var MCP_TOOL_METADATA_KEY = /* @__PURE__ */ Symbol.for("anvia.mcp.tool.metadata");
|
|
1151
|
+
function agentToolItems(agent) {
|
|
1152
|
+
return [
|
|
1153
|
+
...agent.agent.toolSet.values().map((tool) => ({ tool, source: "static" })),
|
|
1154
|
+
...agent.agent.dynamicTools.flatMap((registration) => {
|
|
1155
|
+
const maybeToolSet = registration.index.toolSet;
|
|
1156
|
+
if (!(maybeToolSet instanceof ToolSet)) {
|
|
1157
|
+
return [];
|
|
1158
|
+
}
|
|
1159
|
+
return maybeToolSet.values().map((tool) => ({ tool, source: "dynamic" }));
|
|
1160
|
+
})
|
|
1161
|
+
];
|
|
1156
1162
|
}
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1163
|
+
function approvalMetadata(tool) {
|
|
1164
|
+
const approval = tool.approval;
|
|
1165
|
+
if (approval === void 0 || typeof approval !== "object" || approval === null) {
|
|
1166
|
+
return { required: false };
|
|
1160
1167
|
}
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
${agentClause}
|
|
1173
|
-
GROUP BY s.id, s.agent_id, s.title, s.metadata_json, s.created_at, s.updated_at
|
|
1174
|
-
ORDER BY s.updated_at DESC
|
|
1175
|
-
LIMIT $limit`
|
|
1176
|
-
).all({
|
|
1177
|
-
$agentId: options.agentId ?? null,
|
|
1178
|
-
$limit: options.limit
|
|
1179
|
-
});
|
|
1180
|
-
return rows.map(toSessionSummary);
|
|
1168
|
+
const policy = approval;
|
|
1169
|
+
return {
|
|
1170
|
+
required: true,
|
|
1171
|
+
...typeof policy.reason === "string" ? { reason: policy.reason } : {},
|
|
1172
|
+
...typeof policy.rejectMessage === "string" ? { rejectMessage: policy.rejectMessage } : {}
|
|
1173
|
+
};
|
|
1174
|
+
}
|
|
1175
|
+
function mcpServerName(tool) {
|
|
1176
|
+
const metadata = tool[MCP_TOOL_METADATA_KEY];
|
|
1177
|
+
if (typeof metadata !== "object" || metadata === null) {
|
|
1178
|
+
return void 0;
|
|
1181
1179
|
}
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
}
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
};
|
|
1180
|
+
const serverName = metadata.serverName;
|
|
1181
|
+
return typeof serverName === "string" && serverName.length > 0 ? serverName : void 0;
|
|
1182
|
+
}
|
|
1183
|
+
function agentHasMcpTools(agent) {
|
|
1184
|
+
return agentToolItems(agent).some(({ tool }) => mcpServerName(tool) !== void 0);
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
// src/runtime/shared.ts
|
|
1188
|
+
function resolveStores(options) {
|
|
1189
|
+
const defaultStore = defaultStudioStore();
|
|
1190
|
+
const sessions = resolveSessionStore(options, defaultStore);
|
|
1191
|
+
const traces = resolveTraceStore(options, sessions, defaultStore);
|
|
1192
|
+
const pipelineLogs = resolvePipelineLogStore(options, sessions, defaultStore);
|
|
1193
|
+
const pipelineRuns = resolvePipelineRunStore(options, sessions, pipelineLogs, defaultStore);
|
|
1194
|
+
return {
|
|
1195
|
+
...sessions === void 0 ? {} : { sessions },
|
|
1196
|
+
...traces === void 0 ? {} : { traces },
|
|
1197
|
+
...pipelineLogs === void 0 ? {} : { pipelineLogs },
|
|
1198
|
+
...pipelineRuns === void 0 ? {} : { pipelineRuns }
|
|
1199
|
+
};
|
|
1200
|
+
}
|
|
1201
|
+
function defaultStudioStore() {
|
|
1202
|
+
return createInMemoryStudioStore();
|
|
1203
|
+
}
|
|
1204
|
+
function resolveSessionStore(options, defaultStore) {
|
|
1205
|
+
if (options.stores?.sessions === false) {
|
|
1206
|
+
return void 0;
|
|
1210
1207
|
}
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
return row === void 0 ? void 0 : toSession(row, this.listSessionMessages(id), this.listSessionRunRows(id));
|
|
1208
|
+
if (options.stores?.sessions !== void 0) {
|
|
1209
|
+
return options.stores.sessions;
|
|
1214
1210
|
}
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1211
|
+
return defaultStore;
|
|
1212
|
+
}
|
|
1213
|
+
function resolveTraceStore(options, sessionStore, defaultStore) {
|
|
1214
|
+
if (options.stores?.traces !== void 0) {
|
|
1215
|
+
return options.stores.traces;
|
|
1218
1216
|
}
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
try {
|
|
1222
|
-
db.exec("BEGIN IMMEDIATE");
|
|
1223
|
-
const row = db.prepare(
|
|
1224
|
-
`SELECT id, agent_id, title, metadata_json, created_at, updated_at
|
|
1225
|
-
FROM anvia_studio_sessions
|
|
1226
|
-
WHERE id = $id`
|
|
1227
|
-
).get({ $id: input.context.sessionId });
|
|
1228
|
-
if (row === void 0) {
|
|
1229
|
-
db.exec("ROLLBACK");
|
|
1230
|
-
return Promise.resolve();
|
|
1231
|
-
}
|
|
1232
|
-
const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1233
|
-
const nextIndex = this.nextMessageIndex(input.context.sessionId);
|
|
1234
|
-
this.insertMessages(input.context.sessionId, input.messages, nextIndex, updatedAt);
|
|
1235
|
-
db.prepare(
|
|
1236
|
-
`UPDATE anvia_studio_sessions
|
|
1237
|
-
SET updated_at = $updatedAt
|
|
1238
|
-
WHERE id = $id`
|
|
1239
|
-
).run({
|
|
1240
|
-
$id: input.context.sessionId,
|
|
1241
|
-
$updatedAt: updatedAt
|
|
1242
|
-
});
|
|
1243
|
-
db.exec("COMMIT");
|
|
1244
|
-
return Promise.resolve();
|
|
1245
|
-
} catch (error) {
|
|
1246
|
-
if (db.isTransaction) {
|
|
1247
|
-
db.exec("ROLLBACK");
|
|
1248
|
-
}
|
|
1249
|
-
throw error;
|
|
1250
|
-
}
|
|
1217
|
+
if (sessionStore === void 0) {
|
|
1218
|
+
return void 0;
|
|
1251
1219
|
}
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1255
|
-
try {
|
|
1256
|
-
db.exec("BEGIN IMMEDIATE");
|
|
1257
|
-
db.prepare(
|
|
1258
|
-
`UPDATE anvia_studio_sessions
|
|
1259
|
-
SET updated_at = $updatedAt
|
|
1260
|
-
WHERE id = $id`
|
|
1261
|
-
).run({
|
|
1262
|
-
$id: context.sessionId,
|
|
1263
|
-
$updatedAt: updatedAt
|
|
1264
|
-
});
|
|
1265
|
-
db.prepare("DELETE FROM anvia_studio_session_messages WHERE session_id = $id").run({
|
|
1266
|
-
$id: context.sessionId
|
|
1267
|
-
});
|
|
1268
|
-
db.prepare("DELETE FROM anvia_studio_session_runs WHERE session_id = $id").run({
|
|
1269
|
-
$id: context.sessionId
|
|
1270
|
-
});
|
|
1271
|
-
db.exec("COMMIT");
|
|
1272
|
-
return Promise.resolve();
|
|
1273
|
-
} catch (error) {
|
|
1274
|
-
if (db.isTransaction) {
|
|
1275
|
-
db.exec("ROLLBACK");
|
|
1276
|
-
}
|
|
1277
|
-
throw error;
|
|
1278
|
-
}
|
|
1220
|
+
if (isTraceStore(sessionStore)) {
|
|
1221
|
+
return sessionStore;
|
|
1279
1222
|
}
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
id: input.context.sessionId,
|
|
1286
|
-
runId,
|
|
1287
|
-
transcript,
|
|
1288
|
-
status: "error",
|
|
1289
|
-
error: serializeJsonError2(input.error)
|
|
1290
|
-
});
|
|
1223
|
+
return defaultStore;
|
|
1224
|
+
}
|
|
1225
|
+
function resolvePipelineLogStore(options, sessionStore, defaultStore) {
|
|
1226
|
+
if (options.stores?.pipelineLogs === false) {
|
|
1227
|
+
return void 0;
|
|
1291
1228
|
}
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1295
|
-
try {
|
|
1296
|
-
db.exec("BEGIN IMMEDIATE");
|
|
1297
|
-
const row = this.getSessionRow(input.id);
|
|
1298
|
-
if (row === void 0) {
|
|
1299
|
-
db.exec("ROLLBACK");
|
|
1300
|
-
return void 0;
|
|
1301
|
-
}
|
|
1302
|
-
const current = toSession(
|
|
1303
|
-
row,
|
|
1304
|
-
this.listSessionMessages(input.id),
|
|
1305
|
-
this.listSessionRunRows(input.id)
|
|
1306
|
-
);
|
|
1307
|
-
const title = current.title ?? input.title;
|
|
1308
|
-
db.prepare(
|
|
1309
|
-
`INSERT INTO anvia_studio_session_runs (
|
|
1310
|
-
run_id,
|
|
1311
|
-
session_id,
|
|
1312
|
-
status,
|
|
1313
|
-
title,
|
|
1314
|
-
transcript_json,
|
|
1315
|
-
error_json,
|
|
1316
|
-
created_at,
|
|
1317
|
-
updated_at
|
|
1318
|
-
) VALUES (
|
|
1319
|
-
$runId,
|
|
1320
|
-
$sessionId,
|
|
1321
|
-
$status,
|
|
1322
|
-
$title,
|
|
1323
|
-
$transcript,
|
|
1324
|
-
$error,
|
|
1325
|
-
$now,
|
|
1326
|
-
$now
|
|
1327
|
-
)
|
|
1328
|
-
ON CONFLICT(run_id) DO UPDATE SET
|
|
1329
|
-
status = excluded.status,
|
|
1330
|
-
title = COALESCE(anvia_studio_session_runs.title, excluded.title),
|
|
1331
|
-
transcript_json = excluded.transcript_json,
|
|
1332
|
-
error_json = excluded.error_json,
|
|
1333
|
-
updated_at = excluded.updated_at`
|
|
1334
|
-
).run({
|
|
1335
|
-
$runId: input.runId,
|
|
1336
|
-
$sessionId: input.id,
|
|
1337
|
-
$status: input.status,
|
|
1338
|
-
$title: input.title ?? null,
|
|
1339
|
-
$transcript: JSON.stringify(renumberTranscript(input.transcript)),
|
|
1340
|
-
$error: input.error === void 0 ? null : JSON.stringify(input.error),
|
|
1341
|
-
$now: now
|
|
1342
|
-
});
|
|
1343
|
-
db.prepare(
|
|
1344
|
-
`UPDATE anvia_studio_sessions
|
|
1345
|
-
SET title = $title,
|
|
1346
|
-
updated_at = $updatedAt
|
|
1347
|
-
WHERE id = $id`
|
|
1348
|
-
).run({
|
|
1349
|
-
$id: input.id,
|
|
1350
|
-
$title: title ?? null,
|
|
1351
|
-
$updatedAt: now
|
|
1352
|
-
});
|
|
1353
|
-
db.exec("COMMIT");
|
|
1354
|
-
const updated = this.getSession(input.id);
|
|
1355
|
-
return updated;
|
|
1356
|
-
} catch (error) {
|
|
1357
|
-
if (db.isTransaction) {
|
|
1358
|
-
db.exec("ROLLBACK");
|
|
1359
|
-
}
|
|
1360
|
-
throw error;
|
|
1361
|
-
}
|
|
1229
|
+
if (options.stores?.pipelineLogs !== void 0) {
|
|
1230
|
+
return options.stores.pipelineLogs;
|
|
1362
1231
|
}
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1366
|
-
try {
|
|
1367
|
-
db.exec("BEGIN IMMEDIATE");
|
|
1368
|
-
const row = this.getSessionRow(input.sessionId);
|
|
1369
|
-
if (row === void 0) {
|
|
1370
|
-
throw new Error("Session not found");
|
|
1371
|
-
}
|
|
1372
|
-
const sequence = this.nextSessionLogSequence(input.sessionId);
|
|
1373
|
-
const entry = {
|
|
1374
|
-
id: globalThis.crypto.randomUUID(),
|
|
1375
|
-
sessionId: input.sessionId,
|
|
1376
|
-
...input.runId === void 0 ? {} : { runId: input.runId },
|
|
1377
|
-
sequence,
|
|
1378
|
-
timestamp: now,
|
|
1379
|
-
level: input.level,
|
|
1380
|
-
category: input.category,
|
|
1381
|
-
event: input.event,
|
|
1382
|
-
message: input.message,
|
|
1383
|
-
...input.metadata === void 0 ? {} : { metadata: input.metadata }
|
|
1384
|
-
};
|
|
1385
|
-
db.prepare(
|
|
1386
|
-
`INSERT INTO anvia_studio_session_logs (
|
|
1387
|
-
id,
|
|
1388
|
-
session_id,
|
|
1389
|
-
run_id,
|
|
1390
|
-
sequence,
|
|
1391
|
-
timestamp,
|
|
1392
|
-
level,
|
|
1393
|
-
category,
|
|
1394
|
-
event,
|
|
1395
|
-
message,
|
|
1396
|
-
metadata_json
|
|
1397
|
-
) VALUES (
|
|
1398
|
-
$id,
|
|
1399
|
-
$sessionId,
|
|
1400
|
-
$runId,
|
|
1401
|
-
$sequence,
|
|
1402
|
-
$timestamp,
|
|
1403
|
-
$level,
|
|
1404
|
-
$category,
|
|
1405
|
-
$event,
|
|
1406
|
-
$message,
|
|
1407
|
-
$metadata
|
|
1408
|
-
)`
|
|
1409
|
-
).run({
|
|
1410
|
-
$id: entry.id,
|
|
1411
|
-
$sessionId: entry.sessionId,
|
|
1412
|
-
$runId: entry.runId ?? null,
|
|
1413
|
-
$sequence: entry.sequence,
|
|
1414
|
-
$timestamp: entry.timestamp,
|
|
1415
|
-
$level: entry.level,
|
|
1416
|
-
$category: entry.category,
|
|
1417
|
-
$event: entry.event,
|
|
1418
|
-
$message: entry.message,
|
|
1419
|
-
$metadata: entry.metadata === void 0 ? null : JSON.stringify(entry.metadata)
|
|
1420
|
-
});
|
|
1421
|
-
db.exec("COMMIT");
|
|
1422
|
-
return entry;
|
|
1423
|
-
} catch (error) {
|
|
1424
|
-
if (db.isTransaction) {
|
|
1425
|
-
db.exec("ROLLBACK");
|
|
1426
|
-
}
|
|
1427
|
-
throw error;
|
|
1428
|
-
}
|
|
1232
|
+
if (sessionStore !== void 0 && isPipelineLogStore(sessionStore)) {
|
|
1233
|
+
return sessionStore;
|
|
1429
1234
|
}
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
metadata_json
|
|
1436
|
-
FROM anvia_studio_session_logs
|
|
1437
|
-
WHERE session_id = $sessionId
|
|
1438
|
-
${afterClause}
|
|
1439
|
-
ORDER BY sequence ASC
|
|
1440
|
-
LIMIT $limit`
|
|
1441
|
-
).all({
|
|
1442
|
-
$sessionId: options.sessionId,
|
|
1443
|
-
$after: options.after ?? null,
|
|
1444
|
-
$limit: options.limit
|
|
1445
|
-
});
|
|
1446
|
-
return rows.map(toSessionLog);
|
|
1235
|
+
return defaultStore;
|
|
1236
|
+
}
|
|
1237
|
+
function resolvePipelineRunStore(options, sessionStore, pipelineLogStore, defaultStore) {
|
|
1238
|
+
if (options.stores?.pipelineRuns === false) {
|
|
1239
|
+
return void 0;
|
|
1447
1240
|
}
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1451
|
-
try {
|
|
1452
|
-
db.exec("BEGIN IMMEDIATE");
|
|
1453
|
-
const sequence = this.nextPipelineLogSequence(input.pipelineId);
|
|
1454
|
-
const entry = {
|
|
1455
|
-
id: globalThis.crypto.randomUUID(),
|
|
1456
|
-
pipelineId: input.pipelineId,
|
|
1457
|
-
...input.runId === void 0 ? {} : { runId: input.runId },
|
|
1458
|
-
sequence,
|
|
1459
|
-
timestamp: now,
|
|
1460
|
-
level: input.level,
|
|
1461
|
-
category: input.category,
|
|
1462
|
-
event: input.event,
|
|
1463
|
-
message: input.message,
|
|
1464
|
-
...input.metadata === void 0 ? {} : { metadata: input.metadata }
|
|
1465
|
-
};
|
|
1466
|
-
db.prepare(
|
|
1467
|
-
`INSERT INTO anvia_studio_pipeline_logs (
|
|
1468
|
-
id,
|
|
1469
|
-
pipeline_id,
|
|
1470
|
-
run_id,
|
|
1471
|
-
sequence,
|
|
1472
|
-
timestamp,
|
|
1473
|
-
level,
|
|
1474
|
-
category,
|
|
1475
|
-
event,
|
|
1476
|
-
message,
|
|
1477
|
-
metadata_json
|
|
1478
|
-
) VALUES (
|
|
1479
|
-
$id,
|
|
1480
|
-
$pipelineId,
|
|
1481
|
-
$runId,
|
|
1482
|
-
$sequence,
|
|
1483
|
-
$timestamp,
|
|
1484
|
-
$level,
|
|
1485
|
-
$category,
|
|
1486
|
-
$event,
|
|
1487
|
-
$message,
|
|
1488
|
-
$metadata
|
|
1489
|
-
)`
|
|
1490
|
-
).run({
|
|
1491
|
-
$id: entry.id,
|
|
1492
|
-
$pipelineId: entry.pipelineId,
|
|
1493
|
-
$runId: entry.runId ?? null,
|
|
1494
|
-
$sequence: entry.sequence,
|
|
1495
|
-
$timestamp: entry.timestamp,
|
|
1496
|
-
$level: entry.level,
|
|
1497
|
-
$category: entry.category,
|
|
1498
|
-
$event: entry.event,
|
|
1499
|
-
$message: entry.message,
|
|
1500
|
-
$metadata: entry.metadata === void 0 ? null : JSON.stringify(entry.metadata)
|
|
1501
|
-
});
|
|
1502
|
-
db.exec("COMMIT");
|
|
1503
|
-
return entry;
|
|
1504
|
-
} catch (error) {
|
|
1505
|
-
if (db.isTransaction) {
|
|
1506
|
-
db.exec("ROLLBACK");
|
|
1507
|
-
}
|
|
1508
|
-
throw error;
|
|
1509
|
-
}
|
|
1241
|
+
if (options.stores?.pipelineRuns !== void 0) {
|
|
1242
|
+
return options.stores.pipelineRuns;
|
|
1510
1243
|
}
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
const afterClause = options.after === void 0 ? "" : "AND sequence > $after";
|
|
1514
|
-
const rows = db.prepare(
|
|
1515
|
-
`SELECT id, pipeline_id, run_id, sequence, timestamp, level, category, event, message,
|
|
1516
|
-
metadata_json
|
|
1517
|
-
FROM anvia_studio_pipeline_logs
|
|
1518
|
-
WHERE pipeline_id = $pipelineId
|
|
1519
|
-
${afterClause}
|
|
1520
|
-
ORDER BY sequence ASC
|
|
1521
|
-
LIMIT $limit`
|
|
1522
|
-
).all({
|
|
1523
|
-
$pipelineId: options.pipelineId,
|
|
1524
|
-
$after: options.after ?? null,
|
|
1525
|
-
$limit: options.limit
|
|
1526
|
-
});
|
|
1527
|
-
return rows.map(toPipelineLog);
|
|
1244
|
+
if (sessionStore !== void 0 && isPipelineRunStore(sessionStore)) {
|
|
1245
|
+
return sessionStore;
|
|
1528
1246
|
}
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
db.prepare(
|
|
1532
|
-
`INSERT INTO anvia_studio_pipeline_runs (
|
|
1533
|
-
run_id,
|
|
1534
|
-
pipeline_id,
|
|
1535
|
-
status,
|
|
1536
|
-
input_json,
|
|
1537
|
-
output_json,
|
|
1538
|
-
error_json,
|
|
1539
|
-
metadata_json,
|
|
1540
|
-
started_at,
|
|
1541
|
-
ended_at,
|
|
1542
|
-
duration_ms
|
|
1543
|
-
) VALUES (
|
|
1544
|
-
$runId,
|
|
1545
|
-
$pipelineId,
|
|
1546
|
-
$status,
|
|
1547
|
-
$input,
|
|
1548
|
-
$output,
|
|
1549
|
-
$error,
|
|
1550
|
-
$metadata,
|
|
1551
|
-
$startedAt,
|
|
1552
|
-
$endedAt,
|
|
1553
|
-
$durationMs
|
|
1554
|
-
)
|
|
1555
|
-
ON CONFLICT(run_id) DO UPDATE SET
|
|
1556
|
-
pipeline_id = excluded.pipeline_id,
|
|
1557
|
-
status = excluded.status,
|
|
1558
|
-
input_json = excluded.input_json,
|
|
1559
|
-
output_json = excluded.output_json,
|
|
1560
|
-
error_json = excluded.error_json,
|
|
1561
|
-
metadata_json = excluded.metadata_json,
|
|
1562
|
-
started_at = excluded.started_at,
|
|
1563
|
-
ended_at = excluded.ended_at,
|
|
1564
|
-
duration_ms = excluded.duration_ms`
|
|
1565
|
-
).run({
|
|
1566
|
-
$runId: input.runId,
|
|
1567
|
-
$pipelineId: input.pipelineId,
|
|
1568
|
-
$status: input.status,
|
|
1569
|
-
$input: JSON.stringify(input.input),
|
|
1570
|
-
$output: input.output === void 0 ? null : JSON.stringify(input.output),
|
|
1571
|
-
$error: input.error === void 0 ? null : JSON.stringify(input.error),
|
|
1572
|
-
$metadata: input.metadata === void 0 ? null : JSON.stringify(input.metadata),
|
|
1573
|
-
$startedAt: input.startedAt,
|
|
1574
|
-
$endedAt: input.endedAt ?? null,
|
|
1575
|
-
$durationMs: input.durationMs ?? null
|
|
1576
|
-
});
|
|
1577
|
-
return {
|
|
1578
|
-
runId: input.runId,
|
|
1579
|
-
pipelineId: input.pipelineId,
|
|
1580
|
-
status: input.status,
|
|
1581
|
-
input: input.input,
|
|
1582
|
-
...input.output === void 0 ? {} : { output: input.output },
|
|
1583
|
-
...input.error === void 0 ? {} : { error: input.error },
|
|
1584
|
-
...input.metadata === void 0 ? {} : { metadata: input.metadata },
|
|
1585
|
-
startedAt: input.startedAt,
|
|
1586
|
-
...input.endedAt === void 0 ? {} : { endedAt: input.endedAt },
|
|
1587
|
-
...input.durationMs === void 0 ? {} : { durationMs: input.durationMs }
|
|
1588
|
-
};
|
|
1247
|
+
if (pipelineLogStore !== void 0 && isPipelineRunStore(pipelineLogStore)) {
|
|
1248
|
+
return pipelineLogStore;
|
|
1589
1249
|
}
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
return rows.map(toPipelineRun);
|
|
1617
|
-
}
|
|
1618
|
-
deleteSession(id) {
|
|
1619
|
-
const db = this.database();
|
|
1620
|
-
try {
|
|
1621
|
-
db.exec("BEGIN IMMEDIATE");
|
|
1622
|
-
db.prepare("DELETE FROM anvia_studio_traces WHERE session_id = $id").run({ $id: id });
|
|
1623
|
-
db.prepare("DELETE FROM anvia_studio_session_runs WHERE session_id = $id").run({ $id: id });
|
|
1624
|
-
db.prepare("DELETE FROM anvia_studio_session_logs WHERE session_id = $id").run({ $id: id });
|
|
1625
|
-
const result = db.prepare("DELETE FROM anvia_studio_sessions WHERE id = $id").run({ $id: id });
|
|
1626
|
-
db.exec("COMMIT");
|
|
1627
|
-
return Number(result.changes) > 0;
|
|
1628
|
-
} catch (error) {
|
|
1629
|
-
if (db.isTransaction) {
|
|
1630
|
-
db.exec("ROLLBACK");
|
|
1631
|
-
}
|
|
1632
|
-
throw error;
|
|
1250
|
+
return defaultStore;
|
|
1251
|
+
}
|
|
1252
|
+
function isTraceStore(store) {
|
|
1253
|
+
const candidate = store;
|
|
1254
|
+
return typeof candidate.listSessionTraces === "function" && typeof candidate.getTrace === "function" && typeof candidate.saveTrace === "function";
|
|
1255
|
+
}
|
|
1256
|
+
function isPipelineLogStore(store) {
|
|
1257
|
+
const candidate = store;
|
|
1258
|
+
return typeof candidate.appendPipelineLog === "function" && typeof candidate.listPipelineLogs === "function";
|
|
1259
|
+
}
|
|
1260
|
+
function isPipelineRunStore(store) {
|
|
1261
|
+
const candidate = store;
|
|
1262
|
+
return typeof candidate.savePipelineRun === "function" && typeof candidate.getPipelineRun === "function" && typeof candidate.listPipelineRuns === "function";
|
|
1263
|
+
}
|
|
1264
|
+
function unsupportedCapabilities(stores) {
|
|
1265
|
+
return [
|
|
1266
|
+
...stores.sessions === void 0 ? ["sessions"] : [],
|
|
1267
|
+
...stores.traces === void 0 ? ["traces"] : []
|
|
1268
|
+
];
|
|
1269
|
+
}
|
|
1270
|
+
function normalizeAgents(agents) {
|
|
1271
|
+
const ids = /* @__PURE__ */ new Set();
|
|
1272
|
+
return agents.map((agent) => {
|
|
1273
|
+
const id = agent.id.trim();
|
|
1274
|
+
if (id.length === 0) {
|
|
1275
|
+
throw new Error("Studio agent id cannot be empty");
|
|
1633
1276
|
}
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
const db = this.database();
|
|
1637
|
-
const filters = [];
|
|
1638
|
-
const values = {
|
|
1639
|
-
$limit: options.limit
|
|
1640
|
-
};
|
|
1641
|
-
if (options.agentId !== void 0) {
|
|
1642
|
-
filters.push(
|
|
1643
|
-
"(s.agent_id = $agentId OR json_extract(t.metadata_json, '$.metadata.agentId') = $agentId)"
|
|
1644
|
-
);
|
|
1645
|
-
values.$agentId = options.agentId;
|
|
1277
|
+
if (ids.has(id)) {
|
|
1278
|
+
throw new Error(`Duplicate runner agent id: ${id}`);
|
|
1646
1279
|
}
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1280
|
+
ids.add(id);
|
|
1281
|
+
return { ...agent, id };
|
|
1282
|
+
});
|
|
1283
|
+
}
|
|
1284
|
+
function normalizePipelines(pipelines) {
|
|
1285
|
+
const ids = /* @__PURE__ */ new Set();
|
|
1286
|
+
return pipelines.map((pipeline) => {
|
|
1287
|
+
const id = pipeline.id.trim();
|
|
1288
|
+
if (id.length === 0) {
|
|
1289
|
+
throw new Error("Studio pipeline id cannot be empty");
|
|
1650
1290
|
}
|
|
1651
|
-
if (
|
|
1652
|
-
|
|
1653
|
-
values.$status = options.status;
|
|
1291
|
+
if (ids.has(id)) {
|
|
1292
|
+
throw new Error(`Duplicate Studio pipeline id: ${id}`);
|
|
1654
1293
|
}
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1294
|
+
ids.add(id);
|
|
1295
|
+
return { ...pipeline, id };
|
|
1296
|
+
});
|
|
1297
|
+
}
|
|
1298
|
+
function buildConfig(options, agents, pipelines, stores) {
|
|
1299
|
+
return {
|
|
1300
|
+
id: runnerId(options),
|
|
1301
|
+
...options.name === void 0 ? {} : { name: options.name },
|
|
1302
|
+
...options.description === void 0 ? {} : { description: options.description },
|
|
1303
|
+
...options.version === void 0 ? {} : { version: options.version },
|
|
1304
|
+
agents: agents.map(agentConfig),
|
|
1305
|
+
pipelines: pipelines.map(pipelineConfig),
|
|
1306
|
+
evals: options.evals.map(evalConfig),
|
|
1307
|
+
chat: {
|
|
1308
|
+
quickPrompts: Object.fromEntries(agents.map((agent) => [agent.id, agent.quickPrompts ?? []]))
|
|
1309
|
+
},
|
|
1310
|
+
capabilities: capabilityConfig(options, agents, pipelines, stores),
|
|
1311
|
+
unsupportedCapabilities: unsupportedCapabilities(stores)
|
|
1312
|
+
};
|
|
1313
|
+
}
|
|
1314
|
+
function runnerId(options) {
|
|
1315
|
+
return options.id ?? "anvia-studio";
|
|
1316
|
+
}
|
|
1317
|
+
function agentConfig(agent) {
|
|
1318
|
+
const name = agent.name ?? agent.agent.name;
|
|
1319
|
+
const description = agent.description ?? agent.agent.description;
|
|
1320
|
+
return {
|
|
1321
|
+
id: agent.id,
|
|
1322
|
+
...name === void 0 ? {} : { name },
|
|
1323
|
+
...description === void 0 ? {} : { description },
|
|
1324
|
+
quickPrompts: agent.quickPrompts ?? [],
|
|
1325
|
+
...agent.metadata === void 0 ? {} : { metadata: agent.metadata }
|
|
1326
|
+
};
|
|
1327
|
+
}
|
|
1328
|
+
function agentRuntimeSummary(agent) {
|
|
1329
|
+
const tools = agentToolItems(agent);
|
|
1330
|
+
const name = agent.name ?? agent.agent.name;
|
|
1331
|
+
const description = agent.description ?? agent.agent.description;
|
|
1332
|
+
return {
|
|
1333
|
+
id: agent.id,
|
|
1334
|
+
...name === void 0 ? {} : { name },
|
|
1335
|
+
...description === void 0 ? {} : { description },
|
|
1336
|
+
model: toJsonValue(agent.agent.model),
|
|
1337
|
+
toolCount: tools.length,
|
|
1338
|
+
staticToolCount: tools.filter((item) => item.source === "static").length,
|
|
1339
|
+
dynamicToolCount: tools.filter((item) => item.source === "dynamic").length,
|
|
1340
|
+
approvalToolCount: tools.filter((item) => item.tool.approval !== void 0).length,
|
|
1341
|
+
mcpToolCount: tools.filter((item) => mcpServerName(item.tool) !== void 0).length,
|
|
1342
|
+
staticContextCount: agent.agent.staticContext.length,
|
|
1343
|
+
dynamicContextCount: agent.agent.dynamicContexts.length,
|
|
1344
|
+
observerCount: agent.agent.observers.length,
|
|
1345
|
+
hasMemory: agent.agent.memory !== void 0,
|
|
1346
|
+
hasHook: agent.agent.hook !== void 0,
|
|
1347
|
+
hasOutputSchema: agent.agent.outputSchema !== void 0,
|
|
1348
|
+
...agent.agent.defaultMaxTurns === void 0 ? {} : { defaultMaxTurns: agent.agent.defaultMaxTurns },
|
|
1349
|
+
...agent.metadata === void 0 ? {} : { metadata: agent.metadata }
|
|
1350
|
+
};
|
|
1351
|
+
}
|
|
1352
|
+
function pipelineConfig(pipeline) {
|
|
1353
|
+
const graph = pipeline.pipeline.graph();
|
|
1354
|
+
const stageNodes = graph.nodes.filter((node) => node.kind !== "input" && node.kind !== "output");
|
|
1355
|
+
return {
|
|
1356
|
+
id: pipeline.id,
|
|
1357
|
+
...pipeline.name === void 0 ? {} : { name: pipeline.name },
|
|
1358
|
+
...pipeline.description === void 0 ? {} : { description: pipeline.description },
|
|
1359
|
+
...pipeline.metadata === void 0 ? {} : { metadata: pipeline.metadata },
|
|
1360
|
+
stageCount: stageNodes.length,
|
|
1361
|
+
edgeCount: graph.edges.length,
|
|
1362
|
+
hasParallelStages: graph.nodes.some((node) => node.kind === "parallel"),
|
|
1363
|
+
agentCount: graph.nodes.filter((node) => node.kind === "agent").length,
|
|
1364
|
+
extractorCount: graph.nodes.filter((node) => node.kind === "extractor").length
|
|
1365
|
+
};
|
|
1366
|
+
}
|
|
1367
|
+
function capabilityConfig(_options, agents, pipelines, stores) {
|
|
1368
|
+
const capabilities = {
|
|
1369
|
+
agents: { enabled: true },
|
|
1370
|
+
observability: { enabled: true },
|
|
1371
|
+
status: { enabled: true }
|
|
1372
|
+
};
|
|
1373
|
+
if (stores.sessions !== void 0) {
|
|
1374
|
+
capabilities.sessions = { enabled: true };
|
|
1375
|
+
capabilities.memory = { enabled: true };
|
|
1667
1376
|
}
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
const rows = db.prepare(
|
|
1671
|
-
`SELECT id, session_id, name, status, trace_json, input_json, output, error_json,
|
|
1672
|
-
usage_json, metadata_json, observations_json, started_at, ended_at, duration_ms
|
|
1673
|
-
FROM anvia_studio_traces
|
|
1674
|
-
WHERE session_id = $sessionId
|
|
1675
|
-
ORDER BY started_at DESC
|
|
1676
|
-
LIMIT $limit`
|
|
1677
|
-
).all({
|
|
1678
|
-
$sessionId: options.sessionId,
|
|
1679
|
-
$limit: options.limit
|
|
1680
|
-
});
|
|
1681
|
-
return rows.map(toTraceSummary);
|
|
1377
|
+
if (stores.traces !== void 0) {
|
|
1378
|
+
capabilities.traces = { enabled: true };
|
|
1682
1379
|
}
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
const row = db.prepare(
|
|
1686
|
-
`SELECT id, session_id, name, status, trace_json, input_json, output, error_json,
|
|
1687
|
-
usage_json, metadata_json, observations_json, started_at, ended_at, duration_ms
|
|
1688
|
-
FROM anvia_studio_traces
|
|
1689
|
-
WHERE id = $id`
|
|
1690
|
-
).get({ $id: id });
|
|
1691
|
-
return row === void 0 ? void 0 : toTrace(row);
|
|
1380
|
+
if (pipelines.length > 0) {
|
|
1381
|
+
capabilities.pipelines = { enabled: true };
|
|
1692
1382
|
}
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
db.prepare(
|
|
1696
|
-
`INSERT INTO anvia_studio_traces (
|
|
1697
|
-
id,
|
|
1698
|
-
session_id,
|
|
1699
|
-
name,
|
|
1700
|
-
status,
|
|
1701
|
-
trace_json,
|
|
1702
|
-
input_json,
|
|
1703
|
-
output,
|
|
1704
|
-
error_json,
|
|
1705
|
-
usage_json,
|
|
1706
|
-
metadata_json,
|
|
1707
|
-
observations_json,
|
|
1708
|
-
started_at,
|
|
1709
|
-
ended_at,
|
|
1710
|
-
duration_ms
|
|
1711
|
-
) VALUES (
|
|
1712
|
-
$id,
|
|
1713
|
-
$sessionId,
|
|
1714
|
-
$name,
|
|
1715
|
-
$status,
|
|
1716
|
-
$trace,
|
|
1717
|
-
$input,
|
|
1718
|
-
$output,
|
|
1719
|
-
$error,
|
|
1720
|
-
$usage,
|
|
1721
|
-
$metadata,
|
|
1722
|
-
$observations,
|
|
1723
|
-
$startedAt,
|
|
1724
|
-
$endedAt,
|
|
1725
|
-
$durationMs
|
|
1726
|
-
)
|
|
1727
|
-
ON CONFLICT(id) DO UPDATE SET
|
|
1728
|
-
session_id = excluded.session_id,
|
|
1729
|
-
name = excluded.name,
|
|
1730
|
-
status = excluded.status,
|
|
1731
|
-
trace_json = excluded.trace_json,
|
|
1732
|
-
input_json = excluded.input_json,
|
|
1733
|
-
output = excluded.output,
|
|
1734
|
-
error_json = excluded.error_json,
|
|
1735
|
-
usage_json = excluded.usage_json,
|
|
1736
|
-
metadata_json = excluded.metadata_json,
|
|
1737
|
-
observations_json = excluded.observations_json,
|
|
1738
|
-
started_at = excluded.started_at,
|
|
1739
|
-
ended_at = excluded.ended_at,
|
|
1740
|
-
duration_ms = excluded.duration_ms`
|
|
1741
|
-
).run({
|
|
1742
|
-
$id: trace.id,
|
|
1743
|
-
$sessionId: trace.sessionId,
|
|
1744
|
-
$name: trace.name ?? null,
|
|
1745
|
-
$status: trace.status,
|
|
1746
|
-
$trace: trace.trace === void 0 ? null : JSON.stringify(trace.trace),
|
|
1747
|
-
$input: trace.input === void 0 ? null : JSON.stringify(trace.input),
|
|
1748
|
-
$output: trace.output ?? null,
|
|
1749
|
-
$error: trace.error === void 0 ? null : JSON.stringify(trace.error),
|
|
1750
|
-
$usage: trace.usage === void 0 ? null : JSON.stringify(trace.usage),
|
|
1751
|
-
$metadata: trace.metadata === void 0 ? null : JSON.stringify(trace.metadata),
|
|
1752
|
-
$observations: JSON.stringify(trace.observations),
|
|
1753
|
-
$startedAt: trace.startedAt,
|
|
1754
|
-
$endedAt: trace.endedAt ?? null,
|
|
1755
|
-
$durationMs: trace.durationMs ?? null
|
|
1756
|
-
});
|
|
1757
|
-
return trace;
|
|
1383
|
+
if (_options.evals.length > 0) {
|
|
1384
|
+
capabilities.evals = { enabled: true };
|
|
1758
1385
|
}
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
}
|
|
1763
|
-
if (this.path !== ":memory:") {
|
|
1764
|
-
mkdirSync(dirname(resolve(this.path)), { recursive: true });
|
|
1765
|
-
}
|
|
1766
|
-
const db = new (loadDatabaseSync())(this.path, {
|
|
1767
|
-
allowUnknownNamedParameters: true,
|
|
1768
|
-
timeout: 5e3
|
|
1769
|
-
});
|
|
1770
|
-
db.exec(`
|
|
1771
|
-
PRAGMA journal_mode = WAL;
|
|
1772
|
-
PRAGMA foreign_keys = ON;
|
|
1773
|
-
`);
|
|
1774
|
-
guardAgainstLegacySessionSchema(db);
|
|
1775
|
-
db.exec(`
|
|
1776
|
-
CREATE TABLE IF NOT EXISTS anvia_studio_sessions (
|
|
1777
|
-
id TEXT PRIMARY KEY,
|
|
1778
|
-
agent_id TEXT NOT NULL,
|
|
1779
|
-
title TEXT,
|
|
1780
|
-
metadata_json TEXT,
|
|
1781
|
-
created_at TEXT NOT NULL,
|
|
1782
|
-
updated_at TEXT NOT NULL
|
|
1783
|
-
) STRICT;
|
|
1784
|
-
CREATE INDEX IF NOT EXISTS anvia_studio_sessions_agent_updated_idx
|
|
1785
|
-
ON anvia_studio_sessions(agent_id, updated_at DESC);
|
|
1786
|
-
CREATE TABLE IF NOT EXISTS anvia_studio_session_messages (
|
|
1787
|
-
session_id TEXT NOT NULL,
|
|
1788
|
-
message_index INTEGER NOT NULL,
|
|
1789
|
-
role TEXT NOT NULL,
|
|
1790
|
-
message_id TEXT,
|
|
1791
|
-
created_at TEXT NOT NULL,
|
|
1792
|
-
PRIMARY KEY(session_id, message_index),
|
|
1793
|
-
FOREIGN KEY(session_id) REFERENCES anvia_studio_sessions(id) ON DELETE CASCADE
|
|
1794
|
-
) STRICT;
|
|
1795
|
-
CREATE INDEX IF NOT EXISTS anvia_studio_session_messages_session_idx
|
|
1796
|
-
ON anvia_studio_session_messages(session_id, message_index ASC);
|
|
1797
|
-
CREATE TABLE IF NOT EXISTS anvia_studio_session_message_parts (
|
|
1798
|
-
session_id TEXT NOT NULL,
|
|
1799
|
-
message_index INTEGER NOT NULL,
|
|
1800
|
-
part_index INTEGER NOT NULL,
|
|
1801
|
-
type TEXT NOT NULL,
|
|
1802
|
-
part_json TEXT NOT NULL,
|
|
1803
|
-
PRIMARY KEY(session_id, message_index, part_index),
|
|
1804
|
-
FOREIGN KEY(session_id, message_index)
|
|
1805
|
-
REFERENCES anvia_studio_session_messages(session_id, message_index)
|
|
1806
|
-
ON DELETE CASCADE
|
|
1807
|
-
) STRICT;
|
|
1808
|
-
CREATE TABLE IF NOT EXISTS anvia_studio_session_runs (
|
|
1809
|
-
run_id TEXT PRIMARY KEY,
|
|
1810
|
-
session_id TEXT NOT NULL,
|
|
1811
|
-
status TEXT NOT NULL,
|
|
1812
|
-
title TEXT,
|
|
1813
|
-
transcript_json TEXT NOT NULL,
|
|
1814
|
-
error_json TEXT,
|
|
1815
|
-
created_at TEXT NOT NULL,
|
|
1816
|
-
updated_at TEXT NOT NULL,
|
|
1817
|
-
FOREIGN KEY(session_id) REFERENCES anvia_studio_sessions(id) ON DELETE CASCADE
|
|
1818
|
-
) STRICT;
|
|
1819
|
-
CREATE INDEX IF NOT EXISTS anvia_studio_session_runs_session_created_idx
|
|
1820
|
-
ON anvia_studio_session_runs(session_id, created_at ASC);
|
|
1821
|
-
CREATE TABLE IF NOT EXISTS anvia_studio_session_logs (
|
|
1822
|
-
id TEXT PRIMARY KEY,
|
|
1823
|
-
session_id TEXT NOT NULL,
|
|
1824
|
-
run_id TEXT,
|
|
1825
|
-
sequence INTEGER NOT NULL,
|
|
1826
|
-
timestamp TEXT NOT NULL,
|
|
1827
|
-
level TEXT NOT NULL,
|
|
1828
|
-
category TEXT NOT NULL,
|
|
1829
|
-
event TEXT NOT NULL,
|
|
1830
|
-
message TEXT NOT NULL,
|
|
1831
|
-
metadata_json TEXT,
|
|
1832
|
-
UNIQUE(session_id, sequence),
|
|
1833
|
-
FOREIGN KEY(session_id) REFERENCES anvia_studio_sessions(id) ON DELETE CASCADE
|
|
1834
|
-
) STRICT;
|
|
1835
|
-
CREATE INDEX IF NOT EXISTS anvia_studio_session_logs_session_sequence_idx
|
|
1836
|
-
ON anvia_studio_session_logs(session_id, sequence ASC);
|
|
1837
|
-
CREATE TABLE IF NOT EXISTS anvia_studio_pipeline_logs (
|
|
1838
|
-
id TEXT PRIMARY KEY,
|
|
1839
|
-
pipeline_id TEXT NOT NULL,
|
|
1840
|
-
run_id TEXT,
|
|
1841
|
-
sequence INTEGER NOT NULL,
|
|
1842
|
-
timestamp TEXT NOT NULL,
|
|
1843
|
-
level TEXT NOT NULL,
|
|
1844
|
-
category TEXT NOT NULL,
|
|
1845
|
-
event TEXT NOT NULL,
|
|
1846
|
-
message TEXT NOT NULL,
|
|
1847
|
-
metadata_json TEXT,
|
|
1848
|
-
UNIQUE(pipeline_id, sequence)
|
|
1849
|
-
) STRICT;
|
|
1850
|
-
CREATE INDEX IF NOT EXISTS anvia_studio_pipeline_logs_pipeline_sequence_idx
|
|
1851
|
-
ON anvia_studio_pipeline_logs(pipeline_id, sequence ASC);
|
|
1852
|
-
CREATE TABLE IF NOT EXISTS anvia_studio_pipeline_runs (
|
|
1853
|
-
run_id TEXT PRIMARY KEY,
|
|
1854
|
-
pipeline_id TEXT NOT NULL,
|
|
1855
|
-
status TEXT NOT NULL,
|
|
1856
|
-
input_json TEXT NOT NULL,
|
|
1857
|
-
output_json TEXT,
|
|
1858
|
-
error_json TEXT,
|
|
1859
|
-
metadata_json TEXT,
|
|
1860
|
-
started_at TEXT NOT NULL,
|
|
1861
|
-
ended_at TEXT,
|
|
1862
|
-
duration_ms INTEGER
|
|
1863
|
-
) STRICT;
|
|
1864
|
-
CREATE INDEX IF NOT EXISTS anvia_studio_pipeline_runs_pipeline_started_idx
|
|
1865
|
-
ON anvia_studio_pipeline_runs(pipeline_id, started_at DESC);
|
|
1866
|
-
CREATE TABLE IF NOT EXISTS anvia_studio_traces (
|
|
1867
|
-
id TEXT PRIMARY KEY,
|
|
1868
|
-
session_id TEXT NOT NULL,
|
|
1869
|
-
name TEXT,
|
|
1870
|
-
status TEXT NOT NULL,
|
|
1871
|
-
trace_json TEXT,
|
|
1872
|
-
input_json TEXT,
|
|
1873
|
-
output TEXT,
|
|
1874
|
-
error_json TEXT,
|
|
1875
|
-
usage_json TEXT,
|
|
1876
|
-
metadata_json TEXT,
|
|
1877
|
-
observations_json TEXT NOT NULL,
|
|
1878
|
-
started_at TEXT NOT NULL,
|
|
1879
|
-
ended_at TEXT,
|
|
1880
|
-
duration_ms INTEGER
|
|
1881
|
-
) STRICT;
|
|
1882
|
-
CREATE INDEX IF NOT EXISTS anvia_studio_traces_session_started_idx
|
|
1883
|
-
ON anvia_studio_traces(session_id, started_at DESC);
|
|
1884
|
-
`);
|
|
1885
|
-
this.db = db;
|
|
1886
|
-
return db;
|
|
1386
|
+
if (agents.some(
|
|
1387
|
+
(agent) => agent.agent.toolSet.values().length > 0 || agent.agent.dynamicTools.length > 0
|
|
1388
|
+
)) {
|
|
1389
|
+
capabilities.tools = { enabled: true };
|
|
1887
1390
|
}
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
`SELECT id, agent_id, title, metadata_json, created_at, updated_at
|
|
1891
|
-
FROM anvia_studio_sessions
|
|
1892
|
-
WHERE id = $id`
|
|
1893
|
-
).get({ $id: id });
|
|
1391
|
+
if (agents.some(agentHasMcpTools)) {
|
|
1392
|
+
capabilities.mcps = { enabled: true };
|
|
1894
1393
|
}
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
WHERE session_id = $sessionId AND run_id = $runId`
|
|
1900
|
-
).get({ $sessionId: sessionId, $runId: runId });
|
|
1394
|
+
if (agents.some(
|
|
1395
|
+
(agent) => agent.agent.hook !== void 0 || agent.agent.toolSet.values().some((tool) => tool.approval)
|
|
1396
|
+
)) {
|
|
1397
|
+
capabilities.approvals = { enabled: true };
|
|
1901
1398
|
}
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
WHERE session_id = $sessionId
|
|
1907
|
-
ORDER BY created_at ASC`
|
|
1908
|
-
).all({ $sessionId: sessionId });
|
|
1399
|
+
if (agents.some(
|
|
1400
|
+
(agent) => agent.agent.staticContext.length > 0 || agent.agent.dynamicContexts.length > 0 || agent.agent.dynamicTools.length > 0
|
|
1401
|
+
)) {
|
|
1402
|
+
capabilities.knowledge = { enabled: true };
|
|
1909
1403
|
}
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1404
|
+
return capabilities;
|
|
1405
|
+
}
|
|
1406
|
+
function evalConfig(suite) {
|
|
1407
|
+
return {
|
|
1408
|
+
id: suite.id ?? suite.name,
|
|
1409
|
+
name: suite.name,
|
|
1410
|
+
...suite.description === void 0 ? {} : { description: suite.description },
|
|
1411
|
+
caseCount: suite.cases.length,
|
|
1412
|
+
metricNames: suite.metrics.map((metric) => metric.name),
|
|
1413
|
+
...suite.concurrency === void 0 ? {} : { concurrency: suite.concurrency },
|
|
1414
|
+
...suite.metadata === void 0 ? {} : { metadata: suite.metadata }
|
|
1415
|
+
};
|
|
1416
|
+
}
|
|
1417
|
+
function optionalQueryString(value) {
|
|
1418
|
+
const trimmed = value?.trim();
|
|
1419
|
+
return trimmed === void 0 || trimmed.length === 0 ? void 0 : trimmed;
|
|
1420
|
+
}
|
|
1421
|
+
function parseLimit(value) {
|
|
1422
|
+
if (value === void 0 || value.trim().length === 0) {
|
|
1423
|
+
return 50;
|
|
1917
1424
|
}
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
FROM anvia_studio_pipeline_logs
|
|
1922
|
-
WHERE pipeline_id = $pipelineId`
|
|
1923
|
-
).get({ $pipelineId: pipelineId });
|
|
1924
|
-
return row.next_sequence;
|
|
1425
|
+
const limit = Number(value);
|
|
1426
|
+
if (!Number.isInteger(limit) || limit <= 0) {
|
|
1427
|
+
return void 0;
|
|
1925
1428
|
}
|
|
1926
|
-
|
|
1927
|
-
const db = this.database();
|
|
1928
|
-
const messageRows = db.prepare(
|
|
1929
|
-
`SELECT session_id, message_index, role, message_id, created_at
|
|
1930
|
-
FROM anvia_studio_session_messages
|
|
1931
|
-
WHERE session_id = $sessionId
|
|
1932
|
-
ORDER BY message_index ASC`
|
|
1933
|
-
).all({ $sessionId: sessionId });
|
|
1934
|
-
if (messageRows.length === 0) {
|
|
1935
|
-
return [];
|
|
1936
|
-
}
|
|
1937
|
-
const partRows = db.prepare(
|
|
1938
|
-
`SELECT session_id, message_index, part_index, type, part_json
|
|
1939
|
-
FROM anvia_studio_session_message_parts
|
|
1940
|
-
WHERE session_id = $sessionId
|
|
1941
|
-
ORDER BY message_index ASC, part_index ASC`
|
|
1942
|
-
).all({ $sessionId: sessionId });
|
|
1943
|
-
const partsByMessage = /* @__PURE__ */ new Map();
|
|
1944
|
-
for (const partRow of partRows) {
|
|
1945
|
-
const parts = partsByMessage.get(partRow.message_index) ?? [];
|
|
1946
|
-
parts.push(partRow);
|
|
1947
|
-
partsByMessage.set(partRow.message_index, parts);
|
|
1948
|
-
}
|
|
1949
|
-
return messageRows.map(
|
|
1950
|
-
(row) => messageFromRows(row, partsByMessage.get(row.message_index) ?? [])
|
|
1951
|
-
);
|
|
1952
|
-
}
|
|
1953
|
-
nextMessageIndex(sessionId) {
|
|
1954
|
-
const row = this.database().prepare(
|
|
1955
|
-
`SELECT COALESCE(MAX(message_index) + 1, 0) AS next_index
|
|
1956
|
-
FROM anvia_studio_session_messages
|
|
1957
|
-
WHERE session_id = $sessionId`
|
|
1958
|
-
).get({ $sessionId: sessionId });
|
|
1959
|
-
return row.next_index;
|
|
1960
|
-
}
|
|
1961
|
-
insertMessages(sessionId, messages, startIndex, createdAt) {
|
|
1962
|
-
const db = this.database();
|
|
1963
|
-
const insertMessage = db.prepare(
|
|
1964
|
-
`INSERT INTO anvia_studio_session_messages (
|
|
1965
|
-
session_id,
|
|
1966
|
-
message_index,
|
|
1967
|
-
role,
|
|
1968
|
-
message_id,
|
|
1969
|
-
created_at
|
|
1970
|
-
) VALUES ($sessionId, $messageIndex, $role, $messageId, $createdAt)`
|
|
1971
|
-
);
|
|
1972
|
-
const insertPart = db.prepare(
|
|
1973
|
-
`INSERT INTO anvia_studio_session_message_parts (
|
|
1974
|
-
session_id,
|
|
1975
|
-
message_index,
|
|
1976
|
-
part_index,
|
|
1977
|
-
type,
|
|
1978
|
-
part_json
|
|
1979
|
-
) VALUES ($sessionId, $messageIndex, $partIndex, $type, $partJson)`
|
|
1980
|
-
);
|
|
1981
|
-
messages.forEach((message, messageOffset) => {
|
|
1982
|
-
const messageIndex = startIndex + messageOffset;
|
|
1983
|
-
insertMessage.run({
|
|
1984
|
-
$sessionId: sessionId,
|
|
1985
|
-
$messageIndex: messageIndex,
|
|
1986
|
-
$role: message.role,
|
|
1987
|
-
$messageId: message.role === "assistant" ? message.id ?? null : null,
|
|
1988
|
-
$createdAt: createdAt
|
|
1989
|
-
});
|
|
1990
|
-
messageParts(message).forEach((part, partIndex) => {
|
|
1991
|
-
insertPart.run({
|
|
1992
|
-
$sessionId: sessionId,
|
|
1993
|
-
$messageIndex: messageIndex,
|
|
1994
|
-
$partIndex: partIndex,
|
|
1995
|
-
$type: part.type,
|
|
1996
|
-
$partJson: JSON.stringify(part.value)
|
|
1997
|
-
});
|
|
1998
|
-
});
|
|
1999
|
-
});
|
|
2000
|
-
}
|
|
2001
|
-
};
|
|
2002
|
-
function toSession(row, messages, runRows = []) {
|
|
2003
|
-
const summary = toSessionSummary({ ...row, message_count: messages.length });
|
|
2004
|
-
const runTranscript = runRows.flatMap(
|
|
2005
|
-
(runRow) => parseJsonArray(runRow.transcript_json)
|
|
2006
|
-
);
|
|
2007
|
-
return {
|
|
2008
|
-
...summary,
|
|
2009
|
-
messages,
|
|
2010
|
-
transcript: renumberTranscript(runTranscript)
|
|
2011
|
-
};
|
|
2012
|
-
}
|
|
2013
|
-
function toSessionSummary(row) {
|
|
2014
|
-
const metadata = parseJsonValue(row.metadata_json);
|
|
2015
|
-
return {
|
|
2016
|
-
id: row.id,
|
|
2017
|
-
agentId: row.agent_id,
|
|
2018
|
-
...row.title === null ? {} : { title: row.title },
|
|
2019
|
-
createdAt: row.created_at,
|
|
2020
|
-
updatedAt: row.updated_at,
|
|
2021
|
-
messageCount: row.message_count,
|
|
2022
|
-
...metadata === void 0 ? {} : { metadata }
|
|
2023
|
-
};
|
|
2024
|
-
}
|
|
2025
|
-
function toSessionLog(row) {
|
|
2026
|
-
const metadata = parseJsonValue(row.metadata_json);
|
|
2027
|
-
return {
|
|
2028
|
-
id: row.id,
|
|
2029
|
-
sessionId: row.session_id,
|
|
2030
|
-
...row.run_id === null ? {} : { runId: row.run_id },
|
|
2031
|
-
sequence: row.sequence,
|
|
2032
|
-
timestamp: row.timestamp,
|
|
2033
|
-
level: row.level,
|
|
2034
|
-
category: row.category,
|
|
2035
|
-
event: row.event,
|
|
2036
|
-
message: row.message,
|
|
2037
|
-
...metadata === void 0 ? {} : { metadata }
|
|
2038
|
-
};
|
|
2039
|
-
}
|
|
2040
|
-
function toPipelineLog(row) {
|
|
2041
|
-
const metadata = parseJsonValue(row.metadata_json);
|
|
2042
|
-
return {
|
|
2043
|
-
id: row.id,
|
|
2044
|
-
pipelineId: row.pipeline_id,
|
|
2045
|
-
...row.run_id === null ? {} : { runId: row.run_id },
|
|
2046
|
-
sequence: row.sequence,
|
|
2047
|
-
timestamp: row.timestamp,
|
|
2048
|
-
level: row.level,
|
|
2049
|
-
category: row.category,
|
|
2050
|
-
event: row.event,
|
|
2051
|
-
message: row.message,
|
|
2052
|
-
...metadata === void 0 ? {} : { metadata }
|
|
2053
|
-
};
|
|
2054
|
-
}
|
|
2055
|
-
function toPipelineRun(row) {
|
|
2056
|
-
const output = parseJsonValue(row.output_json);
|
|
2057
|
-
const error = parseJsonValue(row.error_json);
|
|
2058
|
-
const metadata = parseJsonValue(row.metadata_json);
|
|
2059
|
-
return {
|
|
2060
|
-
runId: row.run_id,
|
|
2061
|
-
pipelineId: row.pipeline_id,
|
|
2062
|
-
status: row.status,
|
|
2063
|
-
input: JSON.parse(row.input_json),
|
|
2064
|
-
...output === void 0 ? {} : { output },
|
|
2065
|
-
...error === void 0 ? {} : { error },
|
|
2066
|
-
...metadata === void 0 ? {} : { metadata },
|
|
2067
|
-
startedAt: row.started_at,
|
|
2068
|
-
...row.ended_at === null ? {} : { endedAt: row.ended_at },
|
|
2069
|
-
...row.duration_ms === null ? {} : { durationMs: row.duration_ms }
|
|
2070
|
-
};
|
|
1429
|
+
return Math.min(limit, 100);
|
|
2071
1430
|
}
|
|
2072
|
-
function
|
|
2073
|
-
|
|
2074
|
-
|
|
1431
|
+
function parseTraceStatus(value) {
|
|
1432
|
+
const status = optionalQueryString(value);
|
|
1433
|
+
if (status === void 0) {
|
|
1434
|
+
return void 0;
|
|
2075
1435
|
}
|
|
2076
|
-
return
|
|
2077
|
-
type: content.type,
|
|
2078
|
-
value: content
|
|
2079
|
-
}));
|
|
1436
|
+
return status === "running" || status === "success" || status === "error" ? status : false;
|
|
2080
1437
|
}
|
|
2081
|
-
function
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
return {
|
|
2088
|
-
role: "user",
|
|
2089
|
-
content: parts
|
|
2090
|
-
};
|
|
1438
|
+
function isMessageInput(value) {
|
|
1439
|
+
return typeof value === "string" || isMessage(value);
|
|
1440
|
+
}
|
|
1441
|
+
function isMessage(value) {
|
|
1442
|
+
if (!isObject(value) || typeof value.role !== "string") {
|
|
1443
|
+
return false;
|
|
2091
1444
|
}
|
|
2092
|
-
if (
|
|
2093
|
-
return
|
|
2094
|
-
role: "assistant",
|
|
2095
|
-
...row.message_id === null ? {} : { id: row.message_id },
|
|
2096
|
-
content: parts
|
|
2097
|
-
};
|
|
1445
|
+
if (value.role === "system") {
|
|
1446
|
+
return typeof value.content === "string";
|
|
2098
1447
|
}
|
|
2099
|
-
if (
|
|
2100
|
-
return
|
|
2101
|
-
role: "tool",
|
|
2102
|
-
content: parts
|
|
2103
|
-
};
|
|
1448
|
+
if (value.role === "user" || value.role === "assistant" || value.role === "tool") {
|
|
1449
|
+
return Array.isArray(value.content);
|
|
2104
1450
|
}
|
|
2105
|
-
|
|
1451
|
+
return false;
|
|
2106
1452
|
}
|
|
2107
|
-
function
|
|
2108
|
-
|
|
2109
|
-
if (typeof first === "object" && first !== null && "type" in first && first.type === "text" && "text" in first && typeof first.text === "string") {
|
|
2110
|
-
return first.text;
|
|
2111
|
-
}
|
|
2112
|
-
return "";
|
|
1453
|
+
function isObject(value) {
|
|
1454
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2113
1455
|
}
|
|
2114
|
-
function
|
|
2115
|
-
|
|
2116
|
-
if (columns.some((column) => column.name === "messages_json")) {
|
|
2117
|
-
throw new Error(
|
|
2118
|
-
"Existing Studio SQLite DB uses the legacy messages_json schema. Delete or recreate the Studio SQLite DB to use normalized session messages."
|
|
2119
|
-
);
|
|
2120
|
-
}
|
|
1456
|
+
function isJsonObject2(value) {
|
|
1457
|
+
return isObject(value) && Object.values(value).every(isJsonValue2);
|
|
2121
1458
|
}
|
|
2122
|
-
function
|
|
2123
|
-
if (
|
|
2124
|
-
return
|
|
1459
|
+
function isJsonValue2(value) {
|
|
1460
|
+
if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
1461
|
+
return true;
|
|
2125
1462
|
}
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
"node:sqlite"
|
|
2129
|
-
));
|
|
2130
|
-
return DatabaseSync;
|
|
2131
|
-
} catch (error) {
|
|
2132
|
-
throw new Error(
|
|
2133
|
-
"The default Studio SQLite store requires Node.js with node:sqlite support. Provide custom Studio stores or disable persisted stores when running Studio in a runtime without node:sqlite.",
|
|
2134
|
-
{ cause: error }
|
|
2135
|
-
);
|
|
1463
|
+
if (Array.isArray(value)) {
|
|
1464
|
+
return value.every(isJsonValue2);
|
|
2136
1465
|
}
|
|
1466
|
+
return isJsonObject2(value);
|
|
2137
1467
|
}
|
|
2138
|
-
function
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
...trace === void 0 ? {} : { trace },
|
|
2144
|
-
...input === void 0 ? {} : { input },
|
|
2145
|
-
observations: parseJsonArray(row.observations_json)
|
|
2146
|
-
};
|
|
1468
|
+
function isAgentTraceOptions(value) {
|
|
1469
|
+
if (!isObject(value)) {
|
|
1470
|
+
return false;
|
|
1471
|
+
}
|
|
1472
|
+
return optionalString(value.name) && optionalString(value.userId) && optionalString(value.sessionId) && optionalString(value.version) && optionalString(value.traceId) && optionalBoolean(value.failOnObserverError) && optionalStringArray(value.tags) && optionalObject(value.metadata);
|
|
2147
1473
|
}
|
|
2148
|
-
function
|
|
2149
|
-
|
|
2150
|
-
const error = parseJsonValue(row.error_json);
|
|
2151
|
-
const usage = parseJsonValue(row.usage_json);
|
|
2152
|
-
const metadata = parseJsonValue(row.metadata_json);
|
|
2153
|
-
return {
|
|
2154
|
-
id: row.id,
|
|
2155
|
-
sessionId: row.session_id,
|
|
2156
|
-
...row.name === null ? {} : { name: row.name },
|
|
2157
|
-
status: row.status,
|
|
2158
|
-
startedAt: row.started_at,
|
|
2159
|
-
...row.ended_at === null ? {} : { endedAt: row.ended_at },
|
|
2160
|
-
...row.duration_ms === null ? {} : { durationMs: row.duration_ms },
|
|
2161
|
-
...row.output === null ? {} : { output: row.output },
|
|
2162
|
-
...error === void 0 ? {} : { error },
|
|
2163
|
-
...usage === void 0 ? {} : { usage },
|
|
2164
|
-
...metadata === void 0 ? {} : { metadata },
|
|
2165
|
-
observationCount: observations.length
|
|
2166
|
-
};
|
|
1474
|
+
function optionalString(value) {
|
|
1475
|
+
return value === void 0 || typeof value === "string";
|
|
2167
1476
|
}
|
|
2168
|
-
function
|
|
2169
|
-
|
|
2170
|
-
return Array.isArray(parsed) ? parsed : [];
|
|
1477
|
+
function optionalBoolean(value) {
|
|
1478
|
+
return value === void 0 || typeof value === "boolean";
|
|
2171
1479
|
}
|
|
2172
|
-
function
|
|
2173
|
-
|
|
2174
|
-
return void 0;
|
|
2175
|
-
}
|
|
2176
|
-
return JSON.parse(value);
|
|
1480
|
+
function optionalStringArray(value) {
|
|
1481
|
+
return value === void 0 || Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
2177
1482
|
}
|
|
2178
|
-
function
|
|
2179
|
-
|
|
2180
|
-
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
1483
|
+
function optionalObject(value) {
|
|
1484
|
+
return value === void 0 || isObject(value);
|
|
2181
1485
|
}
|
|
2182
|
-
function
|
|
2183
|
-
|
|
2184
|
-
return {
|
|
2185
|
-
name: error.name,
|
|
2186
|
-
message: error.message
|
|
2187
|
-
};
|
|
2188
|
-
}
|
|
2189
|
-
if (error === null || typeof error === "string" || typeof error === "number" || typeof error === "boolean") {
|
|
2190
|
-
return error;
|
|
2191
|
-
}
|
|
2192
|
-
return String(error);
|
|
1486
|
+
function isNonNegativeInteger(value) {
|
|
1487
|
+
return Number.isInteger(value) && typeof value === "number" && value >= 0;
|
|
2193
1488
|
}
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
import { ToolSet } from "@anvia/core/tool";
|
|
2197
|
-
var MCP_TOOL_METADATA_KEY = /* @__PURE__ */ Symbol.for("anvia.mcp.tool.metadata");
|
|
2198
|
-
function agentToolItems(agent) {
|
|
2199
|
-
return [
|
|
2200
|
-
...agent.agent.toolSet.values().map((tool) => ({ tool, source: "static" })),
|
|
2201
|
-
...agent.agent.dynamicTools.flatMap((registration) => {
|
|
2202
|
-
const maybeToolSet = registration.index.toolSet;
|
|
2203
|
-
if (!(maybeToolSet instanceof ToolSet)) {
|
|
2204
|
-
return [];
|
|
2205
|
-
}
|
|
2206
|
-
return maybeToolSet.values().map((tool) => ({ tool, source: "dynamic" }));
|
|
2207
|
-
})
|
|
2208
|
-
];
|
|
1489
|
+
function isPositiveInteger(value) {
|
|
1490
|
+
return Number.isInteger(value) && typeof value === "number" && value > 0;
|
|
2209
1491
|
}
|
|
2210
|
-
function
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
...typeof policy.reason === "string" ? { reason: policy.reason } : {},
|
|
2219
|
-
...typeof policy.rejectMessage === "string" ? { rejectMessage: policy.rejectMessage } : {}
|
|
2220
|
-
};
|
|
1492
|
+
function unsupportedCapability(c, capability) {
|
|
1493
|
+
return errorResponse(
|
|
1494
|
+
c,
|
|
1495
|
+
501,
|
|
1496
|
+
"unsupported_capability",
|
|
1497
|
+
`Capability "${capability}" is not implemented by this runner`,
|
|
1498
|
+
{ capability }
|
|
1499
|
+
);
|
|
2221
1500
|
}
|
|
2222
|
-
function
|
|
2223
|
-
const
|
|
2224
|
-
|
|
2225
|
-
|
|
1501
|
+
function errorResponse(c, status, code, message, details) {
|
|
1502
|
+
const body = {
|
|
1503
|
+
error: {
|
|
1504
|
+
code,
|
|
1505
|
+
message
|
|
1506
|
+
}
|
|
1507
|
+
};
|
|
1508
|
+
if (details !== void 0) {
|
|
1509
|
+
body.error.details = details;
|
|
2226
1510
|
}
|
|
2227
|
-
|
|
2228
|
-
return typeof serverName === "string" && serverName.length > 0 ? serverName : void 0;
|
|
1511
|
+
return c.json(body, status);
|
|
2229
1512
|
}
|
|
2230
|
-
function
|
|
2231
|
-
return
|
|
1513
|
+
function serializeError(error) {
|
|
1514
|
+
return serializeUnknown(error);
|
|
2232
1515
|
}
|
|
2233
1516
|
|
|
2234
|
-
// src/runtime/
|
|
2235
|
-
function
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
}
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
return
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
}
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
1517
|
+
// src/runtime/approvals.ts
|
|
1518
|
+
function registerApprovalRoutes(app, approvals) {
|
|
1519
|
+
app.get("/approvals", (c) => {
|
|
1520
|
+
const status = parseApprovalStatus(c.req.query("status"));
|
|
1521
|
+
if (status === false) {
|
|
1522
|
+
return errorResponse(c, 400, "bad_request", "status must be pending or resolved");
|
|
1523
|
+
}
|
|
1524
|
+
const options = {};
|
|
1525
|
+
const runId = optionalQueryString(c.req.query("runId"));
|
|
1526
|
+
const agentId = optionalQueryString(c.req.query("agentId"));
|
|
1527
|
+
const sessionId = optionalQueryString(c.req.query("sessionId"));
|
|
1528
|
+
if (status !== void 0) {
|
|
1529
|
+
options.status = status;
|
|
1530
|
+
}
|
|
1531
|
+
if (runId !== void 0) {
|
|
1532
|
+
options.runId = runId;
|
|
1533
|
+
}
|
|
1534
|
+
if (agentId !== void 0) {
|
|
1535
|
+
options.agentId = agentId;
|
|
1536
|
+
}
|
|
1537
|
+
if (sessionId !== void 0) {
|
|
1538
|
+
options.sessionId = sessionId;
|
|
1539
|
+
}
|
|
1540
|
+
return c.json({
|
|
1541
|
+
approvals: approvals.list(options)
|
|
1542
|
+
});
|
|
1543
|
+
});
|
|
1544
|
+
app.post("/approvals/:approvalId/decision", async (c) => {
|
|
1545
|
+
const body = await parseApprovalDecisionRequest(c);
|
|
1546
|
+
if ("error" in body) {
|
|
1547
|
+
return body.error;
|
|
1548
|
+
}
|
|
1549
|
+
const result = approvals.decide(c.req.param("approvalId"), body);
|
|
1550
|
+
if (result === "missing") {
|
|
1551
|
+
return errorResponse(c, 404, "not_found", "Approval not found");
|
|
1552
|
+
}
|
|
1553
|
+
if (result === "resolved") {
|
|
1554
|
+
return errorResponse(c, 409, "conflict", "Approval is already resolved");
|
|
1555
|
+
}
|
|
1556
|
+
return c.json(result);
|
|
1557
|
+
});
|
|
2272
1558
|
}
|
|
2273
|
-
function
|
|
2274
|
-
|
|
1559
|
+
function parseApprovalStatus(value) {
|
|
1560
|
+
const status = optionalQueryString(value);
|
|
1561
|
+
if (status === void 0) {
|
|
2275
1562
|
return void 0;
|
|
2276
1563
|
}
|
|
2277
|
-
|
|
2278
|
-
return options.stores.pipelineLogs;
|
|
2279
|
-
}
|
|
2280
|
-
if (sessionStore !== void 0 && isPipelineLogStore(sessionStore)) {
|
|
2281
|
-
return sessionStore;
|
|
2282
|
-
}
|
|
2283
|
-
return defaultStore;
|
|
1564
|
+
return status === "pending" || status === "resolved" ? status : false;
|
|
2284
1565
|
}
|
|
2285
|
-
function
|
|
2286
|
-
|
|
2287
|
-
|
|
1566
|
+
async function parseApprovalDecisionRequest(c) {
|
|
1567
|
+
let body;
|
|
1568
|
+
try {
|
|
1569
|
+
body = await c.req.json();
|
|
1570
|
+
} catch {
|
|
1571
|
+
return { error: errorResponse(c, 400, "bad_request", "Request body must be JSON") };
|
|
2288
1572
|
}
|
|
2289
|
-
if (
|
|
2290
|
-
return
|
|
1573
|
+
if (!isObject(body)) {
|
|
1574
|
+
return { error: errorResponse(c, 400, "bad_request", "Request body must be an object") };
|
|
2291
1575
|
}
|
|
2292
|
-
if (
|
|
2293
|
-
return
|
|
1576
|
+
if (typeof body.approved !== "boolean") {
|
|
1577
|
+
return { error: errorResponse(c, 400, "bad_request", "approved must be a boolean") };
|
|
2294
1578
|
}
|
|
2295
|
-
if (
|
|
2296
|
-
return
|
|
1579
|
+
if ("reason" in body && typeof body.reason !== "string") {
|
|
1580
|
+
return { error: errorResponse(c, 400, "bad_request", "reason must be a string") };
|
|
2297
1581
|
}
|
|
2298
|
-
return defaultStore;
|
|
2299
|
-
}
|
|
2300
|
-
function isTraceStore(store) {
|
|
2301
|
-
const candidate = store;
|
|
2302
|
-
return typeof candidate.listSessionTraces === "function" && typeof candidate.getTrace === "function" && typeof candidate.saveTrace === "function";
|
|
2303
|
-
}
|
|
2304
|
-
function isPipelineLogStore(store) {
|
|
2305
|
-
const candidate = store;
|
|
2306
|
-
return typeof candidate.appendPipelineLog === "function" && typeof candidate.listPipelineLogs === "function";
|
|
2307
|
-
}
|
|
2308
|
-
function isPipelineRunStore(store) {
|
|
2309
|
-
const candidate = store;
|
|
2310
|
-
return typeof candidate.savePipelineRun === "function" && typeof candidate.getPipelineRun === "function" && typeof candidate.listPipelineRuns === "function";
|
|
2311
|
-
}
|
|
2312
|
-
function unsupportedCapabilities(stores) {
|
|
2313
|
-
return [
|
|
2314
|
-
...stores.sessions === void 0 ? ["sessions"] : [],
|
|
2315
|
-
...stores.traces === void 0 ? ["traces"] : []
|
|
2316
|
-
];
|
|
2317
|
-
}
|
|
2318
|
-
function normalizeAgents(agents) {
|
|
2319
|
-
const ids = /* @__PURE__ */ new Set();
|
|
2320
|
-
return agents.map((agent) => {
|
|
2321
|
-
const id = agent.id.trim();
|
|
2322
|
-
if (id.length === 0) {
|
|
2323
|
-
throw new Error("Studio agent id cannot be empty");
|
|
2324
|
-
}
|
|
2325
|
-
if (ids.has(id)) {
|
|
2326
|
-
throw new Error(`Duplicate runner agent id: ${id}`);
|
|
2327
|
-
}
|
|
2328
|
-
ids.add(id);
|
|
2329
|
-
return { ...agent, id };
|
|
2330
|
-
});
|
|
2331
|
-
}
|
|
2332
|
-
function normalizePipelines(pipelines) {
|
|
2333
|
-
const ids = /* @__PURE__ */ new Set();
|
|
2334
|
-
return pipelines.map((pipeline) => {
|
|
2335
|
-
const id = pipeline.id.trim();
|
|
2336
|
-
if (id.length === 0) {
|
|
2337
|
-
throw new Error("Studio pipeline id cannot be empty");
|
|
2338
|
-
}
|
|
2339
|
-
if (ids.has(id)) {
|
|
2340
|
-
throw new Error(`Duplicate Studio pipeline id: ${id}`);
|
|
2341
|
-
}
|
|
2342
|
-
ids.add(id);
|
|
2343
|
-
return { ...pipeline, id };
|
|
2344
|
-
});
|
|
2345
|
-
}
|
|
2346
|
-
function buildConfig(options, agents, pipelines, stores) {
|
|
2347
1582
|
return {
|
|
2348
|
-
|
|
2349
|
-
...
|
|
2350
|
-
...options.description === void 0 ? {} : { description: options.description },
|
|
2351
|
-
...options.version === void 0 ? {} : { version: options.version },
|
|
2352
|
-
agents: agents.map(agentConfig),
|
|
2353
|
-
pipelines: pipelines.map(pipelineConfig),
|
|
2354
|
-
evals: options.evals.map(evalConfig),
|
|
2355
|
-
chat: {
|
|
2356
|
-
quickPrompts: Object.fromEntries(agents.map((agent) => [agent.id, agent.quickPrompts ?? []]))
|
|
2357
|
-
},
|
|
2358
|
-
capabilities: capabilityConfig(options, agents, pipelines, stores),
|
|
2359
|
-
unsupportedCapabilities: unsupportedCapabilities(stores)
|
|
1583
|
+
approved: body.approved,
|
|
1584
|
+
...typeof body.reason === "string" && body.reason.trim().length > 0 ? { reason: body.reason.trim() } : {}
|
|
2360
1585
|
};
|
|
2361
1586
|
}
|
|
2362
|
-
function
|
|
2363
|
-
|
|
2364
|
-
}
|
|
2365
|
-
function agentConfig(agent) {
|
|
2366
|
-
const name = agent.name ?? agent.agent.name;
|
|
2367
|
-
const description = agent.description ?? agent.agent.description;
|
|
1587
|
+
function createApprovalRuntime() {
|
|
1588
|
+
const approvals = /* @__PURE__ */ new Map();
|
|
2368
1589
|
return {
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
1590
|
+
approvals,
|
|
1591
|
+
createHook(context) {
|
|
1592
|
+
const handleApprovalRequest = async ({ toolName, toolCallId, internalCallId, args, tool: control }, request) => {
|
|
1593
|
+
const decision = await requestApproval(approvals, context, {
|
|
1594
|
+
toolName,
|
|
1595
|
+
...toolCallId === void 0 ? {} : { toolCallId },
|
|
1596
|
+
internalCallId,
|
|
1597
|
+
args,
|
|
1598
|
+
...request.reason === void 0 ? {} : { reason: request.reason },
|
|
1599
|
+
...request.rejectMessage === void 0 ? {} : { rejectMessage: request.rejectMessage }
|
|
1600
|
+
});
|
|
1601
|
+
return decision.approved ? control.run() : control.skip(decision.reason ?? request.rejectMessage ?? "Rejected in Anvia Studio.");
|
|
1602
|
+
};
|
|
1603
|
+
return {
|
|
1604
|
+
...createHook({
|
|
1605
|
+
async onToolCall({ toolName, toolCallId, internalCallId, args, tool: control }) {
|
|
1606
|
+
const registeredTool = context.getTool(toolName);
|
|
1607
|
+
if (registeredTool?.approval === void 0) {
|
|
1608
|
+
return control.run();
|
|
1609
|
+
}
|
|
1610
|
+
const approval = registeredTool.approval;
|
|
1611
|
+
const rawParsedArgs = parseToolArgs(args);
|
|
1612
|
+
const parsedArgs = registeredTool.parseApprovalArgs?.(rawParsedArgs) ?? rawParsedArgs;
|
|
1613
|
+
const approvalContext = {
|
|
1614
|
+
toolName,
|
|
1615
|
+
args: parsedArgs,
|
|
1616
|
+
rawArgs: args,
|
|
1617
|
+
...toolCallId === void 0 ? {} : { toolCallId },
|
|
1618
|
+
internalCallId,
|
|
1619
|
+
run: {
|
|
1620
|
+
agentId: context.agentId,
|
|
1621
|
+
runId: context.runId,
|
|
1622
|
+
...context.sessionId === void 0 ? {} : { sessionId: context.sessionId },
|
|
1623
|
+
...context.metadata === void 0 ? {} : { metadata: context.metadata }
|
|
1624
|
+
}
|
|
1625
|
+
};
|
|
1626
|
+
const required = await approval.when(approvalContext);
|
|
1627
|
+
if (!required) {
|
|
1628
|
+
return control.run();
|
|
1629
|
+
}
|
|
1630
|
+
const reason = await resolveApprovalText(approval.reason, approvalContext);
|
|
1631
|
+
const rejectMessage = await resolveApprovalText(
|
|
1632
|
+
approval.rejectMessage,
|
|
1633
|
+
approvalContext
|
|
1634
|
+
);
|
|
1635
|
+
const decision = await requestApproval(approvals, context, {
|
|
1636
|
+
toolName,
|
|
1637
|
+
...toolCallId === void 0 ? {} : { toolCallId },
|
|
1638
|
+
internalCallId,
|
|
1639
|
+
args,
|
|
1640
|
+
...reason === void 0 ? {} : { reason },
|
|
1641
|
+
...rejectMessage === void 0 ? {} : { rejectMessage }
|
|
1642
|
+
});
|
|
1643
|
+
return decision.approved ? control.run() : control.skip(decision.reason ?? rejectMessage ?? "Rejected in Anvia Studio.");
|
|
1644
|
+
}
|
|
1645
|
+
}),
|
|
1646
|
+
handleApprovalRequest
|
|
1647
|
+
};
|
|
1648
|
+
},
|
|
1649
|
+
list(options) {
|
|
1650
|
+
return [...approvals.values()].filter((approval) => {
|
|
1651
|
+
if (options.status === "pending" && approval.status !== "pending") {
|
|
1652
|
+
return false;
|
|
1653
|
+
}
|
|
1654
|
+
if (options.status === "resolved" && approval.status === "pending") {
|
|
1655
|
+
return false;
|
|
1656
|
+
}
|
|
1657
|
+
if (options.runId !== void 0 && approval.runId !== options.runId) {
|
|
1658
|
+
return false;
|
|
1659
|
+
}
|
|
1660
|
+
if (options.agentId !== void 0 && approval.agentId !== options.agentId) {
|
|
1661
|
+
return false;
|
|
1662
|
+
}
|
|
1663
|
+
if (options.sessionId !== void 0 && approval.sessionId !== options.sessionId) {
|
|
1664
|
+
return false;
|
|
1665
|
+
}
|
|
1666
|
+
return true;
|
|
1667
|
+
}).map(publicApproval);
|
|
1668
|
+
},
|
|
1669
|
+
decide(id, decision) {
|
|
1670
|
+
const approval = approvals.get(id);
|
|
1671
|
+
if (approval === void 0) {
|
|
1672
|
+
return "missing";
|
|
1673
|
+
}
|
|
1674
|
+
if (!isPendingApproval(approval)) {
|
|
1675
|
+
return "resolved";
|
|
1676
|
+
}
|
|
1677
|
+
const reason = decision.approved ? decision.reason : decision.reason ?? approval.rejectMessage ?? "Rejected in Anvia Studio.";
|
|
1678
|
+
const resolved = resolveApproval(approval, decision.approved ? "approved" : "rejected", {
|
|
1679
|
+
...reason === void 0 ? {} : { reason }
|
|
1680
|
+
});
|
|
1681
|
+
approvals.set(id, resolved);
|
|
1682
|
+
approval.emit?.({ type: "tool_approval_result", approval: resolved });
|
|
1683
|
+
approval.resolve({
|
|
1684
|
+
approved: decision.approved,
|
|
1685
|
+
...reason === void 0 ? {} : { reason }
|
|
1686
|
+
});
|
|
1687
|
+
return publicApproval(resolved);
|
|
1688
|
+
}
|
|
2398
1689
|
};
|
|
2399
1690
|
}
|
|
2400
|
-
function
|
|
2401
|
-
const
|
|
2402
|
-
const
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
...
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
1691
|
+
async function requestApproval(approvals, context, request) {
|
|
1692
|
+
const id = globalThis.crypto.randomUUID();
|
|
1693
|
+
const approval = {
|
|
1694
|
+
id,
|
|
1695
|
+
runId: context.runId,
|
|
1696
|
+
agentId: context.agentId,
|
|
1697
|
+
...context.sessionId === void 0 ? {} : { sessionId: context.sessionId },
|
|
1698
|
+
toolName: request.toolName,
|
|
1699
|
+
...request.toolCallId === void 0 ? {} : { callId: request.toolCallId },
|
|
1700
|
+
internalCallId: request.internalCallId,
|
|
1701
|
+
args: request.args,
|
|
1702
|
+
status: "pending",
|
|
1703
|
+
requestedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1704
|
+
...request.reason === void 0 ? {} : { reason: request.reason },
|
|
1705
|
+
...request.rejectMessage === void 0 ? {} : { rejectMessage: request.rejectMessage },
|
|
1706
|
+
...context.emit === void 0 ? {} : { emit: context.emit },
|
|
1707
|
+
resolve: () => {
|
|
1708
|
+
}
|
|
2413
1709
|
};
|
|
1710
|
+
const decision = new Promise((resolve2) => {
|
|
1711
|
+
approval.resolve = (decision2) => {
|
|
1712
|
+
const current = approvals.get(id);
|
|
1713
|
+
if (!isPendingApproval(current)) {
|
|
1714
|
+
if (current !== void 0) {
|
|
1715
|
+
resolve2({
|
|
1716
|
+
approved: current.status === "approved",
|
|
1717
|
+
...current.reason === void 0 ? {} : { reason: current.reason }
|
|
1718
|
+
});
|
|
1719
|
+
}
|
|
1720
|
+
return;
|
|
1721
|
+
}
|
|
1722
|
+
const reason = decision2.approved ? decision2.reason : decision2.reason ?? request.rejectMessage ?? "Rejected in Anvia Studio.";
|
|
1723
|
+
const resolved = resolveApproval(current, decision2.approved ? "approved" : "rejected", {
|
|
1724
|
+
...reason === void 0 ? {} : { reason }
|
|
1725
|
+
});
|
|
1726
|
+
approvals.set(id, resolved);
|
|
1727
|
+
context.emit?.({ type: "tool_approval_result", approval: resolved });
|
|
1728
|
+
resolve2({
|
|
1729
|
+
approved: decision2.approved,
|
|
1730
|
+
...reason === void 0 ? {} : { reason }
|
|
1731
|
+
});
|
|
1732
|
+
};
|
|
1733
|
+
});
|
|
1734
|
+
approvals.set(id, approval);
|
|
1735
|
+
context.emit?.({ type: "tool_approval_request", approval: publicApproval(approval) });
|
|
1736
|
+
return decision;
|
|
2414
1737
|
}
|
|
2415
|
-
function
|
|
2416
|
-
|
|
2417
|
-
agents: { enabled: true },
|
|
2418
|
-
observability: { enabled: true },
|
|
2419
|
-
status: { enabled: true }
|
|
2420
|
-
};
|
|
2421
|
-
if (stores.sessions !== void 0) {
|
|
2422
|
-
capabilities.sessions = { enabled: true };
|
|
2423
|
-
capabilities.memory = { enabled: true };
|
|
2424
|
-
}
|
|
2425
|
-
if (stores.traces !== void 0) {
|
|
2426
|
-
capabilities.traces = { enabled: true };
|
|
2427
|
-
}
|
|
2428
|
-
if (pipelines.length > 0) {
|
|
2429
|
-
capabilities.pipelines = { enabled: true };
|
|
2430
|
-
}
|
|
2431
|
-
if (_options.evals.length > 0) {
|
|
2432
|
-
capabilities.evals = { enabled: true };
|
|
2433
|
-
}
|
|
2434
|
-
if (agents.some(
|
|
2435
|
-
(agent) => agent.agent.toolSet.values().length > 0 || agent.agent.dynamicTools.length > 0
|
|
2436
|
-
)) {
|
|
2437
|
-
capabilities.tools = { enabled: true };
|
|
2438
|
-
}
|
|
2439
|
-
if (agents.some(agentHasMcpTools)) {
|
|
2440
|
-
capabilities.mcps = { enabled: true };
|
|
2441
|
-
}
|
|
2442
|
-
if (agents.some(
|
|
2443
|
-
(agent) => agent.agent.hook !== void 0 || agent.agent.toolSet.values().some((tool) => tool.approval)
|
|
2444
|
-
)) {
|
|
2445
|
-
capabilities.approvals = { enabled: true };
|
|
2446
|
-
}
|
|
2447
|
-
if (agents.some(
|
|
2448
|
-
(agent) => agent.agent.staticContext.length > 0 || agent.agent.dynamicContexts.length > 0 || agent.agent.dynamicTools.length > 0
|
|
2449
|
-
)) {
|
|
2450
|
-
capabilities.knowledge = { enabled: true };
|
|
2451
|
-
}
|
|
2452
|
-
return capabilities;
|
|
1738
|
+
async function resolveApprovalText(value, context) {
|
|
1739
|
+
return typeof value === "function" ? value(context) : value;
|
|
2453
1740
|
}
|
|
2454
|
-
function
|
|
2455
|
-
return
|
|
2456
|
-
id: suite.id ?? suite.name,
|
|
2457
|
-
name: suite.name,
|
|
2458
|
-
...suite.description === void 0 ? {} : { description: suite.description },
|
|
2459
|
-
caseCount: suite.cases.length,
|
|
2460
|
-
metricNames: suite.metrics.map((metric) => metric.name),
|
|
2461
|
-
...suite.concurrency === void 0 ? {} : { concurrency: suite.concurrency },
|
|
2462
|
-
...suite.metadata === void 0 ? {} : { metadata: suite.metadata }
|
|
2463
|
-
};
|
|
1741
|
+
function isPendingApproval(approval) {
|
|
1742
|
+
return approval !== void 0 && approval.status === "pending" && "resolve" in approval;
|
|
2464
1743
|
}
|
|
2465
|
-
function
|
|
2466
|
-
|
|
2467
|
-
|
|
1744
|
+
function resolveApproval(approval, status, options = {}) {
|
|
1745
|
+
return publicApproval({
|
|
1746
|
+
...approval,
|
|
1747
|
+
status,
|
|
1748
|
+
resolvedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1749
|
+
...options.reason === void 0 ? {} : { reason: options.reason }
|
|
1750
|
+
});
|
|
2468
1751
|
}
|
|
2469
|
-
function
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
return void 0;
|
|
2476
|
-
}
|
|
2477
|
-
return Math.min(limit, 100);
|
|
2478
|
-
}
|
|
2479
|
-
function parseTraceStatus(value) {
|
|
2480
|
-
const status = optionalQueryString(value);
|
|
2481
|
-
if (status === void 0) {
|
|
2482
|
-
return void 0;
|
|
2483
|
-
}
|
|
2484
|
-
return status === "running" || status === "success" || status === "error" ? status : false;
|
|
2485
|
-
}
|
|
2486
|
-
function isMessageInput(value) {
|
|
2487
|
-
return typeof value === "string" || isMessage(value);
|
|
2488
|
-
}
|
|
2489
|
-
function isMessage(value) {
|
|
2490
|
-
if (!isObject(value) || typeof value.role !== "string") {
|
|
2491
|
-
return false;
|
|
2492
|
-
}
|
|
2493
|
-
if (value.role === "system") {
|
|
2494
|
-
return typeof value.content === "string";
|
|
2495
|
-
}
|
|
2496
|
-
if (value.role === "user" || value.role === "assistant" || value.role === "tool") {
|
|
2497
|
-
return Array.isArray(value.content);
|
|
2498
|
-
}
|
|
2499
|
-
return false;
|
|
2500
|
-
}
|
|
2501
|
-
function isObject(value) {
|
|
2502
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2503
|
-
}
|
|
2504
|
-
function isJsonObject2(value) {
|
|
2505
|
-
return isObject(value) && Object.values(value).every(isJsonValue2);
|
|
2506
|
-
}
|
|
2507
|
-
function isJsonValue2(value) {
|
|
2508
|
-
if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
2509
|
-
return true;
|
|
2510
|
-
}
|
|
2511
|
-
if (Array.isArray(value)) {
|
|
2512
|
-
return value.every(isJsonValue2);
|
|
2513
|
-
}
|
|
2514
|
-
return isJsonObject2(value);
|
|
2515
|
-
}
|
|
2516
|
-
function isAgentTraceOptions(value) {
|
|
2517
|
-
if (!isObject(value)) {
|
|
2518
|
-
return false;
|
|
2519
|
-
}
|
|
2520
|
-
return optionalString(value.name) && optionalString(value.userId) && optionalString(value.sessionId) && optionalString(value.version) && optionalString(value.traceId) && optionalBoolean(value.failOnObserverError) && optionalStringArray(value.tags) && optionalObject(value.metadata);
|
|
2521
|
-
}
|
|
2522
|
-
function optionalString(value) {
|
|
2523
|
-
return value === void 0 || typeof value === "string";
|
|
2524
|
-
}
|
|
2525
|
-
function optionalBoolean(value) {
|
|
2526
|
-
return value === void 0 || typeof value === "boolean";
|
|
2527
|
-
}
|
|
2528
|
-
function optionalStringArray(value) {
|
|
2529
|
-
return value === void 0 || Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
2530
|
-
}
|
|
2531
|
-
function optionalObject(value) {
|
|
2532
|
-
return value === void 0 || isObject(value);
|
|
2533
|
-
}
|
|
2534
|
-
function isNonNegativeInteger(value) {
|
|
2535
|
-
return Number.isInteger(value) && typeof value === "number" && value >= 0;
|
|
2536
|
-
}
|
|
2537
|
-
function isPositiveInteger(value) {
|
|
2538
|
-
return Number.isInteger(value) && typeof value === "number" && value > 0;
|
|
2539
|
-
}
|
|
2540
|
-
function unsupportedCapability(c, capability) {
|
|
2541
|
-
return errorResponse(
|
|
2542
|
-
c,
|
|
2543
|
-
501,
|
|
2544
|
-
"unsupported_capability",
|
|
2545
|
-
`Capability "${capability}" is not implemented by this runner`,
|
|
2546
|
-
{ capability }
|
|
2547
|
-
);
|
|
2548
|
-
}
|
|
2549
|
-
function errorResponse(c, status, code, message, details) {
|
|
2550
|
-
const body = {
|
|
2551
|
-
error: {
|
|
2552
|
-
code,
|
|
2553
|
-
message
|
|
2554
|
-
}
|
|
2555
|
-
};
|
|
2556
|
-
if (details !== void 0) {
|
|
2557
|
-
body.error.details = details;
|
|
2558
|
-
}
|
|
2559
|
-
return c.json(body, status);
|
|
2560
|
-
}
|
|
2561
|
-
function serializeError(error) {
|
|
2562
|
-
return serializeUnknown(error);
|
|
1752
|
+
function publicApproval(approval) {
|
|
1753
|
+
const { emit, rejectMessage, resolve: resolve2, ...rest } = approval;
|
|
1754
|
+
void emit;
|
|
1755
|
+
void rejectMessage;
|
|
1756
|
+
void resolve2;
|
|
1757
|
+
return rest;
|
|
2563
1758
|
}
|
|
2564
1759
|
|
|
2565
|
-
// src/runtime/
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
const
|
|
2576
|
-
if (
|
|
2577
|
-
|
|
2578
|
-
}
|
|
2579
|
-
if (runId !== void 0) {
|
|
2580
|
-
options.runId = runId;
|
|
2581
|
-
}
|
|
2582
|
-
if (agentId !== void 0) {
|
|
2583
|
-
options.agentId = agentId;
|
|
2584
|
-
}
|
|
2585
|
-
if (sessionId !== void 0) {
|
|
2586
|
-
options.sessionId = sessionId;
|
|
1760
|
+
// src/runtime/evals.ts
|
|
1761
|
+
import { runEvalSuite } from "@anvia/core/evals";
|
|
1762
|
+
function registerEvalRoutes(app, props) {
|
|
1763
|
+
app.get(
|
|
1764
|
+
"/evals",
|
|
1765
|
+
(c) => c.json({
|
|
1766
|
+
evals: props.evals.map(evalConfig)
|
|
1767
|
+
})
|
|
1768
|
+
);
|
|
1769
|
+
app.get("/evals/:evalId", (c) => {
|
|
1770
|
+
const suite = props.evalMap.get(c.req.param("evalId"));
|
|
1771
|
+
if (suite === void 0) {
|
|
1772
|
+
return errorResponse(c, 404, "not_found", "Eval suite not found");
|
|
2587
1773
|
}
|
|
2588
|
-
return c.json(
|
|
2589
|
-
approvals: approvals.list(options)
|
|
2590
|
-
});
|
|
1774
|
+
return c.json(evalConfig(suite));
|
|
2591
1775
|
});
|
|
2592
|
-
app.post("/
|
|
2593
|
-
const
|
|
1776
|
+
app.post("/evals/:evalId/runs", async (c) => {
|
|
1777
|
+
const suite = props.evalMap.get(c.req.param("evalId"));
|
|
1778
|
+
if (suite === void 0) {
|
|
1779
|
+
return errorResponse(c, 404, "not_found", "Eval suite not found");
|
|
1780
|
+
}
|
|
1781
|
+
const body = await parseEvalRunRequest(c);
|
|
2594
1782
|
if ("error" in body) {
|
|
2595
1783
|
return body.error;
|
|
2596
1784
|
}
|
|
2597
|
-
const
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
1785
|
+
const runId = globalThis.crypto.randomUUID();
|
|
1786
|
+
const startedAt = Date.now();
|
|
1787
|
+
const result = await runEvalSuite({
|
|
1788
|
+
...suite,
|
|
1789
|
+
...body.concurrency === void 0 ? {} : { concurrency: body.concurrency }
|
|
1790
|
+
});
|
|
1791
|
+
const endedAt = Date.now();
|
|
1792
|
+
const jsonResult = toJsonValue(result);
|
|
1793
|
+
const response = {
|
|
1794
|
+
runId,
|
|
1795
|
+
suiteId: suite.id ?? suite.name,
|
|
1796
|
+
startedAt: new Date(startedAt).toISOString(),
|
|
1797
|
+
endedAt: new Date(endedAt).toISOString(),
|
|
1798
|
+
durationMs: endedAt - startedAt,
|
|
1799
|
+
result: isJsonObject2(jsonResult) ? jsonResult : { value: jsonResult }
|
|
1800
|
+
};
|
|
1801
|
+
return c.json(response);
|
|
2605
1802
|
});
|
|
2606
1803
|
}
|
|
2607
|
-
function
|
|
2608
|
-
|
|
2609
|
-
if (status === void 0) {
|
|
2610
|
-
return void 0;
|
|
2611
|
-
}
|
|
2612
|
-
return status === "pending" || status === "resolved" ? status : false;
|
|
2613
|
-
}
|
|
2614
|
-
async function parseApprovalDecisionRequest(c) {
|
|
2615
|
-
let body;
|
|
1804
|
+
async function parseEvalRunRequest(c) {
|
|
1805
|
+
let body = {};
|
|
2616
1806
|
try {
|
|
2617
1807
|
body = await c.req.json();
|
|
2618
1808
|
} catch {
|
|
2619
|
-
|
|
1809
|
+
body = {};
|
|
2620
1810
|
}
|
|
2621
1811
|
if (!isObject(body)) {
|
|
2622
1812
|
return { error: errorResponse(c, 400, "bad_request", "Request body must be an object") };
|
|
2623
1813
|
}
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
1814
|
+
const request = {};
|
|
1815
|
+
if ("concurrency" in body) {
|
|
1816
|
+
if (!isPositiveInteger(body.concurrency)) {
|
|
1817
|
+
return {
|
|
1818
|
+
error: errorResponse(c, 400, "bad_request", "concurrency must be a positive integer")
|
|
1819
|
+
};
|
|
1820
|
+
}
|
|
1821
|
+
request.concurrency = body.concurrency;
|
|
2629
1822
|
}
|
|
1823
|
+
return request;
|
|
1824
|
+
}
|
|
1825
|
+
|
|
1826
|
+
// src/runtime/knowledge.ts
|
|
1827
|
+
function registerKnowledgeRoutes(app, props) {
|
|
1828
|
+
app.get("/knowledge", async (c) => {
|
|
1829
|
+
const limit = parseLimit(c.req.query("limit"));
|
|
1830
|
+
if (limit === void 0) {
|
|
1831
|
+
return errorResponse(c, 400, "bad_request", "Invalid limit");
|
|
1832
|
+
}
|
|
1833
|
+
const summary = {
|
|
1834
|
+
agents: await Promise.all(props.agents.map(agentKnowledgeConfig)),
|
|
1835
|
+
evidence: await recentKnowledgeEvidence(props.traceStore, limit)
|
|
1836
|
+
};
|
|
1837
|
+
return c.json(summary);
|
|
1838
|
+
});
|
|
1839
|
+
app.get("/knowledge/items", async (c) => {
|
|
1840
|
+
const limit = parseLimit(c.req.query("limit"));
|
|
1841
|
+
if (limit === void 0) {
|
|
1842
|
+
return errorResponse(c, 400, "bad_request", "Invalid limit");
|
|
1843
|
+
}
|
|
1844
|
+
const agentId = optionalQueryString(c.req.query("agentId"));
|
|
1845
|
+
const sourceId = optionalQueryString(c.req.query("sourceId"));
|
|
1846
|
+
if (agentId === void 0 || sourceId === void 0) {
|
|
1847
|
+
return errorResponse(c, 400, "bad_request", "agentId and sourceId are required");
|
|
1848
|
+
}
|
|
1849
|
+
const agent = props.agents.find((item) => item.id === agentId);
|
|
1850
|
+
if (agent === void 0) {
|
|
1851
|
+
return errorResponse(c, 404, "not_found", "Agent not found");
|
|
1852
|
+
}
|
|
1853
|
+
const page = await knowledgeItemsPage(agent, sourceId, {
|
|
1854
|
+
limit,
|
|
1855
|
+
cursor: optionalQueryString(c.req.query("cursor"))
|
|
1856
|
+
});
|
|
1857
|
+
if (page === void 0) {
|
|
1858
|
+
return errorResponse(c, 404, "not_found", "Knowledge source not found");
|
|
1859
|
+
}
|
|
1860
|
+
return c.json(page);
|
|
1861
|
+
});
|
|
1862
|
+
}
|
|
1863
|
+
async function agentKnowledgeConfig(agent) {
|
|
1864
|
+
const agentName = agent.name ?? agent.agent.name;
|
|
2630
1865
|
return {
|
|
2631
|
-
|
|
2632
|
-
...
|
|
1866
|
+
agentId: agent.id,
|
|
1867
|
+
...agentName === void 0 ? {} : { agentName },
|
|
1868
|
+
sources: await knowledgeSources(agent),
|
|
1869
|
+
staticContext: agent.agent.staticContext.map((document) => ({
|
|
1870
|
+
id: document.id,
|
|
1871
|
+
text: document.text,
|
|
1872
|
+
...document.additionalProps === void 0 ? {} : { additionalProps: jsonObjectFromRecord(document.additionalProps) }
|
|
1873
|
+
}))
|
|
2633
1874
|
};
|
|
2634
1875
|
}
|
|
2635
|
-
function
|
|
2636
|
-
const
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
internalCallId,
|
|
2645
|
-
args,
|
|
2646
|
-
...request.reason === void 0 ? {} : { reason: request.reason },
|
|
2647
|
-
...request.rejectMessage === void 0 ? {} : { rejectMessage: request.rejectMessage }
|
|
2648
|
-
});
|
|
2649
|
-
return decision.approved ? control.run() : control.skip(decision.reason ?? request.rejectMessage ?? "Rejected in Anvia Studio.");
|
|
2650
|
-
};
|
|
2651
|
-
return {
|
|
2652
|
-
...createHook({
|
|
2653
|
-
async onToolCall({ toolName, toolCallId, internalCallId, args, tool: control }) {
|
|
2654
|
-
const registeredTool = context.getTool(toolName);
|
|
2655
|
-
if (registeredTool?.approval === void 0) {
|
|
2656
|
-
return control.run();
|
|
2657
|
-
}
|
|
2658
|
-
const approval = registeredTool.approval;
|
|
2659
|
-
const rawParsedArgs = parseToolArgs(args);
|
|
2660
|
-
const parsedArgs = registeredTool.parseApprovalArgs?.(rawParsedArgs) ?? rawParsedArgs;
|
|
2661
|
-
const approvalContext = {
|
|
2662
|
-
toolName,
|
|
2663
|
-
args: parsedArgs,
|
|
2664
|
-
rawArgs: args,
|
|
2665
|
-
...toolCallId === void 0 ? {} : { toolCallId },
|
|
2666
|
-
internalCallId,
|
|
2667
|
-
run: {
|
|
2668
|
-
agentId: context.agentId,
|
|
2669
|
-
runId: context.runId,
|
|
2670
|
-
...context.sessionId === void 0 ? {} : { sessionId: context.sessionId },
|
|
2671
|
-
...context.metadata === void 0 ? {} : { metadata: context.metadata }
|
|
2672
|
-
}
|
|
2673
|
-
};
|
|
2674
|
-
const required = await approval.when(approvalContext);
|
|
2675
|
-
if (!required) {
|
|
2676
|
-
return control.run();
|
|
2677
|
-
}
|
|
2678
|
-
const reason = await resolveApprovalText(approval.reason, approvalContext);
|
|
2679
|
-
const rejectMessage = await resolveApprovalText(
|
|
2680
|
-
approval.rejectMessage,
|
|
2681
|
-
approvalContext
|
|
2682
|
-
);
|
|
2683
|
-
const decision = await requestApproval(approvals, context, {
|
|
2684
|
-
toolName,
|
|
2685
|
-
...toolCallId === void 0 ? {} : { toolCallId },
|
|
2686
|
-
internalCallId,
|
|
2687
|
-
args,
|
|
2688
|
-
...reason === void 0 ? {} : { reason },
|
|
2689
|
-
...rejectMessage === void 0 ? {} : { rejectMessage }
|
|
2690
|
-
});
|
|
2691
|
-
return decision.approved ? control.run() : control.skip(decision.reason ?? rejectMessage ?? "Rejected in Anvia Studio.");
|
|
2692
|
-
}
|
|
2693
|
-
}),
|
|
2694
|
-
handleApprovalRequest
|
|
2695
|
-
};
|
|
2696
|
-
},
|
|
2697
|
-
list(options) {
|
|
2698
|
-
return [...approvals.values()].filter((approval) => {
|
|
2699
|
-
if (options.status === "pending" && approval.status !== "pending") {
|
|
2700
|
-
return false;
|
|
2701
|
-
}
|
|
2702
|
-
if (options.status === "resolved" && approval.status === "pending") {
|
|
2703
|
-
return false;
|
|
2704
|
-
}
|
|
2705
|
-
if (options.runId !== void 0 && approval.runId !== options.runId) {
|
|
2706
|
-
return false;
|
|
2707
|
-
}
|
|
2708
|
-
if (options.agentId !== void 0 && approval.agentId !== options.agentId) {
|
|
2709
|
-
return false;
|
|
2710
|
-
}
|
|
2711
|
-
if (options.sessionId !== void 0 && approval.sessionId !== options.sessionId) {
|
|
2712
|
-
return false;
|
|
2713
|
-
}
|
|
2714
|
-
return true;
|
|
2715
|
-
}).map(publicApproval);
|
|
2716
|
-
},
|
|
2717
|
-
decide(id, decision) {
|
|
2718
|
-
const approval = approvals.get(id);
|
|
2719
|
-
if (approval === void 0) {
|
|
2720
|
-
return "missing";
|
|
2721
|
-
}
|
|
2722
|
-
if (!isPendingApproval(approval)) {
|
|
2723
|
-
return "resolved";
|
|
2724
|
-
}
|
|
2725
|
-
const reason = decision.approved ? decision.reason : decision.reason ?? approval.rejectMessage ?? "Rejected in Anvia Studio.";
|
|
2726
|
-
const resolved = resolveApproval(approval, decision.approved ? "approved" : "rejected", {
|
|
2727
|
-
...reason === void 0 ? {} : { reason }
|
|
2728
|
-
});
|
|
2729
|
-
approvals.set(id, resolved);
|
|
2730
|
-
approval.emit?.({ type: "tool_approval_result", approval: resolved });
|
|
2731
|
-
approval.resolve({
|
|
2732
|
-
approved: decision.approved,
|
|
2733
|
-
...reason === void 0 ? {} : { reason }
|
|
2734
|
-
});
|
|
2735
|
-
return publicApproval(resolved);
|
|
2736
|
-
}
|
|
2737
|
-
};
|
|
2738
|
-
}
|
|
2739
|
-
async function requestApproval(approvals, context, request) {
|
|
2740
|
-
const id = globalThis.crypto.randomUUID();
|
|
2741
|
-
const approval = {
|
|
2742
|
-
id,
|
|
2743
|
-
runId: context.runId,
|
|
2744
|
-
agentId: context.agentId,
|
|
2745
|
-
...context.sessionId === void 0 ? {} : { sessionId: context.sessionId },
|
|
2746
|
-
toolName: request.toolName,
|
|
2747
|
-
...request.toolCallId === void 0 ? {} : { callId: request.toolCallId },
|
|
2748
|
-
internalCallId: request.internalCallId,
|
|
2749
|
-
args: request.args,
|
|
2750
|
-
status: "pending",
|
|
2751
|
-
requestedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2752
|
-
...request.reason === void 0 ? {} : { reason: request.reason },
|
|
2753
|
-
...request.rejectMessage === void 0 ? {} : { rejectMessage: request.rejectMessage },
|
|
2754
|
-
...context.emit === void 0 ? {} : { emit: context.emit },
|
|
2755
|
-
resolve: () => {
|
|
1876
|
+
async function knowledgeSources(agent) {
|
|
1877
|
+
const sources = [
|
|
1878
|
+
{
|
|
1879
|
+
sourceId: staticSourceId(),
|
|
1880
|
+
kind: "static_context",
|
|
1881
|
+
label: "Static context",
|
|
1882
|
+
count: agent.agent.staticContext.length,
|
|
1883
|
+
inspectable: true,
|
|
1884
|
+
itemCount: agent.agent.staticContext.length
|
|
2756
1885
|
}
|
|
2757
|
-
|
|
2758
|
-
const
|
|
2759
|
-
|
|
2760
|
-
const
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
});
|
|
2774
|
-
approvals.set(id, resolved);
|
|
2775
|
-
context.emit?.({ type: "tool_approval_result", approval: resolved });
|
|
2776
|
-
resolve2({
|
|
2777
|
-
approved: decision2.approved,
|
|
2778
|
-
...reason === void 0 ? {} : { reason }
|
|
2779
|
-
});
|
|
2780
|
-
};
|
|
2781
|
-
});
|
|
2782
|
-
approvals.set(id, approval);
|
|
2783
|
-
context.emit?.({ type: "tool_approval_request", approval: publicApproval(approval) });
|
|
2784
|
-
return decision;
|
|
2785
|
-
}
|
|
2786
|
-
async function resolveApprovalText(value, context) {
|
|
2787
|
-
return typeof value === "function" ? value(context) : value;
|
|
2788
|
-
}
|
|
2789
|
-
function isPendingApproval(approval) {
|
|
2790
|
-
return approval !== void 0 && approval.status === "pending" && "resolve" in approval;
|
|
2791
|
-
}
|
|
2792
|
-
function resolveApproval(approval, status, options = {}) {
|
|
2793
|
-
return publicApproval({
|
|
2794
|
-
...approval,
|
|
2795
|
-
status,
|
|
2796
|
-
resolvedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2797
|
-
...options.reason === void 0 ? {} : { reason: options.reason }
|
|
2798
|
-
});
|
|
2799
|
-
}
|
|
2800
|
-
function publicApproval(approval) {
|
|
2801
|
-
const { emit, rejectMessage, resolve: resolve2, ...rest } = approval;
|
|
2802
|
-
void emit;
|
|
2803
|
-
void rejectMessage;
|
|
2804
|
-
void resolve2;
|
|
2805
|
-
return rest;
|
|
2806
|
-
}
|
|
2807
|
-
|
|
2808
|
-
// src/runtime/evals.ts
|
|
2809
|
-
import { runEvalSuite } from "@anvia/core/evals";
|
|
2810
|
-
function registerEvalRoutes(app, props) {
|
|
2811
|
-
app.get(
|
|
2812
|
-
"/evals",
|
|
2813
|
-
(c) => c.json({
|
|
2814
|
-
evals: props.evals.map(evalConfig)
|
|
1886
|
+
];
|
|
1887
|
+
const dynamicContextSources = await Promise.all(
|
|
1888
|
+
agent.agent.dynamicContexts.map(async (registration, index) => {
|
|
1889
|
+
const inspect = inspectFn(registration.index);
|
|
1890
|
+
const count = await inspectableCount(inspect, registration.options.filter);
|
|
1891
|
+
return {
|
|
1892
|
+
sourceId: dynamicContextSourceId(index),
|
|
1893
|
+
kind: "dynamic_context",
|
|
1894
|
+
label: `Dynamic context ${index + 1}`,
|
|
1895
|
+
count: 1,
|
|
1896
|
+
registrationIndex: index,
|
|
1897
|
+
topK: registration.options.topK,
|
|
1898
|
+
...registration.options.threshold === void 0 ? {} : { threshold: registration.options.threshold },
|
|
1899
|
+
inspectable: inspect !== void 0,
|
|
1900
|
+
...count === void 0 ? {} : { itemCount: count }
|
|
1901
|
+
};
|
|
2815
1902
|
})
|
|
2816
1903
|
);
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
}
|
|
2822
|
-
return c.json(evalConfig(suite));
|
|
2823
|
-
});
|
|
2824
|
-
app.post("/evals/:evalId/runs", async (c) => {
|
|
2825
|
-
const suite = props.evalMap.get(c.req.param("evalId"));
|
|
2826
|
-
if (suite === void 0) {
|
|
2827
|
-
return errorResponse(c, 404, "not_found", "Eval suite not found");
|
|
2828
|
-
}
|
|
2829
|
-
const body = await parseEvalRunRequest(c);
|
|
2830
|
-
if ("error" in body) {
|
|
2831
|
-
return body.error;
|
|
2832
|
-
}
|
|
2833
|
-
const runId = globalThis.crypto.randomUUID();
|
|
2834
|
-
const startedAt = Date.now();
|
|
2835
|
-
const result = await runEvalSuite({
|
|
2836
|
-
...suite,
|
|
2837
|
-
...body.concurrency === void 0 ? {} : { concurrency: body.concurrency }
|
|
2838
|
-
});
|
|
2839
|
-
const endedAt = Date.now();
|
|
2840
|
-
const jsonResult = toJsonValue(result);
|
|
2841
|
-
const response = {
|
|
2842
|
-
runId,
|
|
2843
|
-
suiteId: suite.id ?? suite.name,
|
|
2844
|
-
startedAt: new Date(startedAt).toISOString(),
|
|
2845
|
-
endedAt: new Date(endedAt).toISOString(),
|
|
2846
|
-
durationMs: endedAt - startedAt,
|
|
2847
|
-
result: isJsonObject2(jsonResult) ? jsonResult : { value: jsonResult }
|
|
2848
|
-
};
|
|
2849
|
-
return c.json(response);
|
|
2850
|
-
});
|
|
2851
|
-
}
|
|
2852
|
-
async function parseEvalRunRequest(c) {
|
|
2853
|
-
let body = {};
|
|
2854
|
-
try {
|
|
2855
|
-
body = await c.req.json();
|
|
2856
|
-
} catch {
|
|
2857
|
-
body = {};
|
|
2858
|
-
}
|
|
2859
|
-
if (!isObject(body)) {
|
|
2860
|
-
return { error: errorResponse(c, 400, "bad_request", "Request body must be an object") };
|
|
2861
|
-
}
|
|
2862
|
-
const request = {};
|
|
2863
|
-
if ("concurrency" in body) {
|
|
2864
|
-
if (!isPositiveInteger(body.concurrency)) {
|
|
1904
|
+
const dynamicToolSources = await Promise.all(
|
|
1905
|
+
agent.agent.dynamicTools.map(async (registration, index) => {
|
|
1906
|
+
const inspect = inspectFn(registration.index);
|
|
1907
|
+
const count = await inspectableCount(inspect, registration.options.filter);
|
|
2865
1908
|
return {
|
|
2866
|
-
|
|
1909
|
+
sourceId: dynamicToolsSourceId(index),
|
|
1910
|
+
kind: "dynamic_tools",
|
|
1911
|
+
label: `Dynamic tools ${index + 1}`,
|
|
1912
|
+
count: 1,
|
|
1913
|
+
registrationIndex: index,
|
|
1914
|
+
topK: registration.options.topK,
|
|
1915
|
+
...registration.options.threshold === void 0 ? {} : { threshold: registration.options.threshold },
|
|
1916
|
+
inspectable: inspect !== void 0,
|
|
1917
|
+
...count === void 0 ? {} : { itemCount: count }
|
|
2867
1918
|
};
|
|
2868
|
-
}
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
return request;
|
|
2872
|
-
}
|
|
2873
|
-
|
|
2874
|
-
// src/runtime/knowledge.ts
|
|
2875
|
-
function registerKnowledgeRoutes(app, props) {
|
|
2876
|
-
app.get("/knowledge", async (c) => {
|
|
2877
|
-
const limit = parseLimit(c.req.query("limit"));
|
|
2878
|
-
if (limit === void 0) {
|
|
2879
|
-
return errorResponse(c, 400, "bad_request", "Invalid limit");
|
|
2880
|
-
}
|
|
2881
|
-
const summary = {
|
|
2882
|
-
agents: await Promise.all(props.agents.map(agentKnowledgeConfig)),
|
|
2883
|
-
evidence: await recentKnowledgeEvidence(props.traceStore, limit)
|
|
2884
|
-
};
|
|
2885
|
-
return c.json(summary);
|
|
2886
|
-
});
|
|
2887
|
-
app.get("/knowledge/items", async (c) => {
|
|
2888
|
-
const limit = parseLimit(c.req.query("limit"));
|
|
2889
|
-
if (limit === void 0) {
|
|
2890
|
-
return errorResponse(c, 400, "bad_request", "Invalid limit");
|
|
2891
|
-
}
|
|
2892
|
-
const agentId = optionalQueryString(c.req.query("agentId"));
|
|
2893
|
-
const sourceId = optionalQueryString(c.req.query("sourceId"));
|
|
2894
|
-
if (agentId === void 0 || sourceId === void 0) {
|
|
2895
|
-
return errorResponse(c, 400, "bad_request", "agentId and sourceId are required");
|
|
2896
|
-
}
|
|
2897
|
-
const agent = props.agents.find((item) => item.id === agentId);
|
|
2898
|
-
if (agent === void 0) {
|
|
2899
|
-
return errorResponse(c, 404, "not_found", "Agent not found");
|
|
2900
|
-
}
|
|
2901
|
-
const page = await knowledgeItemsPage(agent, sourceId, {
|
|
2902
|
-
limit,
|
|
2903
|
-
cursor: optionalQueryString(c.req.query("cursor"))
|
|
2904
|
-
});
|
|
2905
|
-
if (page === void 0) {
|
|
2906
|
-
return errorResponse(c, 404, "not_found", "Knowledge source not found");
|
|
2907
|
-
}
|
|
2908
|
-
return c.json(page);
|
|
2909
|
-
});
|
|
2910
|
-
}
|
|
2911
|
-
async function agentKnowledgeConfig(agent) {
|
|
2912
|
-
const agentName = agent.name ?? agent.agent.name;
|
|
2913
|
-
return {
|
|
2914
|
-
agentId: agent.id,
|
|
2915
|
-
...agentName === void 0 ? {} : { agentName },
|
|
2916
|
-
sources: await knowledgeSources(agent),
|
|
2917
|
-
staticContext: agent.agent.staticContext.map((document) => ({
|
|
2918
|
-
id: document.id,
|
|
2919
|
-
text: document.text,
|
|
2920
|
-
...document.additionalProps === void 0 ? {} : { additionalProps: jsonObjectFromRecord(document.additionalProps) }
|
|
2921
|
-
}))
|
|
2922
|
-
};
|
|
2923
|
-
}
|
|
2924
|
-
async function knowledgeSources(agent) {
|
|
2925
|
-
const sources = [
|
|
2926
|
-
{
|
|
2927
|
-
sourceId: staticSourceId(),
|
|
2928
|
-
kind: "static_context",
|
|
2929
|
-
label: "Static context",
|
|
2930
|
-
count: agent.agent.staticContext.length,
|
|
2931
|
-
inspectable: true,
|
|
2932
|
-
itemCount: agent.agent.staticContext.length
|
|
2933
|
-
}
|
|
2934
|
-
];
|
|
2935
|
-
const dynamicContextSources = await Promise.all(
|
|
2936
|
-
agent.agent.dynamicContexts.map(async (registration, index) => {
|
|
2937
|
-
const inspect = inspectFn(registration.index);
|
|
2938
|
-
const count = await inspectableCount(inspect, registration.options.filter);
|
|
2939
|
-
return {
|
|
2940
|
-
sourceId: dynamicContextSourceId(index),
|
|
2941
|
-
kind: "dynamic_context",
|
|
2942
|
-
label: `Dynamic context ${index + 1}`,
|
|
2943
|
-
count: 1,
|
|
2944
|
-
registrationIndex: index,
|
|
2945
|
-
topK: registration.options.topK,
|
|
2946
|
-
...registration.options.threshold === void 0 ? {} : { threshold: registration.options.threshold },
|
|
2947
|
-
inspectable: inspect !== void 0,
|
|
2948
|
-
...count === void 0 ? {} : { itemCount: count }
|
|
2949
|
-
};
|
|
2950
|
-
})
|
|
2951
|
-
);
|
|
2952
|
-
const dynamicToolSources = await Promise.all(
|
|
2953
|
-
agent.agent.dynamicTools.map(async (registration, index) => {
|
|
2954
|
-
const inspect = inspectFn(registration.index);
|
|
2955
|
-
const count = await inspectableCount(inspect, registration.options.filter);
|
|
2956
|
-
return {
|
|
2957
|
-
sourceId: dynamicToolsSourceId(index),
|
|
2958
|
-
kind: "dynamic_tools",
|
|
2959
|
-
label: `Dynamic tools ${index + 1}`,
|
|
2960
|
-
count: 1,
|
|
2961
|
-
registrationIndex: index,
|
|
2962
|
-
topK: registration.options.topK,
|
|
2963
|
-
...registration.options.threshold === void 0 ? {} : { threshold: registration.options.threshold },
|
|
2964
|
-
inspectable: inspect !== void 0,
|
|
2965
|
-
...count === void 0 ? {} : { itemCount: count }
|
|
2966
|
-
};
|
|
2967
|
-
})
|
|
2968
|
-
);
|
|
2969
|
-
return [...sources, ...dynamicContextSources, ...dynamicToolSources];
|
|
1919
|
+
})
|
|
1920
|
+
);
|
|
1921
|
+
return [...sources, ...dynamicContextSources, ...dynamicToolSources];
|
|
2970
1922
|
}
|
|
2971
1923
|
async function inspectableCount(inspect, filter) {
|
|
2972
1924
|
if (inspect === void 0) {
|
|
@@ -3884,6 +2836,15 @@ async function* persistStreamingSessionTranscript(props) {
|
|
|
3884
2836
|
if (nextSession === void 0) {
|
|
3885
2837
|
throw new Error("Session not found");
|
|
3886
2838
|
}
|
|
2839
|
+
const generatedMessages = event.type === "final" ? event.messages.slice(1) : [];
|
|
2840
|
+
if (props.persistGeneratedMessages === true && generatedMessages.length > 0) {
|
|
2841
|
+
await props.store.append({
|
|
2842
|
+
context: { sessionId: props.session.id },
|
|
2843
|
+
runId: props.runId,
|
|
2844
|
+
turn: 1,
|
|
2845
|
+
messages: generatedMessages
|
|
2846
|
+
});
|
|
2847
|
+
}
|
|
3887
2848
|
yield event;
|
|
3888
2849
|
}
|
|
3889
2850
|
} catch (error) {
|
|
@@ -5918,7 +4879,9 @@ function agentMetadata(agent) {
|
|
|
5918
4879
|
function createStudioApp(options) {
|
|
5919
4880
|
const observabilityHub = new StudioObservabilityHub();
|
|
5920
4881
|
const stores = observeStores(resolveStores(options), observabilityHub);
|
|
5921
|
-
const agents = normalizeAgents(options.agents).map(
|
|
4882
|
+
const agents = normalizeAgents(options.agents).map(
|
|
4883
|
+
(agent) => withStudioTraceObserver(agent, stores.traces)
|
|
4884
|
+
);
|
|
5922
4885
|
const pipelines = normalizePipelines(options.pipelines);
|
|
5923
4886
|
const agentMap = new Map(agents.map((agent) => [agent.id, agent]));
|
|
5924
4887
|
const pipelineMap = new Map(pipelines.map((pipeline) => [pipeline.id, pipeline]));
|
|
@@ -6000,288 +4963,1343 @@ function createStudioApp(options) {
|
|
|
6000
4963
|
if (session !== void 0 && session.agentId !== agentId) {
|
|
6001
4964
|
return errorResponse(c, 400, "bad_request", "Session belongs to another agent");
|
|
6002
4965
|
}
|
|
6003
|
-
const runId = globalThis.crypto.randomUUID();
|
|
6004
|
-
const runStartedAt = Date.now();
|
|
6005
|
-
if (session !== void 0) {
|
|
6006
|
-
await appendSessionLog(
|
|
6007
|
-
stores.sessions,
|
|
6008
|
-
runReceivedLog({
|
|
6009
|
-
sessionId: session.id,
|
|
6010
|
-
runId,
|
|
6011
|
-
agentId,
|
|
6012
|
-
message: body.message,
|
|
6013
|
-
stream: body.stream === true,
|
|
6014
|
-
...body.maxTurns === void 0 ? {} : { maxTurns: body.maxTurns },
|
|
6015
|
-
...body.toolConcurrency === void 0 ? {} : { toolConcurrency: body.toolConcurrency },
|
|
6016
|
-
hasTrace: body.trace !== void 0,
|
|
6017
|
-
...body.metadata === void 0 ? {} : { metadata: body.metadata }
|
|
6018
|
-
})
|
|
6019
|
-
);
|
|
4966
|
+
const runId = globalThis.crypto.randomUUID();
|
|
4967
|
+
const runStartedAt = Date.now();
|
|
4968
|
+
if (session !== void 0) {
|
|
4969
|
+
await appendSessionLog(
|
|
4970
|
+
stores.sessions,
|
|
4971
|
+
runReceivedLog({
|
|
4972
|
+
sessionId: session.id,
|
|
4973
|
+
runId,
|
|
4974
|
+
agentId,
|
|
4975
|
+
message: body.message,
|
|
4976
|
+
stream: body.stream === true,
|
|
4977
|
+
...body.maxTurns === void 0 ? {} : { maxTurns: body.maxTurns },
|
|
4978
|
+
...body.toolConcurrency === void 0 ? {} : { toolConcurrency: body.toolConcurrency },
|
|
4979
|
+
hasTrace: body.trace !== void 0,
|
|
4980
|
+
...body.metadata === void 0 ? {} : { metadata: body.metadata }
|
|
4981
|
+
})
|
|
4982
|
+
);
|
|
4983
|
+
}
|
|
4984
|
+
const memoryMetadata = {
|
|
4985
|
+
agentId,
|
|
4986
|
+
...body.metadata ?? {},
|
|
4987
|
+
studioRunId: runId
|
|
4988
|
+
};
|
|
4989
|
+
const promptMessage = normalizePromptMessage(body.message);
|
|
4990
|
+
const sessionStore = stores.sessions;
|
|
4991
|
+
const shouldPersistSessionMessages = session !== void 0 && sessionStore !== void 0 && !usesStoreAsAgentMemory(agent.agent, sessionStore);
|
|
4992
|
+
if (shouldPersistSessionMessages) {
|
|
4993
|
+
await sessionStore.append({
|
|
4994
|
+
context: { sessionId: session.id, metadata: memoryMetadata },
|
|
4995
|
+
runId,
|
|
4996
|
+
turn: 1,
|
|
4997
|
+
messages: [promptMessage]
|
|
4998
|
+
});
|
|
4999
|
+
}
|
|
5000
|
+
const request = session !== void 0 ? agent.agent.memory === void 0 ? agent.agent.prompt([...session.messages, promptMessage]) : agent.agent.session(session.id, { metadata: memoryMetadata }).prompt(body.message) : agent.agent.prompt(
|
|
5001
|
+
body.history !== void 0 ? [...body.history, promptMessage] : body.message
|
|
5002
|
+
);
|
|
5003
|
+
if (body.maxTurns !== void 0) {
|
|
5004
|
+
request.maxTurns(body.maxTurns);
|
|
5005
|
+
}
|
|
5006
|
+
if (body.toolConcurrency !== void 0) {
|
|
5007
|
+
request.withToolConcurrency(body.toolConcurrency);
|
|
5008
|
+
}
|
|
5009
|
+
if (body.trace !== void 0) {
|
|
5010
|
+
request.withTrace(traceForRun(body.trace, agentId, session));
|
|
5011
|
+
} else if (session !== void 0) {
|
|
5012
|
+
request.withTrace(traceForRun(void 0, agentId, session));
|
|
5013
|
+
}
|
|
5014
|
+
if (body.stream === true) {
|
|
5015
|
+
const runtimeEvents = new AsyncEventQueue();
|
|
5016
|
+
const effectiveHook = composeHooks(
|
|
5017
|
+
composeHooks(
|
|
5018
|
+
agent.agent.hook,
|
|
5019
|
+
approvalRuntime.createHook({
|
|
5020
|
+
runId,
|
|
5021
|
+
agentId,
|
|
5022
|
+
...session?.id === void 0 ? {} : { sessionId: session.id },
|
|
5023
|
+
...body.metadata === void 0 ? {} : { metadata: body.metadata },
|
|
5024
|
+
getTool: (toolName) => agent.agent.getTool(toolName),
|
|
5025
|
+
emit: (event) => runtimeEvents.push(event)
|
|
5026
|
+
})
|
|
5027
|
+
),
|
|
5028
|
+
questionRuntime.createHook({
|
|
5029
|
+
runId,
|
|
5030
|
+
agentId,
|
|
5031
|
+
...session?.id === void 0 ? {} : { sessionId: session.id },
|
|
5032
|
+
...body.metadata === void 0 ? {} : { metadata: body.metadata },
|
|
5033
|
+
emit: (event) => runtimeEvents.push(event)
|
|
5034
|
+
})
|
|
5035
|
+
);
|
|
5036
|
+
if (effectiveHook !== void 0) {
|
|
5037
|
+
request.requestHook(effectiveHook);
|
|
5038
|
+
}
|
|
5039
|
+
const runStream = mergeRunAndApprovalEvents(request.stream(), runtimeEvents);
|
|
5040
|
+
const stream = session === void 0 || sessionStore === void 0 ? runStream : persistStreamingSessionTranscript({
|
|
5041
|
+
stream: streamSessionRunLogs({
|
|
5042
|
+
stream: runStream,
|
|
5043
|
+
store: sessionStore,
|
|
5044
|
+
session,
|
|
5045
|
+
runId,
|
|
5046
|
+
startedAt: runStartedAt
|
|
5047
|
+
}),
|
|
5048
|
+
store: sessionStore,
|
|
5049
|
+
session,
|
|
5050
|
+
message: body.message,
|
|
5051
|
+
runId,
|
|
5052
|
+
persistGeneratedMessages: shouldPersistSessionMessages
|
|
5053
|
+
});
|
|
5054
|
+
return streamAgentRunEvents(c, stream);
|
|
5055
|
+
}
|
|
5056
|
+
try {
|
|
5057
|
+
if (session !== void 0) {
|
|
5058
|
+
await appendSessionLog(sessionStore, runStartedLog(session, runId));
|
|
5059
|
+
await appendSessionLog(sessionStore, memoryLoadedLog(session, runId));
|
|
5060
|
+
}
|
|
5061
|
+
const effectiveHook = composeHooks(
|
|
5062
|
+
composeHooks(
|
|
5063
|
+
agent.agent.hook,
|
|
5064
|
+
approvalRuntime.createHook({
|
|
5065
|
+
runId,
|
|
5066
|
+
agentId,
|
|
5067
|
+
...session?.id === void 0 ? {} : { sessionId: session.id },
|
|
5068
|
+
...body.metadata === void 0 ? {} : { metadata: body.metadata },
|
|
5069
|
+
getTool: (toolName) => agent.agent.getTool(toolName)
|
|
5070
|
+
})
|
|
5071
|
+
),
|
|
5072
|
+
questionRuntime.createHook({
|
|
5073
|
+
runId,
|
|
5074
|
+
agentId,
|
|
5075
|
+
...session?.id === void 0 ? {} : { sessionId: session.id },
|
|
5076
|
+
...body.metadata === void 0 ? {} : { metadata: body.metadata }
|
|
5077
|
+
})
|
|
5078
|
+
);
|
|
5079
|
+
if (effectiveHook !== void 0) {
|
|
5080
|
+
request.requestHook(effectiveHook);
|
|
5081
|
+
}
|
|
5082
|
+
const response = await request.send();
|
|
5083
|
+
if (session !== void 0 && sessionStore !== void 0) {
|
|
5084
|
+
if (shouldPersistSessionMessages) {
|
|
5085
|
+
const generatedMessages = response.messages.slice(1);
|
|
5086
|
+
if (generatedMessages.length > 0) {
|
|
5087
|
+
await sessionStore.append({
|
|
5088
|
+
context: { sessionId: session.id, metadata: memoryMetadata },
|
|
5089
|
+
runId,
|
|
5090
|
+
turn: 1,
|
|
5091
|
+
messages: generatedMessages
|
|
5092
|
+
});
|
|
5093
|
+
}
|
|
5094
|
+
}
|
|
5095
|
+
await sessionStore.saveSessionRunTranscript({
|
|
5096
|
+
id: session.id,
|
|
5097
|
+
runId,
|
|
5098
|
+
...optionalTitle(body.message),
|
|
5099
|
+
transcript: transcriptFromMessages(response.messages),
|
|
5100
|
+
status: "success"
|
|
5101
|
+
});
|
|
5102
|
+
await appendSessionLog(
|
|
5103
|
+
sessionStore,
|
|
5104
|
+
runCompletedLog({
|
|
5105
|
+
sessionId: session.id,
|
|
5106
|
+
runId,
|
|
5107
|
+
durationMs: Date.now() - runStartedAt,
|
|
5108
|
+
usage: response.usage,
|
|
5109
|
+
output: response.output,
|
|
5110
|
+
messageCount: response.messages.length
|
|
5111
|
+
})
|
|
5112
|
+
);
|
|
5113
|
+
await appendSessionLog(
|
|
5114
|
+
sessionStore,
|
|
5115
|
+
memorySavedLog({
|
|
5116
|
+
sessionId: session.id,
|
|
5117
|
+
runId,
|
|
5118
|
+
messageCount: response.messages.length
|
|
5119
|
+
})
|
|
5120
|
+
);
|
|
5121
|
+
}
|
|
5122
|
+
return c.json(response);
|
|
5123
|
+
} catch (error) {
|
|
5124
|
+
if (session !== void 0 && sessionStore !== void 0) {
|
|
5125
|
+
const messages = await sessionStore.load({
|
|
5126
|
+
sessionId: session.id,
|
|
5127
|
+
metadata: memoryMetadata
|
|
5128
|
+
});
|
|
5129
|
+
await sessionStore.saveSessionRunTranscript({
|
|
5130
|
+
id: session.id,
|
|
5131
|
+
runId,
|
|
5132
|
+
...optionalTitle(body.message),
|
|
5133
|
+
transcript: transcriptFromMessages(messages.slice(session.messageCount)),
|
|
5134
|
+
status: "error",
|
|
5135
|
+
error: serializeError(error)
|
|
5136
|
+
});
|
|
5137
|
+
await appendSessionLog(sessionStore, runFailedLog(session.id, runId, error, runStartedAt));
|
|
5138
|
+
}
|
|
5139
|
+
return errorResponse(c, 500, "internal_error", "Agent run failed", serializeError(error));
|
|
5140
|
+
}
|
|
5141
|
+
});
|
|
5142
|
+
if (stores.sessions !== void 0) {
|
|
5143
|
+
registerMemoryRoutes(app, {
|
|
5144
|
+
sessionStore: stores.sessions
|
|
5145
|
+
});
|
|
5146
|
+
registerSessionRoutes(app, {
|
|
5147
|
+
agentMap,
|
|
5148
|
+
sessionStore: stores.sessions,
|
|
5149
|
+
...stores.traces === void 0 ? {} : { traceStore: stores.traces }
|
|
5150
|
+
});
|
|
5151
|
+
}
|
|
5152
|
+
if (stores.traces !== void 0) {
|
|
5153
|
+
registerTraceRoutes(app, stores.traces);
|
|
5154
|
+
}
|
|
5155
|
+
for (const capability of unsupportedCapabilities(stores)) {
|
|
5156
|
+
app.all(`/${capability}`, (c) => unsupportedCapability(c, capability));
|
|
5157
|
+
app.all(`/${capability}/*`, (c) => unsupportedCapability(c, capability));
|
|
5158
|
+
}
|
|
5159
|
+
return {
|
|
5160
|
+
app,
|
|
5161
|
+
fetch(request) {
|
|
5162
|
+
return app.fetch(request);
|
|
5163
|
+
},
|
|
5164
|
+
config() {
|
|
5165
|
+
return buildConfig(options, agents, pipelines, stores);
|
|
5166
|
+
},
|
|
5167
|
+
close() {
|
|
5168
|
+
},
|
|
5169
|
+
...stores.sessions === void 0 ? {} : { sessionStore: stores.sessions },
|
|
5170
|
+
...stores.traces === void 0 ? {} : { traceStore: stores.traces }
|
|
5171
|
+
};
|
|
5172
|
+
}
|
|
5173
|
+
function normalizePromptMessage(message) {
|
|
5174
|
+
return typeof message === "string" ? Message.user(message) : message;
|
|
5175
|
+
}
|
|
5176
|
+
function usesStoreAsAgentMemory(agent, store) {
|
|
5177
|
+
return agent.memory?.store === store;
|
|
5178
|
+
}
|
|
5179
|
+
function withStudioTraceObserver(studioAgent, traceStore) {
|
|
5180
|
+
if (traceStore === void 0 || hasStudioTraceObserver(studioAgent.agent)) {
|
|
5181
|
+
return studioAgent;
|
|
5182
|
+
}
|
|
5183
|
+
return {
|
|
5184
|
+
...studioAgent,
|
|
5185
|
+
agent: cloneAgent(studioAgent.agent, {
|
|
5186
|
+
observers: [
|
|
5187
|
+
...studioAgent.agent.observers,
|
|
5188
|
+
{ observer: new StudioTraceObserver({ store: traceStore }) }
|
|
5189
|
+
]
|
|
5190
|
+
})
|
|
5191
|
+
};
|
|
5192
|
+
}
|
|
5193
|
+
function cloneAgent(agent, overrides = {}) {
|
|
5194
|
+
return new Agent({
|
|
5195
|
+
id: agent.id,
|
|
5196
|
+
name: agent.name,
|
|
5197
|
+
description: agent.description,
|
|
5198
|
+
model: agent.model,
|
|
5199
|
+
instructions: agent.instructions,
|
|
5200
|
+
staticContext: agent.staticContext,
|
|
5201
|
+
temperature: agent.temperature,
|
|
5202
|
+
maxTokens: agent.maxTokens,
|
|
5203
|
+
additionalParams: agent.additionalParams,
|
|
5204
|
+
toolSet: agent.toolSet,
|
|
5205
|
+
toolChoice: agent.toolChoice,
|
|
5206
|
+
defaultMaxTurns: agent.defaultMaxTurns,
|
|
5207
|
+
hook: agent.hook,
|
|
5208
|
+
outputSchema: agent.outputSchema,
|
|
5209
|
+
observers: agent.observers,
|
|
5210
|
+
dynamicContexts: agent.dynamicContexts,
|
|
5211
|
+
dynamicTools: agent.dynamicTools,
|
|
5212
|
+
memory: agent.memory,
|
|
5213
|
+
...overrides
|
|
5214
|
+
});
|
|
5215
|
+
}
|
|
5216
|
+
function hasStudioTraceObserver(agent) {
|
|
5217
|
+
return agent.observers.some(
|
|
5218
|
+
(registration) => registration.observer instanceof StudioTraceObserver
|
|
5219
|
+
);
|
|
5220
|
+
}
|
|
5221
|
+
function composeHooks(first, second) {
|
|
5222
|
+
if (first === void 0) {
|
|
5223
|
+
return second;
|
|
5224
|
+
}
|
|
5225
|
+
if (second === void 0) {
|
|
5226
|
+
return first;
|
|
5227
|
+
}
|
|
5228
|
+
return createHook3({
|
|
5229
|
+
async onCompletionCall(args) {
|
|
5230
|
+
const firstAction = await first.onCompletionCall?.(args);
|
|
5231
|
+
return firstAction?.type === "terminate" ? firstAction : await second.onCompletionCall?.(args) ?? void 0;
|
|
5232
|
+
},
|
|
5233
|
+
async onCompletionResponse(args) {
|
|
5234
|
+
const firstAction = await first.onCompletionResponse?.(args);
|
|
5235
|
+
return firstAction?.type === "terminate" ? firstAction : await second.onCompletionResponse?.(args) ?? void 0;
|
|
5236
|
+
},
|
|
5237
|
+
async onToolCall(args) {
|
|
5238
|
+
const firstAction = await first.onToolCall?.(args);
|
|
5239
|
+
if (firstAction?.type === "skip" || firstAction?.type === "terminate") {
|
|
5240
|
+
return firstAction;
|
|
5241
|
+
}
|
|
5242
|
+
if (firstAction?.type === "approval_request") {
|
|
5243
|
+
return await approvalRequestHandler(second)?.(args, firstAction) ?? firstAction;
|
|
5244
|
+
}
|
|
5245
|
+
const secondAction = await second.onToolCall?.(args);
|
|
5246
|
+
return secondAction ?? firstAction ?? void 0;
|
|
5247
|
+
},
|
|
5248
|
+
async onToolResult(args) {
|
|
5249
|
+
const firstAction = await first.onToolResult?.(args);
|
|
5250
|
+
return firstAction?.type === "terminate" ? firstAction : await second.onToolResult?.(args) ?? void 0;
|
|
5251
|
+
}
|
|
5252
|
+
});
|
|
5253
|
+
}
|
|
5254
|
+
function approvalRequestHandler(hook) {
|
|
5255
|
+
const candidate = hook;
|
|
5256
|
+
return typeof candidate.handleApprovalRequest === "function" ? candidate.handleApprovalRequest : void 0;
|
|
5257
|
+
}
|
|
5258
|
+
|
|
5259
|
+
// src/storage/sqlite-store.ts
|
|
5260
|
+
import { mkdirSync } from "fs";
|
|
5261
|
+
import { createRequire } from "module";
|
|
5262
|
+
import { dirname, resolve } from "path";
|
|
5263
|
+
var DatabaseSync;
|
|
5264
|
+
function createSqliteSessionStore(options = {}) {
|
|
5265
|
+
return new SqliteSessionStore(options.path ?? ":memory:");
|
|
5266
|
+
}
|
|
5267
|
+
var SqliteSessionStore = class {
|
|
5268
|
+
constructor(path) {
|
|
5269
|
+
this.path = path;
|
|
5270
|
+
}
|
|
5271
|
+
path;
|
|
5272
|
+
kind = "sqlite";
|
|
5273
|
+
db;
|
|
5274
|
+
listSessions(options) {
|
|
5275
|
+
const db = this.database();
|
|
5276
|
+
const agentClause = options.agentId === void 0 ? "" : "WHERE s.agent_id = $agentId";
|
|
5277
|
+
const rows = db.prepare(
|
|
5278
|
+
`SELECT s.id, s.agent_id, s.title, s.metadata_json, s.created_at, s.updated_at,
|
|
5279
|
+
COUNT(m.message_index) AS message_count
|
|
5280
|
+
FROM anvia_studio_sessions s
|
|
5281
|
+
LEFT JOIN anvia_studio_session_messages m ON m.session_id = s.id
|
|
5282
|
+
${agentClause}
|
|
5283
|
+
GROUP BY s.id, s.agent_id, s.title, s.metadata_json, s.created_at, s.updated_at
|
|
5284
|
+
ORDER BY s.updated_at DESC
|
|
5285
|
+
LIMIT $limit`
|
|
5286
|
+
).all({
|
|
5287
|
+
$agentId: options.agentId ?? null,
|
|
5288
|
+
$limit: options.limit
|
|
5289
|
+
});
|
|
5290
|
+
return rows.map(toSessionSummary);
|
|
5291
|
+
}
|
|
5292
|
+
createSession(input) {
|
|
5293
|
+
const db = this.database();
|
|
5294
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
5295
|
+
db.prepare(
|
|
5296
|
+
`INSERT INTO anvia_studio_sessions (
|
|
5297
|
+
id,
|
|
5298
|
+
agent_id,
|
|
5299
|
+
title,
|
|
5300
|
+
metadata_json,
|
|
5301
|
+
created_at,
|
|
5302
|
+
updated_at
|
|
5303
|
+
) VALUES ($id, $agentId, $title, $metadata, $now, $now)`
|
|
5304
|
+
).run({
|
|
5305
|
+
$id: input.id,
|
|
5306
|
+
$agentId: input.agentId,
|
|
5307
|
+
$title: input.title ?? null,
|
|
5308
|
+
$metadata: input.metadata === void 0 ? null : JSON.stringify(input.metadata),
|
|
5309
|
+
$now: now
|
|
5310
|
+
});
|
|
5311
|
+
return {
|
|
5312
|
+
id: input.id,
|
|
5313
|
+
agentId: input.agentId,
|
|
5314
|
+
...input.title === void 0 ? {} : { title: input.title },
|
|
5315
|
+
createdAt: now,
|
|
5316
|
+
updatedAt: now,
|
|
5317
|
+
messageCount: 0,
|
|
5318
|
+
...input.metadata === void 0 ? {} : { metadata: input.metadata }
|
|
5319
|
+
};
|
|
5320
|
+
}
|
|
5321
|
+
getSession(id) {
|
|
5322
|
+
const row = this.getSessionRow(id);
|
|
5323
|
+
return row === void 0 ? void 0 : toSession(row, this.listSessionMessages(id), this.listSessionRunRows(id));
|
|
5324
|
+
}
|
|
5325
|
+
load(context) {
|
|
5326
|
+
const session = this.getSession(context.sessionId);
|
|
5327
|
+
return Promise.resolve(session?.messages ?? []);
|
|
5328
|
+
}
|
|
5329
|
+
append(input) {
|
|
5330
|
+
const db = this.database();
|
|
5331
|
+
try {
|
|
5332
|
+
db.exec("BEGIN IMMEDIATE");
|
|
5333
|
+
const row = db.prepare(
|
|
5334
|
+
`SELECT id, agent_id, title, metadata_json, created_at, updated_at
|
|
5335
|
+
FROM anvia_studio_sessions
|
|
5336
|
+
WHERE id = $id`
|
|
5337
|
+
).get({ $id: input.context.sessionId });
|
|
5338
|
+
if (row === void 0) {
|
|
5339
|
+
db.exec("ROLLBACK");
|
|
5340
|
+
return Promise.resolve();
|
|
5341
|
+
}
|
|
5342
|
+
const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
5343
|
+
const nextIndex = this.nextMessageIndex(input.context.sessionId);
|
|
5344
|
+
this.insertMessages(input.context.sessionId, input.messages, nextIndex, updatedAt);
|
|
5345
|
+
db.prepare(
|
|
5346
|
+
`UPDATE anvia_studio_sessions
|
|
5347
|
+
SET updated_at = $updatedAt
|
|
5348
|
+
WHERE id = $id`
|
|
5349
|
+
).run({
|
|
5350
|
+
$id: input.context.sessionId,
|
|
5351
|
+
$updatedAt: updatedAt
|
|
5352
|
+
});
|
|
5353
|
+
db.exec("COMMIT");
|
|
5354
|
+
return Promise.resolve();
|
|
5355
|
+
} catch (error) {
|
|
5356
|
+
if (db.isTransaction) {
|
|
5357
|
+
db.exec("ROLLBACK");
|
|
5358
|
+
}
|
|
5359
|
+
throw error;
|
|
5360
|
+
}
|
|
5361
|
+
}
|
|
5362
|
+
clear(context) {
|
|
5363
|
+
const db = this.database();
|
|
5364
|
+
const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
5365
|
+
try {
|
|
5366
|
+
db.exec("BEGIN IMMEDIATE");
|
|
5367
|
+
db.prepare(
|
|
5368
|
+
`UPDATE anvia_studio_sessions
|
|
5369
|
+
SET updated_at = $updatedAt
|
|
5370
|
+
WHERE id = $id`
|
|
5371
|
+
).run({
|
|
5372
|
+
$id: context.sessionId,
|
|
5373
|
+
$updatedAt: updatedAt
|
|
5374
|
+
});
|
|
5375
|
+
db.prepare("DELETE FROM anvia_studio_session_messages WHERE session_id = $id").run({
|
|
5376
|
+
$id: context.sessionId
|
|
5377
|
+
});
|
|
5378
|
+
db.prepare("DELETE FROM anvia_studio_session_runs WHERE session_id = $id").run({
|
|
5379
|
+
$id: context.sessionId
|
|
5380
|
+
});
|
|
5381
|
+
db.exec("COMMIT");
|
|
5382
|
+
return Promise.resolve();
|
|
5383
|
+
} catch (error) {
|
|
5384
|
+
if (db.isTransaction) {
|
|
5385
|
+
db.exec("ROLLBACK");
|
|
5386
|
+
}
|
|
5387
|
+
throw error;
|
|
5388
|
+
}
|
|
5389
|
+
}
|
|
5390
|
+
async recordError(input) {
|
|
5391
|
+
const runId = studioRunId2(input.context) ?? input.runId;
|
|
5392
|
+
const existing = this.getSessionRun(input.context.sessionId, runId);
|
|
5393
|
+
const transcript = existing === void 0 || parseJsonArray(existing.transcript_json).length === 0 ? transcriptFromMessages(input.messages) : parseJsonArray(existing.transcript_json);
|
|
5394
|
+
await this.saveSessionRunTranscript({
|
|
5395
|
+
id: input.context.sessionId,
|
|
5396
|
+
runId,
|
|
5397
|
+
transcript,
|
|
5398
|
+
status: "error",
|
|
5399
|
+
error: serializeJsonError2(input.error)
|
|
5400
|
+
});
|
|
5401
|
+
}
|
|
5402
|
+
saveSessionRunTranscript(input) {
|
|
5403
|
+
const db = this.database();
|
|
5404
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
5405
|
+
try {
|
|
5406
|
+
db.exec("BEGIN IMMEDIATE");
|
|
5407
|
+
const row = this.getSessionRow(input.id);
|
|
5408
|
+
if (row === void 0) {
|
|
5409
|
+
db.exec("ROLLBACK");
|
|
5410
|
+
return void 0;
|
|
5411
|
+
}
|
|
5412
|
+
const current = toSession(
|
|
5413
|
+
row,
|
|
5414
|
+
this.listSessionMessages(input.id),
|
|
5415
|
+
this.listSessionRunRows(input.id)
|
|
5416
|
+
);
|
|
5417
|
+
const title = current.title ?? input.title;
|
|
5418
|
+
db.prepare(
|
|
5419
|
+
`INSERT INTO anvia_studio_session_runs (
|
|
5420
|
+
run_id,
|
|
5421
|
+
session_id,
|
|
5422
|
+
status,
|
|
5423
|
+
title,
|
|
5424
|
+
transcript_json,
|
|
5425
|
+
error_json,
|
|
5426
|
+
created_at,
|
|
5427
|
+
updated_at
|
|
5428
|
+
) VALUES (
|
|
5429
|
+
$runId,
|
|
5430
|
+
$sessionId,
|
|
5431
|
+
$status,
|
|
5432
|
+
$title,
|
|
5433
|
+
$transcript,
|
|
5434
|
+
$error,
|
|
5435
|
+
$now,
|
|
5436
|
+
$now
|
|
5437
|
+
)
|
|
5438
|
+
ON CONFLICT(run_id) DO UPDATE SET
|
|
5439
|
+
status = excluded.status,
|
|
5440
|
+
title = COALESCE(anvia_studio_session_runs.title, excluded.title),
|
|
5441
|
+
transcript_json = excluded.transcript_json,
|
|
5442
|
+
error_json = excluded.error_json,
|
|
5443
|
+
updated_at = excluded.updated_at`
|
|
5444
|
+
).run({
|
|
5445
|
+
$runId: input.runId,
|
|
5446
|
+
$sessionId: input.id,
|
|
5447
|
+
$status: input.status,
|
|
5448
|
+
$title: input.title ?? null,
|
|
5449
|
+
$transcript: JSON.stringify(renumberTranscript(input.transcript)),
|
|
5450
|
+
$error: input.error === void 0 ? null : JSON.stringify(input.error),
|
|
5451
|
+
$now: now
|
|
5452
|
+
});
|
|
5453
|
+
db.prepare(
|
|
5454
|
+
`UPDATE anvia_studio_sessions
|
|
5455
|
+
SET title = $title,
|
|
5456
|
+
updated_at = $updatedAt
|
|
5457
|
+
WHERE id = $id`
|
|
5458
|
+
).run({
|
|
5459
|
+
$id: input.id,
|
|
5460
|
+
$title: title ?? null,
|
|
5461
|
+
$updatedAt: now
|
|
5462
|
+
});
|
|
5463
|
+
db.exec("COMMIT");
|
|
5464
|
+
const updated = this.getSession(input.id);
|
|
5465
|
+
return updated;
|
|
5466
|
+
} catch (error) {
|
|
5467
|
+
if (db.isTransaction) {
|
|
5468
|
+
db.exec("ROLLBACK");
|
|
5469
|
+
}
|
|
5470
|
+
throw error;
|
|
5471
|
+
}
|
|
5472
|
+
}
|
|
5473
|
+
appendSessionLog(input) {
|
|
5474
|
+
const db = this.database();
|
|
5475
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
5476
|
+
try {
|
|
5477
|
+
db.exec("BEGIN IMMEDIATE");
|
|
5478
|
+
const row = this.getSessionRow(input.sessionId);
|
|
5479
|
+
if (row === void 0) {
|
|
5480
|
+
throw new Error("Session not found");
|
|
5481
|
+
}
|
|
5482
|
+
const sequence = this.nextSessionLogSequence(input.sessionId);
|
|
5483
|
+
const entry = {
|
|
5484
|
+
id: globalThis.crypto.randomUUID(),
|
|
5485
|
+
sessionId: input.sessionId,
|
|
5486
|
+
...input.runId === void 0 ? {} : { runId: input.runId },
|
|
5487
|
+
sequence,
|
|
5488
|
+
timestamp: now,
|
|
5489
|
+
level: input.level,
|
|
5490
|
+
category: input.category,
|
|
5491
|
+
event: input.event,
|
|
5492
|
+
message: input.message,
|
|
5493
|
+
...input.metadata === void 0 ? {} : { metadata: input.metadata }
|
|
5494
|
+
};
|
|
5495
|
+
db.prepare(
|
|
5496
|
+
`INSERT INTO anvia_studio_session_logs (
|
|
5497
|
+
id,
|
|
5498
|
+
session_id,
|
|
5499
|
+
run_id,
|
|
5500
|
+
sequence,
|
|
5501
|
+
timestamp,
|
|
5502
|
+
level,
|
|
5503
|
+
category,
|
|
5504
|
+
event,
|
|
5505
|
+
message,
|
|
5506
|
+
metadata_json
|
|
5507
|
+
) VALUES (
|
|
5508
|
+
$id,
|
|
5509
|
+
$sessionId,
|
|
5510
|
+
$runId,
|
|
5511
|
+
$sequence,
|
|
5512
|
+
$timestamp,
|
|
5513
|
+
$level,
|
|
5514
|
+
$category,
|
|
5515
|
+
$event,
|
|
5516
|
+
$message,
|
|
5517
|
+
$metadata
|
|
5518
|
+
)`
|
|
5519
|
+
).run({
|
|
5520
|
+
$id: entry.id,
|
|
5521
|
+
$sessionId: entry.sessionId,
|
|
5522
|
+
$runId: entry.runId ?? null,
|
|
5523
|
+
$sequence: entry.sequence,
|
|
5524
|
+
$timestamp: entry.timestamp,
|
|
5525
|
+
$level: entry.level,
|
|
5526
|
+
$category: entry.category,
|
|
5527
|
+
$event: entry.event,
|
|
5528
|
+
$message: entry.message,
|
|
5529
|
+
$metadata: entry.metadata === void 0 ? null : JSON.stringify(entry.metadata)
|
|
5530
|
+
});
|
|
5531
|
+
db.exec("COMMIT");
|
|
5532
|
+
return entry;
|
|
5533
|
+
} catch (error) {
|
|
5534
|
+
if (db.isTransaction) {
|
|
5535
|
+
db.exec("ROLLBACK");
|
|
5536
|
+
}
|
|
5537
|
+
throw error;
|
|
5538
|
+
}
|
|
5539
|
+
}
|
|
5540
|
+
listSessionLogs(options) {
|
|
5541
|
+
const db = this.database();
|
|
5542
|
+
const afterClause = options.after === void 0 ? "" : "AND sequence > $after";
|
|
5543
|
+
const rows = db.prepare(
|
|
5544
|
+
`SELECT id, session_id, run_id, sequence, timestamp, level, category, event, message,
|
|
5545
|
+
metadata_json
|
|
5546
|
+
FROM anvia_studio_session_logs
|
|
5547
|
+
WHERE session_id = $sessionId
|
|
5548
|
+
${afterClause}
|
|
5549
|
+
ORDER BY sequence ASC
|
|
5550
|
+
LIMIT $limit`
|
|
5551
|
+
).all({
|
|
5552
|
+
$sessionId: options.sessionId,
|
|
5553
|
+
$after: options.after ?? null,
|
|
5554
|
+
$limit: options.limit
|
|
5555
|
+
});
|
|
5556
|
+
return rows.map(toSessionLog);
|
|
5557
|
+
}
|
|
5558
|
+
appendPipelineLog(input) {
|
|
5559
|
+
const db = this.database();
|
|
5560
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
5561
|
+
try {
|
|
5562
|
+
db.exec("BEGIN IMMEDIATE");
|
|
5563
|
+
const sequence = this.nextPipelineLogSequence(input.pipelineId);
|
|
5564
|
+
const entry = {
|
|
5565
|
+
id: globalThis.crypto.randomUUID(),
|
|
5566
|
+
pipelineId: input.pipelineId,
|
|
5567
|
+
...input.runId === void 0 ? {} : { runId: input.runId },
|
|
5568
|
+
sequence,
|
|
5569
|
+
timestamp: now,
|
|
5570
|
+
level: input.level,
|
|
5571
|
+
category: input.category,
|
|
5572
|
+
event: input.event,
|
|
5573
|
+
message: input.message,
|
|
5574
|
+
...input.metadata === void 0 ? {} : { metadata: input.metadata }
|
|
5575
|
+
};
|
|
5576
|
+
db.prepare(
|
|
5577
|
+
`INSERT INTO anvia_studio_pipeline_logs (
|
|
5578
|
+
id,
|
|
5579
|
+
pipeline_id,
|
|
5580
|
+
run_id,
|
|
5581
|
+
sequence,
|
|
5582
|
+
timestamp,
|
|
5583
|
+
level,
|
|
5584
|
+
category,
|
|
5585
|
+
event,
|
|
5586
|
+
message,
|
|
5587
|
+
metadata_json
|
|
5588
|
+
) VALUES (
|
|
5589
|
+
$id,
|
|
5590
|
+
$pipelineId,
|
|
5591
|
+
$runId,
|
|
5592
|
+
$sequence,
|
|
5593
|
+
$timestamp,
|
|
5594
|
+
$level,
|
|
5595
|
+
$category,
|
|
5596
|
+
$event,
|
|
5597
|
+
$message,
|
|
5598
|
+
$metadata
|
|
5599
|
+
)`
|
|
5600
|
+
).run({
|
|
5601
|
+
$id: entry.id,
|
|
5602
|
+
$pipelineId: entry.pipelineId,
|
|
5603
|
+
$runId: entry.runId ?? null,
|
|
5604
|
+
$sequence: entry.sequence,
|
|
5605
|
+
$timestamp: entry.timestamp,
|
|
5606
|
+
$level: entry.level,
|
|
5607
|
+
$category: entry.category,
|
|
5608
|
+
$event: entry.event,
|
|
5609
|
+
$message: entry.message,
|
|
5610
|
+
$metadata: entry.metadata === void 0 ? null : JSON.stringify(entry.metadata)
|
|
5611
|
+
});
|
|
5612
|
+
db.exec("COMMIT");
|
|
5613
|
+
return entry;
|
|
5614
|
+
} catch (error) {
|
|
5615
|
+
if (db.isTransaction) {
|
|
5616
|
+
db.exec("ROLLBACK");
|
|
5617
|
+
}
|
|
5618
|
+
throw error;
|
|
5619
|
+
}
|
|
5620
|
+
}
|
|
5621
|
+
listPipelineLogs(options) {
|
|
5622
|
+
const db = this.database();
|
|
5623
|
+
const afterClause = options.after === void 0 ? "" : "AND sequence > $after";
|
|
5624
|
+
const rows = db.prepare(
|
|
5625
|
+
`SELECT id, pipeline_id, run_id, sequence, timestamp, level, category, event, message,
|
|
5626
|
+
metadata_json
|
|
5627
|
+
FROM anvia_studio_pipeline_logs
|
|
5628
|
+
WHERE pipeline_id = $pipelineId
|
|
5629
|
+
${afterClause}
|
|
5630
|
+
ORDER BY sequence ASC
|
|
5631
|
+
LIMIT $limit`
|
|
5632
|
+
).all({
|
|
5633
|
+
$pipelineId: options.pipelineId,
|
|
5634
|
+
$after: options.after ?? null,
|
|
5635
|
+
$limit: options.limit
|
|
5636
|
+
});
|
|
5637
|
+
return rows.map(toPipelineLog);
|
|
5638
|
+
}
|
|
5639
|
+
savePipelineRun(input) {
|
|
5640
|
+
const db = this.database();
|
|
5641
|
+
db.prepare(
|
|
5642
|
+
`INSERT INTO anvia_studio_pipeline_runs (
|
|
5643
|
+
run_id,
|
|
5644
|
+
pipeline_id,
|
|
5645
|
+
status,
|
|
5646
|
+
input_json,
|
|
5647
|
+
output_json,
|
|
5648
|
+
error_json,
|
|
5649
|
+
metadata_json,
|
|
5650
|
+
started_at,
|
|
5651
|
+
ended_at,
|
|
5652
|
+
duration_ms
|
|
5653
|
+
) VALUES (
|
|
5654
|
+
$runId,
|
|
5655
|
+
$pipelineId,
|
|
5656
|
+
$status,
|
|
5657
|
+
$input,
|
|
5658
|
+
$output,
|
|
5659
|
+
$error,
|
|
5660
|
+
$metadata,
|
|
5661
|
+
$startedAt,
|
|
5662
|
+
$endedAt,
|
|
5663
|
+
$durationMs
|
|
5664
|
+
)
|
|
5665
|
+
ON CONFLICT(run_id) DO UPDATE SET
|
|
5666
|
+
pipeline_id = excluded.pipeline_id,
|
|
5667
|
+
status = excluded.status,
|
|
5668
|
+
input_json = excluded.input_json,
|
|
5669
|
+
output_json = excluded.output_json,
|
|
5670
|
+
error_json = excluded.error_json,
|
|
5671
|
+
metadata_json = excluded.metadata_json,
|
|
5672
|
+
started_at = excluded.started_at,
|
|
5673
|
+
ended_at = excluded.ended_at,
|
|
5674
|
+
duration_ms = excluded.duration_ms`
|
|
5675
|
+
).run({
|
|
5676
|
+
$runId: input.runId,
|
|
5677
|
+
$pipelineId: input.pipelineId,
|
|
5678
|
+
$status: input.status,
|
|
5679
|
+
$input: JSON.stringify(input.input),
|
|
5680
|
+
$output: input.output === void 0 ? null : JSON.stringify(input.output),
|
|
5681
|
+
$error: input.error === void 0 ? null : JSON.stringify(input.error),
|
|
5682
|
+
$metadata: input.metadata === void 0 ? null : JSON.stringify(input.metadata),
|
|
5683
|
+
$startedAt: input.startedAt,
|
|
5684
|
+
$endedAt: input.endedAt ?? null,
|
|
5685
|
+
$durationMs: input.durationMs ?? null
|
|
5686
|
+
});
|
|
5687
|
+
return {
|
|
5688
|
+
runId: input.runId,
|
|
5689
|
+
pipelineId: input.pipelineId,
|
|
5690
|
+
status: input.status,
|
|
5691
|
+
input: input.input,
|
|
5692
|
+
...input.output === void 0 ? {} : { output: input.output },
|
|
5693
|
+
...input.error === void 0 ? {} : { error: input.error },
|
|
5694
|
+
...input.metadata === void 0 ? {} : { metadata: input.metadata },
|
|
5695
|
+
startedAt: input.startedAt,
|
|
5696
|
+
...input.endedAt === void 0 ? {} : { endedAt: input.endedAt },
|
|
5697
|
+
...input.durationMs === void 0 ? {} : { durationMs: input.durationMs }
|
|
5698
|
+
};
|
|
5699
|
+
}
|
|
5700
|
+
getPipelineRun(options) {
|
|
5701
|
+
const db = this.database();
|
|
5702
|
+
const row = db.prepare(
|
|
5703
|
+
`SELECT run_id, pipeline_id, status, input_json, output_json, error_json,
|
|
5704
|
+
metadata_json, started_at, ended_at, duration_ms
|
|
5705
|
+
FROM anvia_studio_pipeline_runs
|
|
5706
|
+
WHERE pipeline_id = $pipelineId AND run_id = $runId`
|
|
5707
|
+
).get({
|
|
5708
|
+
$pipelineId: options.pipelineId,
|
|
5709
|
+
$runId: options.runId
|
|
5710
|
+
});
|
|
5711
|
+
return row === void 0 ? void 0 : toPipelineRun(row);
|
|
5712
|
+
}
|
|
5713
|
+
listPipelineRuns(options) {
|
|
5714
|
+
const db = this.database();
|
|
5715
|
+
const rows = db.prepare(
|
|
5716
|
+
`SELECT run_id, pipeline_id, status, input_json, output_json, error_json,
|
|
5717
|
+
metadata_json, started_at, ended_at, duration_ms
|
|
5718
|
+
FROM anvia_studio_pipeline_runs
|
|
5719
|
+
WHERE pipeline_id = $pipelineId
|
|
5720
|
+
ORDER BY started_at DESC
|
|
5721
|
+
LIMIT $limit`
|
|
5722
|
+
).all({
|
|
5723
|
+
$pipelineId: options.pipelineId,
|
|
5724
|
+
$limit: options.limit
|
|
5725
|
+
});
|
|
5726
|
+
return rows.map(toPipelineRun);
|
|
5727
|
+
}
|
|
5728
|
+
deleteSession(id) {
|
|
5729
|
+
const db = this.database();
|
|
5730
|
+
try {
|
|
5731
|
+
db.exec("BEGIN IMMEDIATE");
|
|
5732
|
+
db.prepare("DELETE FROM anvia_studio_traces WHERE session_id = $id").run({ $id: id });
|
|
5733
|
+
db.prepare("DELETE FROM anvia_studio_session_runs WHERE session_id = $id").run({ $id: id });
|
|
5734
|
+
db.prepare("DELETE FROM anvia_studio_session_logs WHERE session_id = $id").run({ $id: id });
|
|
5735
|
+
const result = db.prepare("DELETE FROM anvia_studio_sessions WHERE id = $id").run({ $id: id });
|
|
5736
|
+
db.exec("COMMIT");
|
|
5737
|
+
return Number(result.changes) > 0;
|
|
5738
|
+
} catch (error) {
|
|
5739
|
+
if (db.isTransaction) {
|
|
5740
|
+
db.exec("ROLLBACK");
|
|
5741
|
+
}
|
|
5742
|
+
throw error;
|
|
5743
|
+
}
|
|
5744
|
+
}
|
|
5745
|
+
listTraces(options) {
|
|
5746
|
+
const db = this.database();
|
|
5747
|
+
const filters = [];
|
|
5748
|
+
const values = {
|
|
5749
|
+
$limit: options.limit
|
|
5750
|
+
};
|
|
5751
|
+
if (options.agentId !== void 0) {
|
|
5752
|
+
filters.push(
|
|
5753
|
+
"(s.agent_id = $agentId OR json_extract(t.metadata_json, '$.metadata.agentId') = $agentId)"
|
|
5754
|
+
);
|
|
5755
|
+
values.$agentId = options.agentId;
|
|
5756
|
+
}
|
|
5757
|
+
if (options.sessionId !== void 0) {
|
|
5758
|
+
filters.push("t.session_id = $sessionId");
|
|
5759
|
+
values.$sessionId = options.sessionId;
|
|
5760
|
+
}
|
|
5761
|
+
if (options.status !== void 0) {
|
|
5762
|
+
filters.push("t.status = $status");
|
|
5763
|
+
values.$status = options.status;
|
|
5764
|
+
}
|
|
5765
|
+
const whereClause = filters.length === 0 ? "" : `WHERE ${filters.join(" AND ")}`;
|
|
5766
|
+
const rows = db.prepare(
|
|
5767
|
+
`SELECT t.id, t.session_id, t.name, t.status, t.trace_json, t.input_json, t.output,
|
|
5768
|
+
t.error_json, t.usage_json, t.metadata_json, t.observations_json,
|
|
5769
|
+
t.started_at, t.ended_at, t.duration_ms
|
|
5770
|
+
FROM anvia_studio_traces t
|
|
5771
|
+
LEFT JOIN anvia_studio_sessions s ON s.id = t.session_id
|
|
5772
|
+
${whereClause}
|
|
5773
|
+
ORDER BY t.started_at DESC
|
|
5774
|
+
LIMIT $limit`
|
|
5775
|
+
).all(values);
|
|
5776
|
+
return rows.map(toTraceSummary);
|
|
5777
|
+
}
|
|
5778
|
+
listSessionTraces(options) {
|
|
5779
|
+
const db = this.database();
|
|
5780
|
+
const rows = db.prepare(
|
|
5781
|
+
`SELECT id, session_id, name, status, trace_json, input_json, output, error_json,
|
|
5782
|
+
usage_json, metadata_json, observations_json, started_at, ended_at, duration_ms
|
|
5783
|
+
FROM anvia_studio_traces
|
|
5784
|
+
WHERE session_id = $sessionId
|
|
5785
|
+
ORDER BY started_at DESC
|
|
5786
|
+
LIMIT $limit`
|
|
5787
|
+
).all({
|
|
5788
|
+
$sessionId: options.sessionId,
|
|
5789
|
+
$limit: options.limit
|
|
5790
|
+
});
|
|
5791
|
+
return rows.map(toTraceSummary);
|
|
5792
|
+
}
|
|
5793
|
+
getTrace(id) {
|
|
5794
|
+
const db = this.database();
|
|
5795
|
+
const row = db.prepare(
|
|
5796
|
+
`SELECT id, session_id, name, status, trace_json, input_json, output, error_json,
|
|
5797
|
+
usage_json, metadata_json, observations_json, started_at, ended_at, duration_ms
|
|
5798
|
+
FROM anvia_studio_traces
|
|
5799
|
+
WHERE id = $id`
|
|
5800
|
+
).get({ $id: id });
|
|
5801
|
+
return row === void 0 ? void 0 : toTrace(row);
|
|
5802
|
+
}
|
|
5803
|
+
saveTrace(trace) {
|
|
5804
|
+
const db = this.database();
|
|
5805
|
+
db.prepare(
|
|
5806
|
+
`INSERT INTO anvia_studio_traces (
|
|
5807
|
+
id,
|
|
5808
|
+
session_id,
|
|
5809
|
+
name,
|
|
5810
|
+
status,
|
|
5811
|
+
trace_json,
|
|
5812
|
+
input_json,
|
|
5813
|
+
output,
|
|
5814
|
+
error_json,
|
|
5815
|
+
usage_json,
|
|
5816
|
+
metadata_json,
|
|
5817
|
+
observations_json,
|
|
5818
|
+
started_at,
|
|
5819
|
+
ended_at,
|
|
5820
|
+
duration_ms
|
|
5821
|
+
) VALUES (
|
|
5822
|
+
$id,
|
|
5823
|
+
$sessionId,
|
|
5824
|
+
$name,
|
|
5825
|
+
$status,
|
|
5826
|
+
$trace,
|
|
5827
|
+
$input,
|
|
5828
|
+
$output,
|
|
5829
|
+
$error,
|
|
5830
|
+
$usage,
|
|
5831
|
+
$metadata,
|
|
5832
|
+
$observations,
|
|
5833
|
+
$startedAt,
|
|
5834
|
+
$endedAt,
|
|
5835
|
+
$durationMs
|
|
5836
|
+
)
|
|
5837
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
5838
|
+
session_id = excluded.session_id,
|
|
5839
|
+
name = excluded.name,
|
|
5840
|
+
status = excluded.status,
|
|
5841
|
+
trace_json = excluded.trace_json,
|
|
5842
|
+
input_json = excluded.input_json,
|
|
5843
|
+
output = excluded.output,
|
|
5844
|
+
error_json = excluded.error_json,
|
|
5845
|
+
usage_json = excluded.usage_json,
|
|
5846
|
+
metadata_json = excluded.metadata_json,
|
|
5847
|
+
observations_json = excluded.observations_json,
|
|
5848
|
+
started_at = excluded.started_at,
|
|
5849
|
+
ended_at = excluded.ended_at,
|
|
5850
|
+
duration_ms = excluded.duration_ms`
|
|
5851
|
+
).run({
|
|
5852
|
+
$id: trace.id,
|
|
5853
|
+
$sessionId: trace.sessionId,
|
|
5854
|
+
$name: trace.name ?? null,
|
|
5855
|
+
$status: trace.status,
|
|
5856
|
+
$trace: trace.trace === void 0 ? null : JSON.stringify(trace.trace),
|
|
5857
|
+
$input: trace.input === void 0 ? null : JSON.stringify(trace.input),
|
|
5858
|
+
$output: trace.output ?? null,
|
|
5859
|
+
$error: trace.error === void 0 ? null : JSON.stringify(trace.error),
|
|
5860
|
+
$usage: trace.usage === void 0 ? null : JSON.stringify(trace.usage),
|
|
5861
|
+
$metadata: trace.metadata === void 0 ? null : JSON.stringify(trace.metadata),
|
|
5862
|
+
$observations: JSON.stringify(trace.observations),
|
|
5863
|
+
$startedAt: trace.startedAt,
|
|
5864
|
+
$endedAt: trace.endedAt ?? null,
|
|
5865
|
+
$durationMs: trace.durationMs ?? null
|
|
5866
|
+
});
|
|
5867
|
+
return trace;
|
|
5868
|
+
}
|
|
5869
|
+
database() {
|
|
5870
|
+
if (this.db !== void 0) {
|
|
5871
|
+
return this.db;
|
|
5872
|
+
}
|
|
5873
|
+
if (this.path !== ":memory:") {
|
|
5874
|
+
mkdirSync(dirname(resolve(this.path)), { recursive: true });
|
|
5875
|
+
}
|
|
5876
|
+
const db = new (loadDatabaseSync())(this.path, {
|
|
5877
|
+
allowUnknownNamedParameters: true,
|
|
5878
|
+
timeout: 5e3
|
|
5879
|
+
});
|
|
5880
|
+
db.exec(`
|
|
5881
|
+
PRAGMA journal_mode = WAL;
|
|
5882
|
+
PRAGMA foreign_keys = ON;
|
|
5883
|
+
`);
|
|
5884
|
+
guardAgainstLegacySessionSchema(db);
|
|
5885
|
+
db.exec(`
|
|
5886
|
+
CREATE TABLE IF NOT EXISTS anvia_studio_sessions (
|
|
5887
|
+
id TEXT PRIMARY KEY,
|
|
5888
|
+
agent_id TEXT NOT NULL,
|
|
5889
|
+
title TEXT,
|
|
5890
|
+
metadata_json TEXT,
|
|
5891
|
+
created_at TEXT NOT NULL,
|
|
5892
|
+
updated_at TEXT NOT NULL
|
|
5893
|
+
) STRICT;
|
|
5894
|
+
CREATE INDEX IF NOT EXISTS anvia_studio_sessions_agent_updated_idx
|
|
5895
|
+
ON anvia_studio_sessions(agent_id, updated_at DESC);
|
|
5896
|
+
CREATE TABLE IF NOT EXISTS anvia_studio_session_messages (
|
|
5897
|
+
session_id TEXT NOT NULL,
|
|
5898
|
+
message_index INTEGER NOT NULL,
|
|
5899
|
+
role TEXT NOT NULL,
|
|
5900
|
+
message_id TEXT,
|
|
5901
|
+
created_at TEXT NOT NULL,
|
|
5902
|
+
PRIMARY KEY(session_id, message_index),
|
|
5903
|
+
FOREIGN KEY(session_id) REFERENCES anvia_studio_sessions(id) ON DELETE CASCADE
|
|
5904
|
+
) STRICT;
|
|
5905
|
+
CREATE INDEX IF NOT EXISTS anvia_studio_session_messages_session_idx
|
|
5906
|
+
ON anvia_studio_session_messages(session_id, message_index ASC);
|
|
5907
|
+
CREATE TABLE IF NOT EXISTS anvia_studio_session_message_parts (
|
|
5908
|
+
session_id TEXT NOT NULL,
|
|
5909
|
+
message_index INTEGER NOT NULL,
|
|
5910
|
+
part_index INTEGER NOT NULL,
|
|
5911
|
+
type TEXT NOT NULL,
|
|
5912
|
+
part_json TEXT NOT NULL,
|
|
5913
|
+
PRIMARY KEY(session_id, message_index, part_index),
|
|
5914
|
+
FOREIGN KEY(session_id, message_index)
|
|
5915
|
+
REFERENCES anvia_studio_session_messages(session_id, message_index)
|
|
5916
|
+
ON DELETE CASCADE
|
|
5917
|
+
) STRICT;
|
|
5918
|
+
CREATE TABLE IF NOT EXISTS anvia_studio_session_runs (
|
|
5919
|
+
run_id TEXT PRIMARY KEY,
|
|
5920
|
+
session_id TEXT NOT NULL,
|
|
5921
|
+
status TEXT NOT NULL,
|
|
5922
|
+
title TEXT,
|
|
5923
|
+
transcript_json TEXT NOT NULL,
|
|
5924
|
+
error_json TEXT,
|
|
5925
|
+
created_at TEXT NOT NULL,
|
|
5926
|
+
updated_at TEXT NOT NULL,
|
|
5927
|
+
FOREIGN KEY(session_id) REFERENCES anvia_studio_sessions(id) ON DELETE CASCADE
|
|
5928
|
+
) STRICT;
|
|
5929
|
+
CREATE INDEX IF NOT EXISTS anvia_studio_session_runs_session_created_idx
|
|
5930
|
+
ON anvia_studio_session_runs(session_id, created_at ASC);
|
|
5931
|
+
CREATE TABLE IF NOT EXISTS anvia_studio_session_logs (
|
|
5932
|
+
id TEXT PRIMARY KEY,
|
|
5933
|
+
session_id TEXT NOT NULL,
|
|
5934
|
+
run_id TEXT,
|
|
5935
|
+
sequence INTEGER NOT NULL,
|
|
5936
|
+
timestamp TEXT NOT NULL,
|
|
5937
|
+
level TEXT NOT NULL,
|
|
5938
|
+
category TEXT NOT NULL,
|
|
5939
|
+
event TEXT NOT NULL,
|
|
5940
|
+
message TEXT NOT NULL,
|
|
5941
|
+
metadata_json TEXT,
|
|
5942
|
+
UNIQUE(session_id, sequence),
|
|
5943
|
+
FOREIGN KEY(session_id) REFERENCES anvia_studio_sessions(id) ON DELETE CASCADE
|
|
5944
|
+
) STRICT;
|
|
5945
|
+
CREATE INDEX IF NOT EXISTS anvia_studio_session_logs_session_sequence_idx
|
|
5946
|
+
ON anvia_studio_session_logs(session_id, sequence ASC);
|
|
5947
|
+
CREATE TABLE IF NOT EXISTS anvia_studio_pipeline_logs (
|
|
5948
|
+
id TEXT PRIMARY KEY,
|
|
5949
|
+
pipeline_id TEXT NOT NULL,
|
|
5950
|
+
run_id TEXT,
|
|
5951
|
+
sequence INTEGER NOT NULL,
|
|
5952
|
+
timestamp TEXT NOT NULL,
|
|
5953
|
+
level TEXT NOT NULL,
|
|
5954
|
+
category TEXT NOT NULL,
|
|
5955
|
+
event TEXT NOT NULL,
|
|
5956
|
+
message TEXT NOT NULL,
|
|
5957
|
+
metadata_json TEXT,
|
|
5958
|
+
UNIQUE(pipeline_id, sequence)
|
|
5959
|
+
) STRICT;
|
|
5960
|
+
CREATE INDEX IF NOT EXISTS anvia_studio_pipeline_logs_pipeline_sequence_idx
|
|
5961
|
+
ON anvia_studio_pipeline_logs(pipeline_id, sequence ASC);
|
|
5962
|
+
CREATE TABLE IF NOT EXISTS anvia_studio_pipeline_runs (
|
|
5963
|
+
run_id TEXT PRIMARY KEY,
|
|
5964
|
+
pipeline_id TEXT NOT NULL,
|
|
5965
|
+
status TEXT NOT NULL,
|
|
5966
|
+
input_json TEXT NOT NULL,
|
|
5967
|
+
output_json TEXT,
|
|
5968
|
+
error_json TEXT,
|
|
5969
|
+
metadata_json TEXT,
|
|
5970
|
+
started_at TEXT NOT NULL,
|
|
5971
|
+
ended_at TEXT,
|
|
5972
|
+
duration_ms INTEGER
|
|
5973
|
+
) STRICT;
|
|
5974
|
+
CREATE INDEX IF NOT EXISTS anvia_studio_pipeline_runs_pipeline_started_idx
|
|
5975
|
+
ON anvia_studio_pipeline_runs(pipeline_id, started_at DESC);
|
|
5976
|
+
CREATE TABLE IF NOT EXISTS anvia_studio_traces (
|
|
5977
|
+
id TEXT PRIMARY KEY,
|
|
5978
|
+
session_id TEXT NOT NULL,
|
|
5979
|
+
name TEXT,
|
|
5980
|
+
status TEXT NOT NULL,
|
|
5981
|
+
trace_json TEXT,
|
|
5982
|
+
input_json TEXT,
|
|
5983
|
+
output TEXT,
|
|
5984
|
+
error_json TEXT,
|
|
5985
|
+
usage_json TEXT,
|
|
5986
|
+
metadata_json TEXT,
|
|
5987
|
+
observations_json TEXT NOT NULL,
|
|
5988
|
+
started_at TEXT NOT NULL,
|
|
5989
|
+
ended_at TEXT,
|
|
5990
|
+
duration_ms INTEGER
|
|
5991
|
+
) STRICT;
|
|
5992
|
+
CREATE INDEX IF NOT EXISTS anvia_studio_traces_session_started_idx
|
|
5993
|
+
ON anvia_studio_traces(session_id, started_at DESC);
|
|
5994
|
+
`);
|
|
5995
|
+
this.db = db;
|
|
5996
|
+
return db;
|
|
5997
|
+
}
|
|
5998
|
+
getSessionRow(id) {
|
|
5999
|
+
return this.database().prepare(
|
|
6000
|
+
`SELECT id, agent_id, title, metadata_json, created_at, updated_at
|
|
6001
|
+
FROM anvia_studio_sessions
|
|
6002
|
+
WHERE id = $id`
|
|
6003
|
+
).get({ $id: id });
|
|
6004
|
+
}
|
|
6005
|
+
getSessionRun(sessionId, runId) {
|
|
6006
|
+
return this.database().prepare(
|
|
6007
|
+
`SELECT run_id, session_id, status, title, transcript_json, error_json, created_at, updated_at
|
|
6008
|
+
FROM anvia_studio_session_runs
|
|
6009
|
+
WHERE session_id = $sessionId AND run_id = $runId`
|
|
6010
|
+
).get({ $sessionId: sessionId, $runId: runId });
|
|
6011
|
+
}
|
|
6012
|
+
listSessionRunRows(sessionId) {
|
|
6013
|
+
return this.database().prepare(
|
|
6014
|
+
`SELECT run_id, session_id, status, title, transcript_json, error_json, created_at, updated_at
|
|
6015
|
+
FROM anvia_studio_session_runs
|
|
6016
|
+
WHERE session_id = $sessionId
|
|
6017
|
+
ORDER BY created_at ASC`
|
|
6018
|
+
).all({ $sessionId: sessionId });
|
|
6019
|
+
}
|
|
6020
|
+
nextSessionLogSequence(sessionId) {
|
|
6021
|
+
const row = this.database().prepare(
|
|
6022
|
+
`SELECT COALESCE(MAX(sequence) + 1, 0) AS next_sequence
|
|
6023
|
+
FROM anvia_studio_session_logs
|
|
6024
|
+
WHERE session_id = $sessionId`
|
|
6025
|
+
).get({ $sessionId: sessionId });
|
|
6026
|
+
return row.next_sequence;
|
|
6027
|
+
}
|
|
6028
|
+
nextPipelineLogSequence(pipelineId) {
|
|
6029
|
+
const row = this.database().prepare(
|
|
6030
|
+
`SELECT COALESCE(MAX(sequence) + 1, 0) AS next_sequence
|
|
6031
|
+
FROM anvia_studio_pipeline_logs
|
|
6032
|
+
WHERE pipeline_id = $pipelineId`
|
|
6033
|
+
).get({ $pipelineId: pipelineId });
|
|
6034
|
+
return row.next_sequence;
|
|
6035
|
+
}
|
|
6036
|
+
listSessionMessages(sessionId) {
|
|
6037
|
+
const db = this.database();
|
|
6038
|
+
const messageRows = db.prepare(
|
|
6039
|
+
`SELECT session_id, message_index, role, message_id, created_at
|
|
6040
|
+
FROM anvia_studio_session_messages
|
|
6041
|
+
WHERE session_id = $sessionId
|
|
6042
|
+
ORDER BY message_index ASC`
|
|
6043
|
+
).all({ $sessionId: sessionId });
|
|
6044
|
+
if (messageRows.length === 0) {
|
|
6045
|
+
return [];
|
|
6046
|
+
}
|
|
6047
|
+
const partRows = db.prepare(
|
|
6048
|
+
`SELECT session_id, message_index, part_index, type, part_json
|
|
6049
|
+
FROM anvia_studio_session_message_parts
|
|
6050
|
+
WHERE session_id = $sessionId
|
|
6051
|
+
ORDER BY message_index ASC, part_index ASC`
|
|
6052
|
+
).all({ $sessionId: sessionId });
|
|
6053
|
+
const partsByMessage = /* @__PURE__ */ new Map();
|
|
6054
|
+
for (const partRow of partRows) {
|
|
6055
|
+
const parts = partsByMessage.get(partRow.message_index) ?? [];
|
|
6056
|
+
parts.push(partRow);
|
|
6057
|
+
partsByMessage.set(partRow.message_index, parts);
|
|
6020
6058
|
}
|
|
6021
|
-
|
|
6022
|
-
|
|
6023
|
-
...body.metadata ?? {},
|
|
6024
|
-
studioRunId: runId
|
|
6025
|
-
};
|
|
6026
|
-
const request = session !== void 0 ? agent.agent.session(session.id, { metadata: memoryMetadata }).prompt(body.message) : agent.agent.prompt(
|
|
6027
|
-
body.history !== void 0 ? [...body.history, normalizePromptMessage(body.message)] : body.message
|
|
6059
|
+
return messageRows.map(
|
|
6060
|
+
(row) => messageFromRows(row, partsByMessage.get(row.message_index) ?? [])
|
|
6028
6061
|
);
|
|
6029
|
-
|
|
6030
|
-
|
|
6031
|
-
|
|
6032
|
-
|
|
6033
|
-
|
|
6034
|
-
|
|
6035
|
-
|
|
6036
|
-
|
|
6037
|
-
|
|
6038
|
-
|
|
6039
|
-
|
|
6040
|
-
|
|
6041
|
-
|
|
6042
|
-
|
|
6043
|
-
|
|
6044
|
-
|
|
6045
|
-
|
|
6046
|
-
|
|
6047
|
-
|
|
6048
|
-
|
|
6049
|
-
|
|
6050
|
-
|
|
6051
|
-
|
|
6052
|
-
|
|
6053
|
-
|
|
6054
|
-
|
|
6055
|
-
|
|
6056
|
-
|
|
6057
|
-
|
|
6058
|
-
|
|
6059
|
-
|
|
6060
|
-
|
|
6061
|
-
|
|
6062
|
-
|
|
6063
|
-
|
|
6064
|
-
|
|
6065
|
-
|
|
6066
|
-
const stream = session === void 0 || stores.sessions === void 0 ? runStream : persistStreamingSessionTranscript({
|
|
6067
|
-
stream: streamSessionRunLogs({
|
|
6068
|
-
stream: runStream,
|
|
6069
|
-
store: stores.sessions,
|
|
6070
|
-
session,
|
|
6071
|
-
runId,
|
|
6072
|
-
startedAt: runStartedAt
|
|
6073
|
-
}),
|
|
6074
|
-
store: stores.sessions,
|
|
6075
|
-
session,
|
|
6076
|
-
message: body.message,
|
|
6077
|
-
runId
|
|
6062
|
+
}
|
|
6063
|
+
nextMessageIndex(sessionId) {
|
|
6064
|
+
const row = this.database().prepare(
|
|
6065
|
+
`SELECT COALESCE(MAX(message_index) + 1, 0) AS next_index
|
|
6066
|
+
FROM anvia_studio_session_messages
|
|
6067
|
+
WHERE session_id = $sessionId`
|
|
6068
|
+
).get({ $sessionId: sessionId });
|
|
6069
|
+
return row.next_index;
|
|
6070
|
+
}
|
|
6071
|
+
insertMessages(sessionId, messages, startIndex, createdAt) {
|
|
6072
|
+
const db = this.database();
|
|
6073
|
+
const insertMessage = db.prepare(
|
|
6074
|
+
`INSERT INTO anvia_studio_session_messages (
|
|
6075
|
+
session_id,
|
|
6076
|
+
message_index,
|
|
6077
|
+
role,
|
|
6078
|
+
message_id,
|
|
6079
|
+
created_at
|
|
6080
|
+
) VALUES ($sessionId, $messageIndex, $role, $messageId, $createdAt)`
|
|
6081
|
+
);
|
|
6082
|
+
const insertPart = db.prepare(
|
|
6083
|
+
`INSERT INTO anvia_studio_session_message_parts (
|
|
6084
|
+
session_id,
|
|
6085
|
+
message_index,
|
|
6086
|
+
part_index,
|
|
6087
|
+
type,
|
|
6088
|
+
part_json
|
|
6089
|
+
) VALUES ($sessionId, $messageIndex, $partIndex, $type, $partJson)`
|
|
6090
|
+
);
|
|
6091
|
+
messages.forEach((message, messageOffset) => {
|
|
6092
|
+
const messageIndex = startIndex + messageOffset;
|
|
6093
|
+
insertMessage.run({
|
|
6094
|
+
$sessionId: sessionId,
|
|
6095
|
+
$messageIndex: messageIndex,
|
|
6096
|
+
$role: message.role,
|
|
6097
|
+
$messageId: message.role === "assistant" ? message.id ?? null : null,
|
|
6098
|
+
$createdAt: createdAt
|
|
6078
6099
|
});
|
|
6079
|
-
|
|
6080
|
-
|
|
6081
|
-
|
|
6082
|
-
|
|
6083
|
-
|
|
6084
|
-
|
|
6085
|
-
|
|
6086
|
-
const effectiveHook = composeHooks(
|
|
6087
|
-
composeHooks(
|
|
6088
|
-
agent.agent.hook,
|
|
6089
|
-
approvalRuntime.createHook({
|
|
6090
|
-
runId,
|
|
6091
|
-
agentId,
|
|
6092
|
-
...session?.id === void 0 ? {} : { sessionId: session.id },
|
|
6093
|
-
...body.metadata === void 0 ? {} : { metadata: body.metadata },
|
|
6094
|
-
getTool: (toolName) => agent.agent.getTool(toolName)
|
|
6095
|
-
})
|
|
6096
|
-
),
|
|
6097
|
-
questionRuntime.createHook({
|
|
6098
|
-
runId,
|
|
6099
|
-
agentId,
|
|
6100
|
-
...session?.id === void 0 ? {} : { sessionId: session.id },
|
|
6101
|
-
...body.metadata === void 0 ? {} : { metadata: body.metadata }
|
|
6102
|
-
})
|
|
6103
|
-
);
|
|
6104
|
-
if (effectiveHook !== void 0) {
|
|
6105
|
-
request.requestHook(effectiveHook);
|
|
6106
|
-
}
|
|
6107
|
-
const response = await request.send();
|
|
6108
|
-
if (session !== void 0 && stores.sessions !== void 0) {
|
|
6109
|
-
await stores.sessions.saveSessionRunTranscript({
|
|
6110
|
-
id: session.id,
|
|
6111
|
-
runId,
|
|
6112
|
-
...optionalTitle(body.message),
|
|
6113
|
-
transcript: transcriptFromMessages(response.messages),
|
|
6114
|
-
status: "success"
|
|
6115
|
-
});
|
|
6116
|
-
await appendSessionLog(
|
|
6117
|
-
stores.sessions,
|
|
6118
|
-
runCompletedLog({
|
|
6119
|
-
sessionId: session.id,
|
|
6120
|
-
runId,
|
|
6121
|
-
durationMs: Date.now() - runStartedAt,
|
|
6122
|
-
usage: response.usage,
|
|
6123
|
-
output: response.output,
|
|
6124
|
-
messageCount: response.messages.length
|
|
6125
|
-
})
|
|
6126
|
-
);
|
|
6127
|
-
await appendSessionLog(
|
|
6128
|
-
stores.sessions,
|
|
6129
|
-
memorySavedLog({
|
|
6130
|
-
sessionId: session.id,
|
|
6131
|
-
runId,
|
|
6132
|
-
messageCount: response.messages.length
|
|
6133
|
-
})
|
|
6134
|
-
);
|
|
6135
|
-
}
|
|
6136
|
-
return c.json(response);
|
|
6137
|
-
} catch (error) {
|
|
6138
|
-
if (session !== void 0 && stores.sessions !== void 0) {
|
|
6139
|
-
const messages = await stores.sessions.load({
|
|
6140
|
-
sessionId: session.id,
|
|
6141
|
-
metadata: memoryMetadata
|
|
6142
|
-
});
|
|
6143
|
-
await stores.sessions.saveSessionRunTranscript({
|
|
6144
|
-
id: session.id,
|
|
6145
|
-
runId,
|
|
6146
|
-
...optionalTitle(body.message),
|
|
6147
|
-
transcript: transcriptFromMessages(messages.slice(session.messageCount)),
|
|
6148
|
-
status: "error",
|
|
6149
|
-
error: serializeError(error)
|
|
6100
|
+
messageParts(message).forEach((part, partIndex) => {
|
|
6101
|
+
insertPart.run({
|
|
6102
|
+
$sessionId: sessionId,
|
|
6103
|
+
$messageIndex: messageIndex,
|
|
6104
|
+
$partIndex: partIndex,
|
|
6105
|
+
$type: part.type,
|
|
6106
|
+
$partJson: JSON.stringify(part.value)
|
|
6150
6107
|
});
|
|
6151
|
-
|
|
6152
|
-
stores.sessions,
|
|
6153
|
-
runFailedLog(session.id, runId, error, runStartedAt)
|
|
6154
|
-
);
|
|
6155
|
-
}
|
|
6156
|
-
return errorResponse(c, 500, "internal_error", "Agent run failed", serializeError(error));
|
|
6157
|
-
}
|
|
6158
|
-
});
|
|
6159
|
-
if (stores.sessions !== void 0) {
|
|
6160
|
-
registerMemoryRoutes(app, {
|
|
6161
|
-
sessionStore: stores.sessions
|
|
6162
|
-
});
|
|
6163
|
-
registerSessionRoutes(app, {
|
|
6164
|
-
agentMap,
|
|
6165
|
-
sessionStore: stores.sessions,
|
|
6166
|
-
...stores.traces === void 0 ? {} : { traceStore: stores.traces }
|
|
6108
|
+
});
|
|
6167
6109
|
});
|
|
6168
6110
|
}
|
|
6169
|
-
|
|
6170
|
-
|
|
6111
|
+
};
|
|
6112
|
+
function toSession(row, messages, runRows = []) {
|
|
6113
|
+
const summary = toSessionSummary({ ...row, message_count: messages.length });
|
|
6114
|
+
const runTranscript = runRows.flatMap(
|
|
6115
|
+
(runRow) => parseJsonArray(runRow.transcript_json)
|
|
6116
|
+
);
|
|
6117
|
+
return {
|
|
6118
|
+
...summary,
|
|
6119
|
+
messages,
|
|
6120
|
+
transcript: renumberTranscript(runTranscript)
|
|
6121
|
+
};
|
|
6122
|
+
}
|
|
6123
|
+
function toSessionSummary(row) {
|
|
6124
|
+
const metadata = parseJsonValue(row.metadata_json);
|
|
6125
|
+
return {
|
|
6126
|
+
id: row.id,
|
|
6127
|
+
agentId: row.agent_id,
|
|
6128
|
+
...row.title === null ? {} : { title: row.title },
|
|
6129
|
+
createdAt: row.created_at,
|
|
6130
|
+
updatedAt: row.updated_at,
|
|
6131
|
+
messageCount: row.message_count,
|
|
6132
|
+
...metadata === void 0 ? {} : { metadata }
|
|
6133
|
+
};
|
|
6134
|
+
}
|
|
6135
|
+
function toSessionLog(row) {
|
|
6136
|
+
const metadata = parseJsonValue(row.metadata_json);
|
|
6137
|
+
return {
|
|
6138
|
+
id: row.id,
|
|
6139
|
+
sessionId: row.session_id,
|
|
6140
|
+
...row.run_id === null ? {} : { runId: row.run_id },
|
|
6141
|
+
sequence: row.sequence,
|
|
6142
|
+
timestamp: row.timestamp,
|
|
6143
|
+
level: row.level,
|
|
6144
|
+
category: row.category,
|
|
6145
|
+
event: row.event,
|
|
6146
|
+
message: row.message,
|
|
6147
|
+
...metadata === void 0 ? {} : { metadata }
|
|
6148
|
+
};
|
|
6149
|
+
}
|
|
6150
|
+
function toPipelineLog(row) {
|
|
6151
|
+
const metadata = parseJsonValue(row.metadata_json);
|
|
6152
|
+
return {
|
|
6153
|
+
id: row.id,
|
|
6154
|
+
pipelineId: row.pipeline_id,
|
|
6155
|
+
...row.run_id === null ? {} : { runId: row.run_id },
|
|
6156
|
+
sequence: row.sequence,
|
|
6157
|
+
timestamp: row.timestamp,
|
|
6158
|
+
level: row.level,
|
|
6159
|
+
category: row.category,
|
|
6160
|
+
event: row.event,
|
|
6161
|
+
message: row.message,
|
|
6162
|
+
...metadata === void 0 ? {} : { metadata }
|
|
6163
|
+
};
|
|
6164
|
+
}
|
|
6165
|
+
function toPipelineRun(row) {
|
|
6166
|
+
const output = parseJsonValue(row.output_json);
|
|
6167
|
+
const error = parseJsonValue(row.error_json);
|
|
6168
|
+
const metadata = parseJsonValue(row.metadata_json);
|
|
6169
|
+
return {
|
|
6170
|
+
runId: row.run_id,
|
|
6171
|
+
pipelineId: row.pipeline_id,
|
|
6172
|
+
status: row.status,
|
|
6173
|
+
input: JSON.parse(row.input_json),
|
|
6174
|
+
...output === void 0 ? {} : { output },
|
|
6175
|
+
...error === void 0 ? {} : { error },
|
|
6176
|
+
...metadata === void 0 ? {} : { metadata },
|
|
6177
|
+
startedAt: row.started_at,
|
|
6178
|
+
...row.ended_at === null ? {} : { endedAt: row.ended_at },
|
|
6179
|
+
...row.duration_ms === null ? {} : { durationMs: row.duration_ms }
|
|
6180
|
+
};
|
|
6181
|
+
}
|
|
6182
|
+
function messageParts(message) {
|
|
6183
|
+
if (message.role === "system") {
|
|
6184
|
+
return [{ type: "text", value: { type: "text", text: message.content } }];
|
|
6185
|
+
}
|
|
6186
|
+
return message.content.map((content) => ({
|
|
6187
|
+
type: content.type,
|
|
6188
|
+
value: content
|
|
6189
|
+
}));
|
|
6190
|
+
}
|
|
6191
|
+
function messageFromRows(row, partRows) {
|
|
6192
|
+
const parts = partRows.map((partRow) => JSON.parse(partRow.part_json));
|
|
6193
|
+
if (row.role === "system") {
|
|
6194
|
+
return { role: "system", content: systemContentFromParts(parts) };
|
|
6171
6195
|
}
|
|
6172
|
-
|
|
6173
|
-
|
|
6174
|
-
|
|
6196
|
+
if (row.role === "user") {
|
|
6197
|
+
return {
|
|
6198
|
+
role: "user",
|
|
6199
|
+
content: parts
|
|
6200
|
+
};
|
|
6175
6201
|
}
|
|
6176
|
-
|
|
6177
|
-
|
|
6178
|
-
|
|
6179
|
-
|
|
6180
|
-
|
|
6181
|
-
|
|
6182
|
-
|
|
6183
|
-
|
|
6184
|
-
|
|
6185
|
-
|
|
6186
|
-
|
|
6187
|
-
|
|
6188
|
-
}
|
|
6202
|
+
if (row.role === "assistant") {
|
|
6203
|
+
return {
|
|
6204
|
+
role: "assistant",
|
|
6205
|
+
...row.message_id === null ? {} : { id: row.message_id },
|
|
6206
|
+
content: parts
|
|
6207
|
+
};
|
|
6208
|
+
}
|
|
6209
|
+
if (row.role === "tool") {
|
|
6210
|
+
return {
|
|
6211
|
+
role: "tool",
|
|
6212
|
+
content: parts
|
|
6213
|
+
};
|
|
6214
|
+
}
|
|
6215
|
+
throw new Error(`Unsupported stored message role: ${row.role}`);
|
|
6189
6216
|
}
|
|
6190
|
-
function
|
|
6191
|
-
|
|
6217
|
+
function systemContentFromParts(parts) {
|
|
6218
|
+
const first = parts[0];
|
|
6219
|
+
if (typeof first === "object" && first !== null && "type" in first && first.type === "text" && "text" in first && typeof first.text === "string") {
|
|
6220
|
+
return first.text;
|
|
6221
|
+
}
|
|
6222
|
+
return "";
|
|
6192
6223
|
}
|
|
6193
|
-
function
|
|
6194
|
-
|
|
6195
|
-
|
|
6224
|
+
function guardAgainstLegacySessionSchema(db) {
|
|
6225
|
+
const columns = db.prepare("PRAGMA table_info('anvia_studio_sessions')").all();
|
|
6226
|
+
if (columns.some((column) => column.name === "messages_json")) {
|
|
6227
|
+
throw new Error(
|
|
6228
|
+
"Existing Studio SQLite DB uses the legacy messages_json schema. Delete or recreate the Studio SQLite DB to use normalized session messages."
|
|
6229
|
+
);
|
|
6230
|
+
}
|
|
6231
|
+
}
|
|
6232
|
+
function loadDatabaseSync() {
|
|
6233
|
+
if (DatabaseSync !== void 0) {
|
|
6234
|
+
return DatabaseSync;
|
|
6235
|
+
}
|
|
6236
|
+
try {
|
|
6237
|
+
({ DatabaseSync } = createRequire(import.meta.url)(
|
|
6238
|
+
"node:sqlite"
|
|
6239
|
+
));
|
|
6240
|
+
return DatabaseSync;
|
|
6241
|
+
} catch (error) {
|
|
6242
|
+
throw new Error(
|
|
6243
|
+
"The default Studio SQLite store requires Node.js with node:sqlite support. Provide custom Studio stores or disable persisted stores when running Studio in a runtime without node:sqlite.",
|
|
6244
|
+
{ cause: error }
|
|
6245
|
+
);
|
|
6196
6246
|
}
|
|
6247
|
+
}
|
|
6248
|
+
function toTrace(row) {
|
|
6249
|
+
const trace = parseJsonValue(row.trace_json);
|
|
6250
|
+
const input = parseJsonValue(row.input_json);
|
|
6197
6251
|
return {
|
|
6198
|
-
...
|
|
6199
|
-
|
|
6200
|
-
|
|
6201
|
-
|
|
6202
|
-
options: resolveMemoryOptions({ savePolicy: "message" })
|
|
6203
|
-
}
|
|
6204
|
-
})
|
|
6252
|
+
...toTraceSummary(row),
|
|
6253
|
+
...trace === void 0 ? {} : { trace },
|
|
6254
|
+
...input === void 0 ? {} : { input },
|
|
6255
|
+
observations: parseJsonArray(row.observations_json)
|
|
6205
6256
|
};
|
|
6206
6257
|
}
|
|
6207
|
-
function
|
|
6208
|
-
|
|
6209
|
-
|
|
6210
|
-
|
|
6258
|
+
function toTraceSummary(row) {
|
|
6259
|
+
const observations = parseJsonArray(row.observations_json);
|
|
6260
|
+
const error = parseJsonValue(row.error_json);
|
|
6261
|
+
const usage = parseJsonValue(row.usage_json);
|
|
6262
|
+
const metadata = parseJsonValue(row.metadata_json);
|
|
6211
6263
|
return {
|
|
6212
|
-
|
|
6213
|
-
|
|
6214
|
-
|
|
6215
|
-
|
|
6216
|
-
|
|
6217
|
-
|
|
6218
|
-
}
|
|
6264
|
+
id: row.id,
|
|
6265
|
+
sessionId: row.session_id,
|
|
6266
|
+
...row.name === null ? {} : { name: row.name },
|
|
6267
|
+
status: row.status,
|
|
6268
|
+
startedAt: row.started_at,
|
|
6269
|
+
...row.ended_at === null ? {} : { endedAt: row.ended_at },
|
|
6270
|
+
...row.duration_ms === null ? {} : { durationMs: row.duration_ms },
|
|
6271
|
+
...row.output === null ? {} : { output: row.output },
|
|
6272
|
+
...error === void 0 ? {} : { error },
|
|
6273
|
+
...usage === void 0 ? {} : { usage },
|
|
6274
|
+
...metadata === void 0 ? {} : { metadata },
|
|
6275
|
+
observationCount: observations.length
|
|
6219
6276
|
};
|
|
6220
6277
|
}
|
|
6221
|
-
function
|
|
6222
|
-
|
|
6223
|
-
|
|
6224
|
-
name: agent.name,
|
|
6225
|
-
description: agent.description,
|
|
6226
|
-
model: agent.model,
|
|
6227
|
-
instructions: agent.instructions,
|
|
6228
|
-
staticContext: agent.staticContext,
|
|
6229
|
-
temperature: agent.temperature,
|
|
6230
|
-
maxTokens: agent.maxTokens,
|
|
6231
|
-
additionalParams: agent.additionalParams,
|
|
6232
|
-
toolSet: agent.toolSet,
|
|
6233
|
-
toolChoice: agent.toolChoice,
|
|
6234
|
-
defaultMaxTurns: agent.defaultMaxTurns,
|
|
6235
|
-
hook: agent.hook,
|
|
6236
|
-
outputSchema: agent.outputSchema,
|
|
6237
|
-
observers: agent.observers,
|
|
6238
|
-
dynamicContexts: agent.dynamicContexts,
|
|
6239
|
-
dynamicTools: agent.dynamicTools,
|
|
6240
|
-
memory: agent.memory,
|
|
6241
|
-
...overrides
|
|
6242
|
-
});
|
|
6278
|
+
function parseJsonArray(value) {
|
|
6279
|
+
const parsed = JSON.parse(value);
|
|
6280
|
+
return Array.isArray(parsed) ? parsed : [];
|
|
6243
6281
|
}
|
|
6244
|
-
function
|
|
6245
|
-
|
|
6246
|
-
|
|
6247
|
-
|
|
6282
|
+
function parseJsonValue(value) {
|
|
6283
|
+
if (value === null) {
|
|
6284
|
+
return void 0;
|
|
6285
|
+
}
|
|
6286
|
+
return JSON.parse(value);
|
|
6248
6287
|
}
|
|
6249
|
-
function
|
|
6250
|
-
|
|
6251
|
-
|
|
6288
|
+
function studioRunId2(context) {
|
|
6289
|
+
const value = context.metadata?.studioRunId;
|
|
6290
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
6291
|
+
}
|
|
6292
|
+
function serializeJsonError2(error) {
|
|
6293
|
+
if (error instanceof Error) {
|
|
6294
|
+
return {
|
|
6295
|
+
name: error.name,
|
|
6296
|
+
message: error.message
|
|
6297
|
+
};
|
|
6252
6298
|
}
|
|
6253
|
-
if (
|
|
6254
|
-
return
|
|
6299
|
+
if (error === null || typeof error === "string" || typeof error === "number" || typeof error === "boolean") {
|
|
6300
|
+
return error;
|
|
6255
6301
|
}
|
|
6256
|
-
return
|
|
6257
|
-
async onCompletionCall(args) {
|
|
6258
|
-
const firstAction = await first.onCompletionCall?.(args);
|
|
6259
|
-
return firstAction?.type === "terminate" ? firstAction : await second.onCompletionCall?.(args) ?? void 0;
|
|
6260
|
-
},
|
|
6261
|
-
async onCompletionResponse(args) {
|
|
6262
|
-
const firstAction = await first.onCompletionResponse?.(args);
|
|
6263
|
-
return firstAction?.type === "terminate" ? firstAction : await second.onCompletionResponse?.(args) ?? void 0;
|
|
6264
|
-
},
|
|
6265
|
-
async onToolCall(args) {
|
|
6266
|
-
const firstAction = await first.onToolCall?.(args);
|
|
6267
|
-
if (firstAction?.type === "skip" || firstAction?.type === "terminate") {
|
|
6268
|
-
return firstAction;
|
|
6269
|
-
}
|
|
6270
|
-
if (firstAction?.type === "approval_request") {
|
|
6271
|
-
return await approvalRequestHandler(second)?.(args, firstAction) ?? firstAction;
|
|
6272
|
-
}
|
|
6273
|
-
const secondAction = await second.onToolCall?.(args);
|
|
6274
|
-
return secondAction ?? firstAction ?? void 0;
|
|
6275
|
-
},
|
|
6276
|
-
async onToolResult(args) {
|
|
6277
|
-
const firstAction = await first.onToolResult?.(args);
|
|
6278
|
-
return firstAction?.type === "terminate" ? firstAction : await second.onToolResult?.(args) ?? void 0;
|
|
6279
|
-
}
|
|
6280
|
-
});
|
|
6281
|
-
}
|
|
6282
|
-
function approvalRequestHandler(hook) {
|
|
6283
|
-
const candidate = hook;
|
|
6284
|
-
return typeof candidate.handleApprovalRequest === "function" ? candidate.handleApprovalRequest : void 0;
|
|
6302
|
+
return String(error);
|
|
6285
6303
|
}
|
|
6286
6304
|
export {
|
|
6287
6305
|
Studio,
|