@anvia/studio 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +9 -6
- package/dist/index.js +357 -73
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Message, JsonObject, AgentTraceOptions, PromptResponse, AgentStreamEvent, JsonValue, Usage, AgentTraceInfo, Agent, AgentObserver, AgentRunStartArgs, AgentRunObserver } from '@anvia/core';
|
|
1
|
+
import { Message, JsonObject, AgentTraceOptions, PromptResponse, AgentStreamEvent, JsonValue, Usage, AgentTraceInfo, Agent, MemoryStore, AgentObserver, AgentRunStartArgs, AgentRunObserver } from '@anvia/core';
|
|
2
2
|
import { Hono } from 'hono';
|
|
3
3
|
|
|
4
4
|
type StudioCapability = "agents" | "approvals" | "knowledge" | "observability" | "sessions" | "traces";
|
|
@@ -80,18 +80,21 @@ type StudioSessionListOptions = {
|
|
|
80
80
|
agentId?: string;
|
|
81
81
|
limit: number;
|
|
82
82
|
};
|
|
83
|
-
type
|
|
83
|
+
type StudioSessionRunStatus = "running" | "success" | "error";
|
|
84
|
+
type StudioSessionRunTranscriptInput = {
|
|
84
85
|
id: string;
|
|
86
|
+
runId: string;
|
|
85
87
|
title?: string;
|
|
86
|
-
messages: Message[];
|
|
87
88
|
transcript: StudioTranscriptEntry[];
|
|
89
|
+
status: StudioSessionRunStatus;
|
|
90
|
+
error?: JsonValue;
|
|
88
91
|
};
|
|
89
|
-
type StudioSessionStore = {
|
|
92
|
+
type StudioSessionStore = MemoryStore & {
|
|
90
93
|
readonly kind?: string;
|
|
91
94
|
listSessions(options: StudioSessionListOptions): StudioSessionSummary[] | Promise<StudioSessionSummary[]>;
|
|
92
95
|
createSession(input: StudioSessionCreateInput): StudioSessionSummary | Promise<StudioSessionSummary>;
|
|
93
96
|
getSession(id: string): StudioSession | undefined | Promise<StudioSession | undefined>;
|
|
94
|
-
|
|
97
|
+
saveSessionRunTranscript(input: StudioSessionRunTranscriptInput): StudioSession | undefined | Promise<StudioSession | undefined>;
|
|
95
98
|
deleteSession?(id: string): boolean | Promise<boolean>;
|
|
96
99
|
};
|
|
97
100
|
type StudioTraceStatus = "running" | "success" | "error";
|
|
@@ -341,4 +344,4 @@ type SqliteSessionStoreOptions = {
|
|
|
341
344
|
};
|
|
342
345
|
declare function createSqliteSessionStore(options?: SqliteSessionStoreOptions): StudioSessionStore & StudioTraceStore;
|
|
343
346
|
|
|
344
|
-
export { type AgentRunRequest, type AgentRunResponse, type AgentRunStreamEvent, type AnviaStudio, type SqliteSessionStoreOptions, Studio, type StudioAgent, type StudioAgentConfig, type StudioAgentKnowledgeConfig, type StudioCapability, type StudioCapabilityConfig, type StudioConfig, type StudioErrorCode, type StudioErrorResponse, type StudioKnowledgeEvidence, type StudioKnowledgeEvidenceDocument, type StudioKnowledgeSourceKind, type StudioKnowledgeSourceSummary, type StudioKnowledgeSummary, type StudioOptions, type StudioServeOptions, type StudioSession, type
|
|
347
|
+
export { type AgentRunRequest, type AgentRunResponse, type AgentRunStreamEvent, type AnviaStudio, type SqliteSessionStoreOptions, Studio, type StudioAgent, type StudioAgentConfig, type StudioAgentKnowledgeConfig, type StudioCapability, type StudioCapabilityConfig, type StudioConfig, type StudioErrorCode, type StudioErrorResponse, type StudioKnowledgeEvidence, type StudioKnowledgeEvidenceDocument, type StudioKnowledgeSourceKind, type StudioKnowledgeSourceSummary, type StudioKnowledgeSummary, type StudioOptions, type StudioServeOptions, type StudioSession, type StudioSessionCreateInput, type StudioSessionListOptions, type StudioSessionRunStatus, type StudioSessionRunTranscriptInput, type StudioSessionStore, type StudioSessionSummary, type StudioSessionTraceListOptions, type StudioStaticKnowledgeDocument, type StudioStores, type StudioToolApproval, type StudioToolApprovalDecision, type StudioToolApprovalRequestEvent, type StudioToolApprovalResultEvent, type StudioToolApprovalStatus, type StudioToolApprovalTranscript, type StudioToolQuestion, type StudioToolQuestionAnswer, type StudioToolQuestionChoice, type StudioToolQuestionPrompt, type StudioToolQuestionRequestEvent, type StudioToolQuestionResultEvent, type StudioToolQuestionStatus, type StudioToolQuestionTranscript, type StudioTrace, type StudioTraceListOptions, type StudioTraceObservation, type StudioTraceObservationKind, StudioTraceObserver, type StudioTraceObserverOptions, type StudioTraceStatus, type StudioTraceStore, type StudioTraceSummary, type StudioTranscriptChatEntry, type StudioTranscriptEntry, type StudioTranscriptReasoningEntry, type StudioTranscriptToolEntry, type StudioUiOptions, createSqliteSessionStore };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
// src/runtime/studio.ts
|
|
2
2
|
import {
|
|
3
3
|
Agent,
|
|
4
|
-
createHook as createHook3
|
|
4
|
+
createHook as createHook3,
|
|
5
|
+
Message,
|
|
6
|
+
resolveMemoryOptions
|
|
5
7
|
} from "@anvia/core";
|
|
6
8
|
import { serve } from "@hono/node-server";
|
|
7
9
|
import { Hono as HonoApp } from "hono";
|
|
@@ -544,15 +546,14 @@ var SqliteSessionStore = class {
|
|
|
544
546
|
};
|
|
545
547
|
}
|
|
546
548
|
getSession(id) {
|
|
547
|
-
const
|
|
548
|
-
|
|
549
|
-
`SELECT id, agent_id, title, metadata_json, messages_json, transcript_json, created_at, updated_at
|
|
550
|
-
FROM runner_sessions
|
|
551
|
-
WHERE id = $id`
|
|
552
|
-
).get({ $id: id });
|
|
553
|
-
return row === void 0 ? void 0 : toSession(row);
|
|
549
|
+
const row = this.getSessionRow(id);
|
|
550
|
+
return row === void 0 ? void 0 : toSession(row, this.listSessionRunRows(id));
|
|
554
551
|
}
|
|
555
|
-
|
|
552
|
+
load(context) {
|
|
553
|
+
const session = this.getSession(context.sessionId);
|
|
554
|
+
return Promise.resolve(session?.messages ?? []);
|
|
555
|
+
}
|
|
556
|
+
append(input) {
|
|
556
557
|
const db = this.database();
|
|
557
558
|
try {
|
|
558
559
|
db.exec("BEGIN IMMEDIATE");
|
|
@@ -560,39 +561,132 @@ var SqliteSessionStore = class {
|
|
|
560
561
|
`SELECT id, agent_id, title, metadata_json, messages_json, transcript_json, created_at, updated_at
|
|
561
562
|
FROM runner_sessions
|
|
562
563
|
WHERE id = $id`
|
|
563
|
-
).get({ $id: input.
|
|
564
|
+
).get({ $id: input.context.sessionId });
|
|
564
565
|
if (row === void 0) {
|
|
565
566
|
db.exec("ROLLBACK");
|
|
566
|
-
return
|
|
567
|
+
return Promise.resolve();
|
|
567
568
|
}
|
|
568
569
|
const current = toSession(row);
|
|
569
570
|
const messages = [...current.messages, ...input.messages];
|
|
570
|
-
const transcript = renumberTranscript([...current.transcript, ...input.transcript]);
|
|
571
|
-
const title = current.title ?? input.title;
|
|
572
571
|
const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
572
|
+
db.prepare(
|
|
573
|
+
`UPDATE runner_sessions
|
|
574
|
+
SET messages_json = $messages,
|
|
575
|
+
updated_at = $updatedAt
|
|
576
|
+
WHERE id = $id`
|
|
577
|
+
).run({
|
|
578
|
+
$id: input.context.sessionId,
|
|
579
|
+
$messages: JSON.stringify(messages),
|
|
580
|
+
$updatedAt: updatedAt
|
|
581
|
+
});
|
|
582
|
+
db.exec("COMMIT");
|
|
583
|
+
return Promise.resolve();
|
|
584
|
+
} catch (error) {
|
|
585
|
+
if (db.isTransaction) {
|
|
586
|
+
db.exec("ROLLBACK");
|
|
587
|
+
}
|
|
588
|
+
throw error;
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
clear(context) {
|
|
592
|
+
const db = this.database();
|
|
593
|
+
const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
594
|
+
try {
|
|
595
|
+
db.exec("BEGIN IMMEDIATE");
|
|
596
|
+
db.prepare(
|
|
597
|
+
`UPDATE runner_sessions
|
|
598
|
+
SET messages_json = '[]',
|
|
599
|
+
transcript_json = '[]',
|
|
600
|
+
updated_at = $updatedAt
|
|
601
|
+
WHERE id = $id`
|
|
602
|
+
).run({
|
|
603
|
+
$id: context.sessionId,
|
|
604
|
+
$updatedAt: updatedAt
|
|
605
|
+
});
|
|
606
|
+
db.prepare("DELETE FROM runner_session_runs WHERE session_id = $id").run({
|
|
607
|
+
$id: context.sessionId
|
|
608
|
+
});
|
|
609
|
+
db.exec("COMMIT");
|
|
610
|
+
return Promise.resolve();
|
|
611
|
+
} catch (error) {
|
|
612
|
+
if (db.isTransaction) {
|
|
613
|
+
db.exec("ROLLBACK");
|
|
614
|
+
}
|
|
615
|
+
throw error;
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
async recordError(input) {
|
|
619
|
+
const runId = studioRunId(input.context) ?? input.runId;
|
|
620
|
+
const existing = this.getSessionRun(input.context.sessionId, runId);
|
|
621
|
+
const transcript = existing === void 0 || parseJsonArray(existing.transcript_json).length === 0 ? transcriptFromMessagesFallback(input.messages) : parseJsonArray(existing.transcript_json);
|
|
622
|
+
await this.saveSessionRunTranscript({
|
|
623
|
+
id: input.context.sessionId,
|
|
624
|
+
runId,
|
|
625
|
+
transcript,
|
|
626
|
+
status: "error",
|
|
627
|
+
error: serializeJsonError(input.error)
|
|
628
|
+
});
|
|
629
|
+
}
|
|
630
|
+
saveSessionRunTranscript(input) {
|
|
631
|
+
const db = this.database();
|
|
632
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
633
|
+
try {
|
|
634
|
+
db.exec("BEGIN IMMEDIATE");
|
|
635
|
+
const row = this.getSessionRow(input.id);
|
|
636
|
+
if (row === void 0) {
|
|
637
|
+
db.exec("ROLLBACK");
|
|
638
|
+
return void 0;
|
|
639
|
+
}
|
|
640
|
+
const current = toSession(row, this.listSessionRunRows(input.id));
|
|
641
|
+
const title = current.title ?? input.title;
|
|
642
|
+
db.prepare(
|
|
643
|
+
`INSERT INTO runner_session_runs (
|
|
644
|
+
run_id,
|
|
645
|
+
session_id,
|
|
646
|
+
status,
|
|
647
|
+
title,
|
|
648
|
+
transcript_json,
|
|
649
|
+
error_json,
|
|
650
|
+
created_at,
|
|
651
|
+
updated_at
|
|
652
|
+
) VALUES (
|
|
653
|
+
$runId,
|
|
654
|
+
$sessionId,
|
|
655
|
+
$status,
|
|
656
|
+
$title,
|
|
657
|
+
$transcript,
|
|
658
|
+
$error,
|
|
659
|
+
$now,
|
|
660
|
+
$now
|
|
661
|
+
)
|
|
662
|
+
ON CONFLICT(run_id) DO UPDATE SET
|
|
663
|
+
status = excluded.status,
|
|
664
|
+
title = COALESCE(runner_session_runs.title, excluded.title),
|
|
665
|
+
transcript_json = excluded.transcript_json,
|
|
666
|
+
error_json = excluded.error_json,
|
|
667
|
+
updated_at = excluded.updated_at`
|
|
668
|
+
).run({
|
|
669
|
+
$runId: input.runId,
|
|
670
|
+
$sessionId: input.id,
|
|
671
|
+
$status: input.status,
|
|
672
|
+
$title: input.title ?? null,
|
|
673
|
+
$transcript: JSON.stringify(renumberTranscript(input.transcript)),
|
|
674
|
+
$error: input.error === void 0 ? null : JSON.stringify(input.error),
|
|
675
|
+
$now: now
|
|
676
|
+
});
|
|
573
677
|
db.prepare(
|
|
574
678
|
`UPDATE runner_sessions
|
|
575
679
|
SET title = $title,
|
|
576
|
-
messages_json = $messages,
|
|
577
|
-
transcript_json = $transcript,
|
|
578
680
|
updated_at = $updatedAt
|
|
579
681
|
WHERE id = $id`
|
|
580
682
|
).run({
|
|
581
683
|
$id: input.id,
|
|
582
684
|
$title: title ?? null,
|
|
583
|
-
$
|
|
584
|
-
$transcript: JSON.stringify(transcript),
|
|
585
|
-
$updatedAt: updatedAt
|
|
685
|
+
$updatedAt: now
|
|
586
686
|
});
|
|
587
687
|
db.exec("COMMIT");
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
...title === void 0 ? {} : { title },
|
|
591
|
-
updatedAt,
|
|
592
|
-
messageCount: messages.length,
|
|
593
|
-
messages,
|
|
594
|
-
transcript
|
|
595
|
-
};
|
|
688
|
+
const updated = this.getSession(input.id);
|
|
689
|
+
return updated;
|
|
596
690
|
} catch (error) {
|
|
597
691
|
if (db.isTransaction) {
|
|
598
692
|
db.exec("ROLLBACK");
|
|
@@ -605,6 +699,7 @@ var SqliteSessionStore = class {
|
|
|
605
699
|
try {
|
|
606
700
|
db.exec("BEGIN IMMEDIATE");
|
|
607
701
|
db.prepare("DELETE FROM runner_traces WHERE session_id = $id").run({ $id: id });
|
|
702
|
+
db.prepare("DELETE FROM runner_session_runs WHERE session_id = $id").run({ $id: id });
|
|
608
703
|
const result = db.prepare("DELETE FROM runner_sessions WHERE id = $id").run({ $id: id });
|
|
609
704
|
db.exec("COMMIT");
|
|
610
705
|
return Number(result.changes) > 0;
|
|
@@ -765,6 +860,19 @@ var SqliteSessionStore = class {
|
|
|
765
860
|
) STRICT;
|
|
766
861
|
CREATE INDEX IF NOT EXISTS runner_sessions_agent_updated_idx
|
|
767
862
|
ON runner_sessions(agent_id, updated_at DESC);
|
|
863
|
+
CREATE TABLE IF NOT EXISTS runner_session_runs (
|
|
864
|
+
run_id TEXT PRIMARY KEY,
|
|
865
|
+
session_id TEXT NOT NULL,
|
|
866
|
+
status TEXT NOT NULL,
|
|
867
|
+
title TEXT,
|
|
868
|
+
transcript_json TEXT NOT NULL,
|
|
869
|
+
error_json TEXT,
|
|
870
|
+
created_at TEXT NOT NULL,
|
|
871
|
+
updated_at TEXT NOT NULL,
|
|
872
|
+
FOREIGN KEY(session_id) REFERENCES runner_sessions(id) ON DELETE CASCADE
|
|
873
|
+
) STRICT;
|
|
874
|
+
CREATE INDEX IF NOT EXISTS runner_session_runs_session_created_idx
|
|
875
|
+
ON runner_session_runs(session_id, created_at ASC);
|
|
768
876
|
CREATE TABLE IF NOT EXISTS runner_traces (
|
|
769
877
|
id TEXT PRIMARY KEY,
|
|
770
878
|
session_id TEXT NOT NULL,
|
|
@@ -787,13 +895,39 @@ var SqliteSessionStore = class {
|
|
|
787
895
|
this.db = db;
|
|
788
896
|
return db;
|
|
789
897
|
}
|
|
898
|
+
getSessionRow(id) {
|
|
899
|
+
return this.database().prepare(
|
|
900
|
+
`SELECT id, agent_id, title, metadata_json, messages_json, transcript_json, created_at, updated_at
|
|
901
|
+
FROM runner_sessions
|
|
902
|
+
WHERE id = $id`
|
|
903
|
+
).get({ $id: id });
|
|
904
|
+
}
|
|
905
|
+
getSessionRun(sessionId, runId) {
|
|
906
|
+
return this.database().prepare(
|
|
907
|
+
`SELECT run_id, session_id, status, title, transcript_json, error_json, created_at, updated_at
|
|
908
|
+
FROM runner_session_runs
|
|
909
|
+
WHERE session_id = $sessionId AND run_id = $runId`
|
|
910
|
+
).get({ $sessionId: sessionId, $runId: runId });
|
|
911
|
+
}
|
|
912
|
+
listSessionRunRows(sessionId) {
|
|
913
|
+
return this.database().prepare(
|
|
914
|
+
`SELECT run_id, session_id, status, title, transcript_json, error_json, created_at, updated_at
|
|
915
|
+
FROM runner_session_runs
|
|
916
|
+
WHERE session_id = $sessionId
|
|
917
|
+
ORDER BY created_at ASC`
|
|
918
|
+
).all({ $sessionId: sessionId });
|
|
919
|
+
}
|
|
790
920
|
};
|
|
791
|
-
function toSession(row) {
|
|
921
|
+
function toSession(row, runRows = []) {
|
|
792
922
|
const summary = toSessionSummary(row);
|
|
923
|
+
const legacyTranscript = parseJsonArray(row.transcript_json);
|
|
924
|
+
const runTranscript = runRows.flatMap(
|
|
925
|
+
(runRow) => parseJsonArray(runRow.transcript_json)
|
|
926
|
+
);
|
|
793
927
|
return {
|
|
794
928
|
...summary,
|
|
795
929
|
messages: parseJsonArray(row.messages_json),
|
|
796
|
-
transcript: renumberTranscript(
|
|
930
|
+
transcript: renumberTranscript([...legacyTranscript, ...runTranscript])
|
|
797
931
|
};
|
|
798
932
|
}
|
|
799
933
|
function toSessionSummary(row) {
|
|
@@ -852,6 +986,96 @@ function parseJsonValue(value) {
|
|
|
852
986
|
function renumberTranscript(entries) {
|
|
853
987
|
return entries.map((entry, entryId) => ({ ...entry, entryId }));
|
|
854
988
|
}
|
|
989
|
+
function studioRunId(context) {
|
|
990
|
+
const value = context.metadata?.studioRunId;
|
|
991
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
992
|
+
}
|
|
993
|
+
function serializeJsonError(error) {
|
|
994
|
+
if (error instanceof Error) {
|
|
995
|
+
return {
|
|
996
|
+
name: error.name,
|
|
997
|
+
message: error.message
|
|
998
|
+
};
|
|
999
|
+
}
|
|
1000
|
+
if (error === null || typeof error === "string" || typeof error === "number" || typeof error === "boolean") {
|
|
1001
|
+
return error;
|
|
1002
|
+
}
|
|
1003
|
+
return String(error);
|
|
1004
|
+
}
|
|
1005
|
+
function transcriptFromMessagesFallback(messages) {
|
|
1006
|
+
const transcript = [];
|
|
1007
|
+
for (const message of messages) {
|
|
1008
|
+
if (message.role === "system") {
|
|
1009
|
+
continue;
|
|
1010
|
+
}
|
|
1011
|
+
if (message.role === "user") {
|
|
1012
|
+
for (const content of message.content) {
|
|
1013
|
+
if (content.type === "text") {
|
|
1014
|
+
transcript.push({
|
|
1015
|
+
entryId: transcript.length,
|
|
1016
|
+
kind: "message",
|
|
1017
|
+
role: "user",
|
|
1018
|
+
text: content.text
|
|
1019
|
+
});
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
continue;
|
|
1023
|
+
}
|
|
1024
|
+
if (message.role === "tool") {
|
|
1025
|
+
for (const content of message.content) {
|
|
1026
|
+
transcript.push({
|
|
1027
|
+
entryId: transcript.length,
|
|
1028
|
+
kind: "tool",
|
|
1029
|
+
toolName: "tool_result",
|
|
1030
|
+
callId: content.callId ?? content.id,
|
|
1031
|
+
result: content.content.map((item) => "text" in item ? item.text : "[image]").join("\n")
|
|
1032
|
+
});
|
|
1033
|
+
}
|
|
1034
|
+
continue;
|
|
1035
|
+
}
|
|
1036
|
+
for (const content of message.content) {
|
|
1037
|
+
if (content.type === "text") {
|
|
1038
|
+
appendAssistantTranscriptText(transcript, content.text);
|
|
1039
|
+
} else if (content.type === "reasoning") {
|
|
1040
|
+
transcript.push({
|
|
1041
|
+
entryId: transcript.length,
|
|
1042
|
+
kind: "reasoning",
|
|
1043
|
+
...content.id === void 0 ? {} : { reasoningId: content.id },
|
|
1044
|
+
text: content.text
|
|
1045
|
+
});
|
|
1046
|
+
} else if (content.type === "tool_call") {
|
|
1047
|
+
transcript.push({
|
|
1048
|
+
entryId: transcript.length,
|
|
1049
|
+
kind: "tool",
|
|
1050
|
+
toolName: content.function.name,
|
|
1051
|
+
callId: content.callId ?? content.id,
|
|
1052
|
+
args: formatJson(content.function.arguments)
|
|
1053
|
+
});
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
return transcript;
|
|
1058
|
+
}
|
|
1059
|
+
function appendAssistantTranscriptText(transcript, text) {
|
|
1060
|
+
const last = transcript.at(-1);
|
|
1061
|
+
if (last?.kind === "message" && last.role === "assistant") {
|
|
1062
|
+
last.text = `${last.text}${text}`;
|
|
1063
|
+
return;
|
|
1064
|
+
}
|
|
1065
|
+
transcript.push({
|
|
1066
|
+
entryId: transcript.length,
|
|
1067
|
+
kind: "message",
|
|
1068
|
+
role: "assistant",
|
|
1069
|
+
text
|
|
1070
|
+
});
|
|
1071
|
+
}
|
|
1072
|
+
function formatJson(value) {
|
|
1073
|
+
try {
|
|
1074
|
+
return JSON.stringify(value, null, 2);
|
|
1075
|
+
} catch {
|
|
1076
|
+
return String(value);
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
855
1079
|
|
|
856
1080
|
// src/runtime/shared.ts
|
|
857
1081
|
function resolveStores(options) {
|
|
@@ -1823,22 +2047,42 @@ function traceForRun(trace, agentId, session) {
|
|
|
1823
2047
|
...trace?.sessionId !== void 0 ? { sessionId: trace.sessionId } : session === void 0 ? {} : { sessionId: session.id }
|
|
1824
2048
|
};
|
|
1825
2049
|
}
|
|
1826
|
-
async function*
|
|
2050
|
+
async function* persistStreamingSessionTranscript(props) {
|
|
1827
2051
|
const transcript = [messageToTranscriptEntry(props.message, 0)];
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
2052
|
+
const title = optionalTitle(props.message);
|
|
2053
|
+
await props.store.saveSessionRunTranscript({
|
|
2054
|
+
id: props.session.id,
|
|
2055
|
+
runId: props.runId,
|
|
2056
|
+
...title,
|
|
2057
|
+
transcript,
|
|
2058
|
+
status: "running"
|
|
2059
|
+
});
|
|
2060
|
+
try {
|
|
2061
|
+
for await (const event of props.stream) {
|
|
2062
|
+
acceptTranscriptStreamEvent(transcript, event);
|
|
2063
|
+
const nextSession = await props.store.saveSessionRunTranscript({
|
|
1832
2064
|
id: props.session.id,
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
transcript
|
|
2065
|
+
runId: props.runId,
|
|
2066
|
+
...title,
|
|
2067
|
+
transcript,
|
|
2068
|
+
status: event.type === "final" ? "success" : event.type === "error" ? "error" : "running",
|
|
2069
|
+
...event.type === "error" ? { error: serializeError2(event.error) } : {}
|
|
1836
2070
|
});
|
|
1837
2071
|
if (nextSession === void 0) {
|
|
1838
2072
|
throw new Error("Session not found");
|
|
1839
2073
|
}
|
|
2074
|
+
yield event;
|
|
1840
2075
|
}
|
|
1841
|
-
|
|
2076
|
+
} catch (error) {
|
|
2077
|
+
await props.store.saveSessionRunTranscript({
|
|
2078
|
+
id: props.session.id,
|
|
2079
|
+
runId: props.runId,
|
|
2080
|
+
...title,
|
|
2081
|
+
transcript,
|
|
2082
|
+
status: "error",
|
|
2083
|
+
error: serializeError2(error)
|
|
2084
|
+
});
|
|
2085
|
+
throw error;
|
|
1842
2086
|
}
|
|
1843
2087
|
}
|
|
1844
2088
|
function acceptTranscriptStreamEvent(transcript, event) {
|
|
@@ -1854,7 +2098,7 @@ function acceptTranscriptStreamEvent(transcript, event) {
|
|
|
1854
2098
|
kind: "tool",
|
|
1855
2099
|
toolName: event.toolCall.function.name,
|
|
1856
2100
|
callId: event.toolCall.callId ?? event.toolCall.id,
|
|
1857
|
-
args:
|
|
2101
|
+
args: formatJson2(event.toolCall.function.arguments)
|
|
1858
2102
|
});
|
|
1859
2103
|
}
|
|
1860
2104
|
if (event.type === "tool_result") {
|
|
@@ -1987,7 +2231,7 @@ function transcriptFromMessages(messages) {
|
|
|
1987
2231
|
kind: "tool",
|
|
1988
2232
|
toolName: content.function.name,
|
|
1989
2233
|
callId: content.callId ?? content.id,
|
|
1990
|
-
args:
|
|
2234
|
+
args: formatJson2(content.function.arguments)
|
|
1991
2235
|
});
|
|
1992
2236
|
}
|
|
1993
2237
|
}
|
|
@@ -2073,7 +2317,7 @@ function extractMessageText(message) {
|
|
|
2073
2317
|
return [item.text];
|
|
2074
2318
|
}
|
|
2075
2319
|
if (item.type === "tool_call") {
|
|
2076
|
-
return [`${item.function.name}(${
|
|
2320
|
+
return [`${item.function.name}(${formatJson2(item.function.arguments)})`];
|
|
2077
2321
|
}
|
|
2078
2322
|
if (item.type === "tool_result") {
|
|
2079
2323
|
return item.content.map((result) => "text" in result ? result.text : "[image]");
|
|
@@ -2081,7 +2325,7 @@ function extractMessageText(message) {
|
|
|
2081
2325
|
return [];
|
|
2082
2326
|
}).join("\n");
|
|
2083
2327
|
}
|
|
2084
|
-
function
|
|
2328
|
+
function formatJson2(value) {
|
|
2085
2329
|
try {
|
|
2086
2330
|
return JSON.stringify(value, null, 2);
|
|
2087
2331
|
} catch {
|
|
@@ -2408,9 +2652,7 @@ function agentMetadata(agent) {
|
|
|
2408
2652
|
}
|
|
2409
2653
|
function createStudioApp(options) {
|
|
2410
2654
|
const stores = resolveStores(options);
|
|
2411
|
-
const agents = normalizeAgents(options.agents).map(
|
|
2412
|
-
(agent) => withStudioTraceObserver(agent, stores.traces)
|
|
2413
|
-
);
|
|
2655
|
+
const agents = normalizeAgents(options.agents).map((agent) => withStudioSessionMemory(agent, stores.sessions)).map((agent) => withStudioTraceObserver(agent, stores.traces));
|
|
2414
2656
|
const agentMap = new Map(agents.map((agent) => [agent.id, agent]));
|
|
2415
2657
|
const approvalRuntime = createApprovalRuntime();
|
|
2416
2658
|
const questionRuntime = createQuestionRuntime();
|
|
@@ -2469,12 +2711,14 @@ function createStudioApp(options) {
|
|
|
2469
2711
|
return errorResponse(c, 400, "bad_request", "Session belongs to another agent");
|
|
2470
2712
|
}
|
|
2471
2713
|
const runId = globalThis.crypto.randomUUID();
|
|
2472
|
-
const
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
}
|
|
2714
|
+
const memoryMetadata = {
|
|
2715
|
+
agentId,
|
|
2716
|
+
...body.metadata ?? {},
|
|
2717
|
+
studioRunId: runId
|
|
2718
|
+
};
|
|
2719
|
+
const request = session !== void 0 ? agent.agent.session(session.id, { metadata: memoryMetadata }).prompt(body.message) : agent.agent.prompt(
|
|
2720
|
+
body.history !== void 0 ? [...body.history, normalizePromptMessage(body.message)] : body.message
|
|
2721
|
+
);
|
|
2478
2722
|
if (body.maxTurns !== void 0) {
|
|
2479
2723
|
request.maxTurns(body.maxTurns);
|
|
2480
2724
|
}
|
|
@@ -2512,11 +2756,12 @@ function createStudioApp(options) {
|
|
|
2512
2756
|
request.requestHook(effectiveHook);
|
|
2513
2757
|
}
|
|
2514
2758
|
const runStream = mergeRunAndApprovalEvents(request.stream(), runtimeEvents);
|
|
2515
|
-
const stream = session === void 0 || stores.sessions === void 0 ? runStream :
|
|
2759
|
+
const stream = session === void 0 || stores.sessions === void 0 ? runStream : persistStreamingSessionTranscript({
|
|
2516
2760
|
stream: runStream,
|
|
2517
2761
|
store: stores.sessions,
|
|
2518
2762
|
session,
|
|
2519
|
-
message: body.message
|
|
2763
|
+
message: body.message,
|
|
2764
|
+
runId
|
|
2520
2765
|
});
|
|
2521
2766
|
return streamAgentRunEvents(c, stream);
|
|
2522
2767
|
}
|
|
@@ -2544,15 +2789,30 @@ function createStudioApp(options) {
|
|
|
2544
2789
|
}
|
|
2545
2790
|
const response = await request.send();
|
|
2546
2791
|
if (session !== void 0 && stores.sessions !== void 0) {
|
|
2547
|
-
await stores.sessions.
|
|
2792
|
+
await stores.sessions.saveSessionRunTranscript({
|
|
2548
2793
|
id: session.id,
|
|
2794
|
+
runId,
|
|
2549
2795
|
...optionalTitle(body.message),
|
|
2550
|
-
|
|
2551
|
-
|
|
2796
|
+
transcript: transcriptFromMessages(response.messages),
|
|
2797
|
+
status: "success"
|
|
2552
2798
|
});
|
|
2553
2799
|
}
|
|
2554
2800
|
return c.json(response);
|
|
2555
2801
|
} catch (error) {
|
|
2802
|
+
if (session !== void 0 && stores.sessions !== void 0) {
|
|
2803
|
+
const messages = await stores.sessions.load({
|
|
2804
|
+
sessionId: session.id,
|
|
2805
|
+
metadata: memoryMetadata
|
|
2806
|
+
});
|
|
2807
|
+
await stores.sessions.saveSessionRunTranscript({
|
|
2808
|
+
id: session.id,
|
|
2809
|
+
runId,
|
|
2810
|
+
...optionalTitle(body.message),
|
|
2811
|
+
transcript: transcriptFromMessages(messages.slice(session.messageCount)),
|
|
2812
|
+
status: "error",
|
|
2813
|
+
error: serializeError2(error)
|
|
2814
|
+
});
|
|
2815
|
+
}
|
|
2556
2816
|
return errorResponse(c, 500, "internal_error", "Agent run failed", serializeError2(error));
|
|
2557
2817
|
}
|
|
2558
2818
|
});
|
|
@@ -2584,36 +2844,60 @@ function createStudioApp(options) {
|
|
|
2584
2844
|
...stores.traces === void 0 ? {} : { traceStore: stores.traces }
|
|
2585
2845
|
};
|
|
2586
2846
|
}
|
|
2847
|
+
function normalizePromptMessage(message) {
|
|
2848
|
+
return typeof message === "string" ? Message.user(message) : message;
|
|
2849
|
+
}
|
|
2850
|
+
function withStudioSessionMemory(studioAgent, sessionStore) {
|
|
2851
|
+
if (sessionStore === void 0) {
|
|
2852
|
+
return studioAgent;
|
|
2853
|
+
}
|
|
2854
|
+
return {
|
|
2855
|
+
...studioAgent,
|
|
2856
|
+
agent: cloneAgent(studioAgent.agent, {
|
|
2857
|
+
memory: {
|
|
2858
|
+
store: sessionStore,
|
|
2859
|
+
options: resolveMemoryOptions({ savePolicy: "message" })
|
|
2860
|
+
}
|
|
2861
|
+
})
|
|
2862
|
+
};
|
|
2863
|
+
}
|
|
2587
2864
|
function withStudioTraceObserver(studioAgent, traceStore) {
|
|
2588
2865
|
if (traceStore === void 0 || hasStudioTraceObserver(studioAgent.agent)) {
|
|
2589
2866
|
return studioAgent;
|
|
2590
2867
|
}
|
|
2591
2868
|
return {
|
|
2592
2869
|
...studioAgent,
|
|
2593
|
-
agent:
|
|
2594
|
-
id: studioAgent.agent.id,
|
|
2595
|
-
name: studioAgent.agent.name,
|
|
2596
|
-
description: studioAgent.agent.description,
|
|
2597
|
-
model: studioAgent.agent.model,
|
|
2598
|
-
instructions: studioAgent.agent.instructions,
|
|
2599
|
-
staticContext: studioAgent.agent.staticContext,
|
|
2600
|
-
temperature: studioAgent.agent.temperature,
|
|
2601
|
-
maxTokens: studioAgent.agent.maxTokens,
|
|
2602
|
-
additionalParams: studioAgent.agent.additionalParams,
|
|
2603
|
-
toolSet: studioAgent.agent.toolSet,
|
|
2604
|
-
toolChoice: studioAgent.agent.toolChoice,
|
|
2605
|
-
defaultMaxTurns: studioAgent.agent.defaultMaxTurns,
|
|
2606
|
-
hook: studioAgent.agent.hook,
|
|
2607
|
-
outputSchema: studioAgent.agent.outputSchema,
|
|
2870
|
+
agent: cloneAgent(studioAgent.agent, {
|
|
2608
2871
|
observers: [
|
|
2609
2872
|
...studioAgent.agent.observers,
|
|
2610
2873
|
{ observer: new StudioTraceObserver({ store: traceStore }) }
|
|
2611
|
-
]
|
|
2612
|
-
dynamicContexts: studioAgent.agent.dynamicContexts,
|
|
2613
|
-
dynamicTools: studioAgent.agent.dynamicTools
|
|
2874
|
+
]
|
|
2614
2875
|
})
|
|
2615
2876
|
};
|
|
2616
2877
|
}
|
|
2878
|
+
function cloneAgent(agent, overrides = {}) {
|
|
2879
|
+
return new Agent({
|
|
2880
|
+
id: agent.id,
|
|
2881
|
+
name: agent.name,
|
|
2882
|
+
description: agent.description,
|
|
2883
|
+
model: agent.model,
|
|
2884
|
+
instructions: agent.instructions,
|
|
2885
|
+
staticContext: agent.staticContext,
|
|
2886
|
+
temperature: agent.temperature,
|
|
2887
|
+
maxTokens: agent.maxTokens,
|
|
2888
|
+
additionalParams: agent.additionalParams,
|
|
2889
|
+
toolSet: agent.toolSet,
|
|
2890
|
+
toolChoice: agent.toolChoice,
|
|
2891
|
+
defaultMaxTurns: agent.defaultMaxTurns,
|
|
2892
|
+
hook: agent.hook,
|
|
2893
|
+
outputSchema: agent.outputSchema,
|
|
2894
|
+
observers: agent.observers,
|
|
2895
|
+
dynamicContexts: agent.dynamicContexts,
|
|
2896
|
+
dynamicTools: agent.dynamicTools,
|
|
2897
|
+
memory: agent.memory,
|
|
2898
|
+
...overrides
|
|
2899
|
+
});
|
|
2900
|
+
}
|
|
2617
2901
|
function hasStudioTraceObserver(agent) {
|
|
2618
2902
|
return agent.observers.some(
|
|
2619
2903
|
(registration) => registration.observer instanceof StudioTraceObserver
|