@truefoundry/assistant-ui-runtime 0.1.4 → 0.1.6-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +374 -190
- package/dist/index.d.ts +32 -29
- package/dist/index.js +334 -241
- package/dist/index.js.map +1 -1
- package/dist/plugins/truefoundry-agent-server-adapter/index.d.ts +30 -0
- package/dist/plugins/truefoundry-agent-server-adapter/index.js +198 -0
- package/dist/plugins/truefoundry-agent-server-adapter/index.js.map +1 -0
- package/dist/types-VUBzoJT2.d.ts +462 -0
- package/package.json +12 -4
- package/src/askUserQuestion.ts +3 -3
- package/src/collectPending.ts +1 -1
- package/src/convertTurnMessages.test.ts +141 -196
- package/src/convertTurnMessages.ts +131 -77
- package/src/createSubAgent.ts +1 -1
- package/src/draftAgentConfig.test.ts +26 -29
- package/src/extractTurnUserText.ts +1 -1
- package/src/foldPeerThreads.test.ts +1 -1
- package/src/foldPeerThreads.ts +3 -2
- package/src/index.ts +39 -4
- package/src/listPages.ts +21 -0
- package/src/loadSessionSnapshot.test.ts +9 -8
- package/src/loadSessionSnapshot.ts +9 -14
- package/src/mcpAuth.ts +6 -3
- package/src/messageCustomMetadata.ts +1 -1
- package/src/modelMessageContent.ts +1 -1
- package/src/modelMessageImageContent.test.ts +1 -1
- package/src/modelMessageImageContent.ts +7 -6
- package/src/plugins/truefoundry-agent-server-adapter/index.ts +285 -0
- package/src/private/agentSpec.ts +8 -3
- package/src/private/draftSessionBridge.ts +14 -13
- package/src/private/truefoundryDraftThreadListAdapter.test.ts +44 -49
- package/src/private/truefoundryDraftThreadListAdapter.ts +22 -16
- package/src/requiredActionInputs.ts +1 -1
- package/src/requiredActionsFromActiveUpdate.test.ts +1 -1
- package/src/server/eventUtils.ts +120 -0
- package/src/server/events.ts +246 -0
- package/src/server/index.ts +66 -0
- package/src/server/types.ts +313 -0
- package/src/sessionSnapshot.ts +1 -1
- package/src/sessions.ts +5 -21
- package/src/streamTurn.test.ts +175 -158
- package/src/streamTurn.ts +51 -57
- package/src/toolApproval.ts +4 -4
- package/src/toolResponse.ts +4 -4
- package/src/truefoundryExtras.ts +1 -1
- package/src/truefoundryOwnedSessionsThreadListAdapter.test.ts +26 -29
- package/src/truefoundryOwnedSessionsThreadListAdapter.ts +18 -23
- package/src/truefoundryThreadListAdapter.test.ts +16 -18
- package/src/truefoundryThreadListAdapter.ts +9 -9
- package/src/turnEventHelpers.ts +1 -1
- package/src/types.ts +2 -16
- package/src/useTrueFoundryAgentMessages.test.tsx +38 -70
- package/src/useTrueFoundryAgentMessages.ts +33 -45
- package/src/useTrueFoundryAgentRuntime.ts +11 -28
- package/src/private/bindDraftAgentSession.test.ts +0 -54
- package/src/private/bindDraftAgentSession.ts +0 -28
- package/src/private/getGatewayFromPrivateClient.ts +0 -13
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, expect, it, vi } from "vitest";
|
|
2
2
|
|
|
3
|
-
import type {
|
|
3
|
+
import type { AgentChatServer, Session } from "../server/index.js";
|
|
4
4
|
|
|
5
5
|
import { createTrueFoundryDraftThreadListAdapter } from "./truefoundryDraftThreadListAdapter.js";
|
|
6
6
|
import type { AgentSpec } from "./agentSpec.js";
|
|
@@ -10,62 +10,57 @@ const defaultAgentSpec: AgentSpec = {
|
|
|
10
10
|
instructions: "You are helpful.",
|
|
11
11
|
};
|
|
12
12
|
|
|
13
|
-
function mockDraft(id: string, title: string | undefined, updatedAt: string) {
|
|
13
|
+
function mockDraft(id: string, title: string | undefined, updatedAt: string): Session {
|
|
14
14
|
return {
|
|
15
|
-
type: "session/draft" as const,
|
|
16
15
|
id,
|
|
17
16
|
agentSpec: defaultAgentSpec,
|
|
18
17
|
title,
|
|
19
|
-
createdBySubject: { type: "user" as const, id: "u1" },
|
|
20
18
|
createdAt: updatedAt,
|
|
21
19
|
updatedAt,
|
|
20
|
+
isMutable: true,
|
|
22
21
|
};
|
|
23
22
|
}
|
|
24
23
|
|
|
25
|
-
function mockDraftListPage(
|
|
26
|
-
drafts: ReturnType<typeof mockDraft>[],
|
|
27
|
-
nextPageToken?: string,
|
|
28
|
-
) {
|
|
24
|
+
function mockDraftListPage(drafts: Session[], nextPageToken?: string) {
|
|
29
25
|
return {
|
|
30
26
|
data: drafts,
|
|
31
|
-
|
|
32
|
-
pagination: {
|
|
33
|
-
nextPageToken,
|
|
34
|
-
limit: 20,
|
|
35
|
-
},
|
|
36
|
-
},
|
|
27
|
+
...(nextPageToken != null ? { nextPageToken } : {}),
|
|
37
28
|
};
|
|
38
29
|
}
|
|
39
30
|
|
|
31
|
+
function mockServer(partial: Partial<AgentChatServer>): AgentChatServer {
|
|
32
|
+
return partial as AgentChatServer;
|
|
33
|
+
}
|
|
34
|
+
|
|
40
35
|
describe("createTrueFoundryDraftThreadListAdapter", () => {
|
|
41
36
|
it("lists draft sessions with pagination cursor", async () => {
|
|
42
|
-
const
|
|
37
|
+
const listSessions = vi.fn().mockResolvedValue(
|
|
43
38
|
mockDraftListPage(
|
|
44
39
|
[mockDraft("d1", "My draft", "2026-06-30T10:00:00.000Z")],
|
|
45
40
|
"page-2",
|
|
46
41
|
),
|
|
47
42
|
);
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
43
|
+
const server = mockServer({
|
|
44
|
+
listSessions,
|
|
45
|
+
createSession: vi.fn(),
|
|
46
|
+
getSession: vi.fn(),
|
|
47
|
+
});
|
|
53
48
|
|
|
54
49
|
const adapter = createTrueFoundryDraftThreadListAdapter({
|
|
55
|
-
|
|
50
|
+
server,
|
|
56
51
|
defaultAgentSpec,
|
|
57
52
|
});
|
|
58
53
|
|
|
59
54
|
const result = await adapter.list();
|
|
60
55
|
|
|
61
|
-
expect(
|
|
56
|
+
expect(listSessions).toHaveBeenCalledWith(
|
|
62
57
|
expect.objectContaining({
|
|
63
58
|
limit: 20,
|
|
64
59
|
pageToken: undefined,
|
|
65
60
|
startTimestamp: expect.any(String),
|
|
66
61
|
}),
|
|
67
62
|
);
|
|
68
|
-
expect(
|
|
63
|
+
expect(listSessions).toHaveBeenCalledWith(
|
|
69
64
|
expect.not.objectContaining({ agentName: expect.anything() }),
|
|
70
65
|
);
|
|
71
66
|
expect(result.threads).toEqual([
|
|
@@ -80,23 +75,23 @@ describe("createTrueFoundryDraftThreadListAdapter", () => {
|
|
|
80
75
|
});
|
|
81
76
|
|
|
82
77
|
it("creates a draft session on initialize", async () => {
|
|
83
|
-
const
|
|
78
|
+
const createSession = vi.fn().mockResolvedValue(
|
|
84
79
|
mockDraft("d-new", undefined, "2026-06-30T12:00:00.000Z"),
|
|
85
80
|
);
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}
|
|
81
|
+
const server = mockServer({
|
|
82
|
+
listSessions: vi.fn(),
|
|
83
|
+
createSession,
|
|
84
|
+
getSession: vi.fn(),
|
|
85
|
+
});
|
|
91
86
|
|
|
92
87
|
const adapter = createTrueFoundryDraftThreadListAdapter({
|
|
93
|
-
|
|
88
|
+
server,
|
|
94
89
|
defaultAgentSpec,
|
|
95
90
|
});
|
|
96
91
|
|
|
97
92
|
const result = await adapter.initialize("local-thread-id");
|
|
98
93
|
|
|
99
|
-
expect(
|
|
94
|
+
expect(createSession).toHaveBeenCalledWith({ agentSpec: defaultAgentSpec });
|
|
100
95
|
expect(result).toEqual({ remoteId: "d-new", externalId: undefined });
|
|
101
96
|
});
|
|
102
97
|
|
|
@@ -104,47 +99,47 @@ describe("createTrueFoundryDraftThreadListAdapter", () => {
|
|
|
104
99
|
const liveAgentSpec: AgentSpec = {
|
|
105
100
|
model: { name: "anthropic/claude-opus-4-8" },
|
|
106
101
|
instructions: "You are helpful.",
|
|
107
|
-
mcpServers: [{
|
|
108
|
-
skills: [{
|
|
102
|
+
mcpServers: [{ id: "github", name: "github" }],
|
|
103
|
+
skills: [{ id: "skill-a", name: "skill-a" }],
|
|
109
104
|
};
|
|
110
|
-
const
|
|
105
|
+
const createSession = vi.fn().mockResolvedValue(
|
|
111
106
|
mockDraft("d-new", undefined, "2026-06-30T12:00:00.000Z"),
|
|
112
107
|
);
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}
|
|
108
|
+
const server = mockServer({
|
|
109
|
+
listSessions: vi.fn(),
|
|
110
|
+
createSession,
|
|
111
|
+
getSession: vi.fn(),
|
|
112
|
+
});
|
|
118
113
|
|
|
119
114
|
const adapter = createTrueFoundryDraftThreadListAdapter({
|
|
120
|
-
|
|
115
|
+
server,
|
|
121
116
|
defaultAgentSpec,
|
|
122
117
|
getAgentSpec: () => liveAgentSpec,
|
|
123
118
|
});
|
|
124
119
|
|
|
125
120
|
await adapter.initialize("local-thread-id");
|
|
126
121
|
|
|
127
|
-
expect(
|
|
122
|
+
expect(createSession).toHaveBeenCalledWith({ agentSpec: liveAgentSpec });
|
|
128
123
|
});
|
|
129
124
|
|
|
130
125
|
it("falls back to model name for title when draft has no title", async () => {
|
|
131
|
-
const
|
|
126
|
+
const getSession = vi.fn().mockResolvedValue(
|
|
132
127
|
mockDraft("d1", undefined, "2026-06-30T10:00:00.000Z"),
|
|
133
128
|
);
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
129
|
+
const server = mockServer({
|
|
130
|
+
listSessions: vi.fn(),
|
|
131
|
+
createSession: vi.fn(),
|
|
132
|
+
getSession,
|
|
133
|
+
});
|
|
139
134
|
|
|
140
135
|
const adapter = createTrueFoundryDraftThreadListAdapter({
|
|
141
|
-
|
|
136
|
+
server,
|
|
142
137
|
defaultAgentSpec,
|
|
143
138
|
});
|
|
144
139
|
|
|
145
140
|
const result = await adapter.fetch("d1");
|
|
146
141
|
|
|
147
|
-
expect(
|
|
142
|
+
expect(getSession).toHaveBeenCalledWith({ sessionId: "d1" });
|
|
148
143
|
expect(result.title).toBe("anthropic/claude-sonnet-4-6");
|
|
149
144
|
});
|
|
150
145
|
});
|
|
@@ -1,52 +1,58 @@
|
|
|
1
1
|
import type { RemoteThreadListAdapter } from "@assistant-ui/core";
|
|
2
|
-
import type { PrivateAgentSessionClient } from "truefoundry-gateway-sdk/agents/private";
|
|
3
2
|
|
|
3
|
+
import type { AgentChatServer } from "../server/types.js";
|
|
4
4
|
import { draftSessionTitle, type AgentSpec } from "./agentSpec.js";
|
|
5
5
|
import { sessionListStartTimestamp } from "../sessionListStartTimestamp.js";
|
|
6
6
|
|
|
7
7
|
const THREAD_LIST_PAGE_SIZE = 20;
|
|
8
8
|
|
|
9
9
|
export function createTrueFoundryDraftThreadListAdapter(options: {
|
|
10
|
-
|
|
10
|
+
server: AgentChatServer;
|
|
11
11
|
defaultAgentSpec: AgentSpec;
|
|
12
12
|
getAgentSpec?: () => AgentSpec;
|
|
13
13
|
}): RemoteThreadListAdapter {
|
|
14
|
-
const {
|
|
14
|
+
const { server, defaultAgentSpec, getAgentSpec } = options;
|
|
15
15
|
|
|
16
16
|
return {
|
|
17
17
|
async list({ after } = {}) {
|
|
18
|
-
const page = await
|
|
18
|
+
const page = await server.listSessions({
|
|
19
19
|
limit: THREAD_LIST_PAGE_SIZE,
|
|
20
20
|
pageToken: after,
|
|
21
21
|
startTimestamp: sessionListStartTimestamp(),
|
|
22
22
|
});
|
|
23
|
-
const threads = page.data
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
const threads = page.data
|
|
24
|
+
.filter((session) => session.isMutable)
|
|
25
|
+
.map((draft) => ({
|
|
26
|
+
status: "regular" as const,
|
|
27
|
+
remoteId: draft.id,
|
|
28
|
+
title: draftSessionTitle({
|
|
29
|
+
title: draft.title,
|
|
30
|
+
agentSpec: draft.agentSpec ?? defaultAgentSpec,
|
|
31
|
+
}),
|
|
32
|
+
lastMessageAt: new Date(draft.updatedAt),
|
|
33
|
+
}));
|
|
29
34
|
return {
|
|
30
35
|
threads,
|
|
31
|
-
nextCursor: page.
|
|
36
|
+
nextCursor: page.nextPageToken ?? undefined,
|
|
32
37
|
};
|
|
33
38
|
},
|
|
34
39
|
|
|
35
40
|
async initialize(_threadId: string) {
|
|
36
|
-
const draft = await
|
|
41
|
+
const draft = await server.createSession({
|
|
37
42
|
agentSpec: getAgentSpec?.() ?? defaultAgentSpec,
|
|
38
43
|
});
|
|
39
44
|
return { remoteId: draft.id, externalId: undefined };
|
|
40
45
|
},
|
|
41
46
|
|
|
42
47
|
async fetch(remoteId) {
|
|
43
|
-
const draft = await
|
|
44
|
-
draftSessionId: remoteId,
|
|
45
|
-
});
|
|
48
|
+
const draft = await server.getSession({ sessionId: remoteId });
|
|
46
49
|
return {
|
|
47
50
|
status: "regular" as const,
|
|
48
51
|
remoteId: draft.id,
|
|
49
|
-
title: draftSessionTitle(
|
|
52
|
+
title: draftSessionTitle({
|
|
53
|
+
title: draft.title,
|
|
54
|
+
agentSpec: draft.agentSpec ?? defaultAgentSpec,
|
|
55
|
+
}),
|
|
50
56
|
lastMessageAt: new Date(draft.updatedAt),
|
|
51
57
|
};
|
|
52
58
|
},
|
|
@@ -64,7 +64,7 @@ describe("requiredActionsFromActiveUpdate", () => {
|
|
|
64
64
|
};
|
|
65
65
|
|
|
66
66
|
const actions = requiredActionsFromActiveUpdate(update);
|
|
67
|
-
expect(actions
|
|
67
|
+
expect(actions?.map((action) => action.type)).toEqual([
|
|
68
68
|
"tool.approval_required",
|
|
69
69
|
"tool.response_required",
|
|
70
70
|
]);
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local implementations of streaming delta helpers.
|
|
3
|
+
* Formerly imported from truefoundry-gateway-sdk/agents.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type {
|
|
7
|
+
DeltaEvents,
|
|
8
|
+
ModelMessageDeltaEvent,
|
|
9
|
+
ModelMessageEvent,
|
|
10
|
+
ToolCall,
|
|
11
|
+
ToolInfo,
|
|
12
|
+
TurnEvent,
|
|
13
|
+
TurnStreamingEvent,
|
|
14
|
+
} from "./events.js";
|
|
15
|
+
|
|
16
|
+
/** True for `.delta` streaming events. */
|
|
17
|
+
export function isEventDelta(event: TurnStreamingEvent): event is DeltaEvents {
|
|
18
|
+
return typeof event.type === "string" && event.type.endsWith(".delta");
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Merge `delta` into `base` in place (same `id` required).
|
|
23
|
+
* Currently handles `model.message.delta` → `model.message`.
|
|
24
|
+
*/
|
|
25
|
+
export function mergeEventDelta(base: TurnEvent, delta: DeltaEvents): void {
|
|
26
|
+
if (base.id !== delta.id) {
|
|
27
|
+
throw new Error(
|
|
28
|
+
`Cannot merge delta into a different event: base id "${base.id}" != delta id "${delta.id}".`,
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
if (delta.type === "model.message.delta" && base.type === "model.message") {
|
|
32
|
+
mergeModelMessageDelta(base, delta);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function asToolInfo(value: unknown): ToolInfo | undefined {
|
|
37
|
+
if (value == null || typeof value !== "object") {
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
return value as ToolInfo;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function mergeModelMessageDelta(
|
|
44
|
+
base: ModelMessageEvent,
|
|
45
|
+
delta: ModelMessageDeltaEvent,
|
|
46
|
+
): void {
|
|
47
|
+
if (delta.content) {
|
|
48
|
+
if (
|
|
49
|
+
base.content === undefined ||
|
|
50
|
+
base.content === null ||
|
|
51
|
+
typeof base.content === "string"
|
|
52
|
+
) {
|
|
53
|
+
base.content = (base.content ?? "") + delta.content;
|
|
54
|
+
} else {
|
|
55
|
+
const last = base.content[base.content.length - 1];
|
|
56
|
+
if (last && last.type === "text") {
|
|
57
|
+
last.text += delta.content;
|
|
58
|
+
} else {
|
|
59
|
+
base.content.push({ type: "text", text: delta.content });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (delta.refusal) {
|
|
65
|
+
base.refusal = (base.refusal ?? "") + delta.refusal;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (delta.toolCalls) {
|
|
69
|
+
base.toolCalls ??= [];
|
|
70
|
+
for (const d of delta.toolCalls) {
|
|
71
|
+
let tc: ToolCall | undefined = base.toolCalls[d.index];
|
|
72
|
+
if (tc === undefined) {
|
|
73
|
+
const toolInfo = asToolInfo(d.toolInfo);
|
|
74
|
+
tc = {
|
|
75
|
+
id: d.id ?? "",
|
|
76
|
+
type: d.type ?? "function",
|
|
77
|
+
function: {
|
|
78
|
+
name: d.function?.name ?? "",
|
|
79
|
+
arguments: "",
|
|
80
|
+
},
|
|
81
|
+
...(toolInfo != null ? { toolInfo } : {}),
|
|
82
|
+
};
|
|
83
|
+
base.toolCalls[d.index] = tc;
|
|
84
|
+
}
|
|
85
|
+
if (d.id) {
|
|
86
|
+
tc.id = d.id;
|
|
87
|
+
}
|
|
88
|
+
if (d.type) {
|
|
89
|
+
tc.type = d.type;
|
|
90
|
+
}
|
|
91
|
+
if (d.function?.name) {
|
|
92
|
+
tc.function.name = d.function.name;
|
|
93
|
+
}
|
|
94
|
+
if (d.function?.arguments) {
|
|
95
|
+
tc.function.arguments += d.function.arguments;
|
|
96
|
+
}
|
|
97
|
+
const toolInfo = asToolInfo(d.toolInfo);
|
|
98
|
+
if (toolInfo != null) {
|
|
99
|
+
tc.toolInfo = toolInfo;
|
|
100
|
+
}
|
|
101
|
+
if (d.providerSpecificFields) {
|
|
102
|
+
tc.providerSpecificFields = {
|
|
103
|
+
...(tc.providerSpecificFields ?? {}),
|
|
104
|
+
...d.providerSpecificFields,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (delta.finishReason) {
|
|
111
|
+
base.finishReason = delta.finishReason;
|
|
112
|
+
}
|
|
113
|
+
if (delta.reasoningContent) {
|
|
114
|
+
base.reasoningContent =
|
|
115
|
+
(base.reasoningContent ?? "") + delta.reasoningContent;
|
|
116
|
+
}
|
|
117
|
+
if (delta.usage) {
|
|
118
|
+
base.usage = delta.usage;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime-owned turn/stream event protocol.
|
|
3
|
+
*
|
|
4
|
+
* Hosts must emit events matching these shapes. The TFY adapter maps
|
|
5
|
+
* truefoundry-gateway-sdk events 1:1 onto these types.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { TurnInputItem, TurnState } from "./types.js";
|
|
9
|
+
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
// Tool call shapes
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
|
|
14
|
+
export interface ToolCallFunction {
|
|
15
|
+
name: string;
|
|
16
|
+
arguments: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type ToolInfo =
|
|
20
|
+
| { type: "truefoundry-system"; name: string }
|
|
21
|
+
| { type: "mcp"; serverId: string; serverName: string; name: string }
|
|
22
|
+
| { type: string; name?: string; [key: string]: unknown };
|
|
23
|
+
|
|
24
|
+
export interface ToolCall {
|
|
25
|
+
id: string;
|
|
26
|
+
type: "function";
|
|
27
|
+
function: ToolCallFunction;
|
|
28
|
+
toolInfo?: ToolInfo;
|
|
29
|
+
providerSpecificFields?: Record<string, unknown>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Ref used by approval/response-required events. */
|
|
33
|
+
export interface ToolCallRef {
|
|
34
|
+
id: string;
|
|
35
|
+
sourceEventId: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface ChunkDeltaToolCall {
|
|
39
|
+
index: number;
|
|
40
|
+
id?: string;
|
|
41
|
+
type?: "function";
|
|
42
|
+
function?: { name?: string; arguments?: string };
|
|
43
|
+
toolInfo?: ToolInfo;
|
|
44
|
+
providerSpecificFields?: Record<string, unknown>;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
// Content events
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
|
|
51
|
+
export type ModelMessageContentPart =
|
|
52
|
+
| { type: "text"; text: string }
|
|
53
|
+
| { type: "refusal"; refusal: string }
|
|
54
|
+
| { type: "image_url"; image_url: { url: string } };
|
|
55
|
+
|
|
56
|
+
export interface ModelMessageEvent {
|
|
57
|
+
type: "model.message";
|
|
58
|
+
id: string;
|
|
59
|
+
threadId: string;
|
|
60
|
+
content?: string | ModelMessageContentPart[] | null;
|
|
61
|
+
name?: string;
|
|
62
|
+
refusal?: string | null;
|
|
63
|
+
reasoningContent?: string;
|
|
64
|
+
toolCalls?: ToolCall[];
|
|
65
|
+
finishReason?: string | null;
|
|
66
|
+
createdAt: string;
|
|
67
|
+
usage?: unknown;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface ModelMessageDeltaEvent {
|
|
71
|
+
type: "model.message.delta";
|
|
72
|
+
id: string;
|
|
73
|
+
threadId: string;
|
|
74
|
+
content?: string | null;
|
|
75
|
+
refusal?: string | null;
|
|
76
|
+
reasoningContent?: string;
|
|
77
|
+
toolCalls?: ChunkDeltaToolCall[];
|
|
78
|
+
finishReason?: string | null;
|
|
79
|
+
createdAt?: string;
|
|
80
|
+
usage?: unknown;
|
|
81
|
+
/** Extended content-block deltas (image streaming). */
|
|
82
|
+
contentBlocks?: Array<{
|
|
83
|
+
index: number;
|
|
84
|
+
delta:
|
|
85
|
+
| { type: "text"; text?: string }
|
|
86
|
+
| { type: "image_url"; image_url?: { url?: string } };
|
|
87
|
+
}>;
|
|
88
|
+
content_blocks?: Array<{
|
|
89
|
+
index: number;
|
|
90
|
+
delta:
|
|
91
|
+
| { type: "text"; text?: string }
|
|
92
|
+
| { type: "image_url"; image_url?: { url?: string } };
|
|
93
|
+
}>;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export interface ToolResponseEvent {
|
|
97
|
+
type: "tool.response";
|
|
98
|
+
id: string;
|
|
99
|
+
threadId: string;
|
|
100
|
+
toolCallId: string;
|
|
101
|
+
content: string;
|
|
102
|
+
createdAt: string;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export interface ToolApprovalRequiredEvent {
|
|
106
|
+
type: "tool.approval_required";
|
|
107
|
+
id: string;
|
|
108
|
+
createdAt: string;
|
|
109
|
+
threadId: string;
|
|
110
|
+
toolCalls: ToolCallRef[];
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export interface ToolResponseRequiredEvent {
|
|
114
|
+
type: "tool.response_required";
|
|
115
|
+
id: string;
|
|
116
|
+
createdAt: string;
|
|
117
|
+
threadId: string;
|
|
118
|
+
toolCalls: ToolCallRef[];
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export interface AgentInfo {
|
|
122
|
+
type?: string;
|
|
123
|
+
name: string;
|
|
124
|
+
input: string;
|
|
125
|
+
model?: string;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export interface AgentParent {
|
|
129
|
+
threadId: string;
|
|
130
|
+
toolCallId: string;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export interface ThreadCreatedEvent {
|
|
134
|
+
type: "thread.created";
|
|
135
|
+
id: string;
|
|
136
|
+
threadId: string;
|
|
137
|
+
title: string;
|
|
138
|
+
agentInfo: AgentInfo;
|
|
139
|
+
parent: AgentParent;
|
|
140
|
+
createdAt: string;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export interface ThreadDoneEvent {
|
|
144
|
+
type: "thread.done";
|
|
145
|
+
id: string;
|
|
146
|
+
threadId: string;
|
|
147
|
+
title?: string;
|
|
148
|
+
createdAt: string;
|
|
149
|
+
state?: unknown;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export interface McpServerAuthInfo {
|
|
153
|
+
id: string;
|
|
154
|
+
name: string;
|
|
155
|
+
authUrl: string;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export interface McpAuthRequiredEvent {
|
|
159
|
+
type: "mcp.auth_required";
|
|
160
|
+
id: string;
|
|
161
|
+
createdAt: string;
|
|
162
|
+
threadId?: string | null;
|
|
163
|
+
mcpServers: McpServerAuthInfo[];
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export interface SandboxCreatedEvent {
|
|
167
|
+
type: "sandbox.created";
|
|
168
|
+
id: string;
|
|
169
|
+
createdAt: string;
|
|
170
|
+
sandboxId: string;
|
|
171
|
+
threadId: string | null;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export interface McpInitializeEvent {
|
|
175
|
+
type: "mcp.initialize";
|
|
176
|
+
id: string;
|
|
177
|
+
createdAt: string;
|
|
178
|
+
threadId: string | null;
|
|
179
|
+
[key: string]: unknown;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// ---------------------------------------------------------------------------
|
|
183
|
+
// Turn lifecycle events
|
|
184
|
+
// ---------------------------------------------------------------------------
|
|
185
|
+
|
|
186
|
+
export interface TurnCreatedEvent {
|
|
187
|
+
type: "turn.created";
|
|
188
|
+
id: string;
|
|
189
|
+
turnId: string;
|
|
190
|
+
previousTurnId?: string | null;
|
|
191
|
+
input?: TurnInputItem[];
|
|
192
|
+
state?: { status: "running" };
|
|
193
|
+
createdAt: string;
|
|
194
|
+
threadId?: string | null;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export interface TurnDoneEvent {
|
|
198
|
+
type: "turn.done";
|
|
199
|
+
id: string;
|
|
200
|
+
state: Exclude<TurnState, { status: "running" }>;
|
|
201
|
+
createdAt: string;
|
|
202
|
+
threadId?: string | null;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// ---------------------------------------------------------------------------
|
|
206
|
+
// Unions
|
|
207
|
+
// ---------------------------------------------------------------------------
|
|
208
|
+
|
|
209
|
+
/** Events stored in fold buckets (non-delta, non-turn-lifecycle). */
|
|
210
|
+
export type TurnEvent =
|
|
211
|
+
| ModelMessageEvent
|
|
212
|
+
| ToolResponseEvent
|
|
213
|
+
| ThreadCreatedEvent
|
|
214
|
+
| ThreadDoneEvent
|
|
215
|
+
| McpAuthRequiredEvent
|
|
216
|
+
| McpInitializeEvent
|
|
217
|
+
| SandboxCreatedEvent
|
|
218
|
+
| ToolApprovalRequiredEvent
|
|
219
|
+
| ToolResponseRequiredEvent;
|
|
220
|
+
|
|
221
|
+
/** Full streaming event union (includes deltas + turn lifecycle). */
|
|
222
|
+
export type TurnStreamingEvent =
|
|
223
|
+
| TurnEvent
|
|
224
|
+
| ModelMessageDeltaEvent
|
|
225
|
+
| TurnCreatedEvent
|
|
226
|
+
| TurnDoneEvent;
|
|
227
|
+
|
|
228
|
+
export type ActionRequiredEvent =
|
|
229
|
+
| ToolApprovalRequiredEvent
|
|
230
|
+
| ToolResponseRequiredEvent
|
|
231
|
+
| McpAuthRequiredEvent;
|
|
232
|
+
|
|
233
|
+
export interface TurnStreamData<
|
|
234
|
+
TStreamEvent extends TurnStreamingEvent = TurnStreamingEvent,
|
|
235
|
+
> {
|
|
236
|
+
sequenceNumber: number;
|
|
237
|
+
event: TStreamEvent;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/** Session-level event item from `listEvents`. */
|
|
241
|
+
export interface SessionEventItem {
|
|
242
|
+
turnId: string;
|
|
243
|
+
event: TurnCreatedEvent | TurnDoneEvent | TurnEvent;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
export type DeltaEvents = ModelMessageDeltaEvent;
|