@truefoundry/assistant-ui-runtime 0.1.4 → 0.1.5
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.js +6 -7
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/buildEditedUserMessageContent.test.ts +2 -2
- package/src/convertTurnMessages.ts +8 -8
- package/src/streamTurn.test.ts +3 -3
- package/src/streamTurn.ts +4 -13
- package/src/truefoundryThreadListAdapter.ts +2 -2
- package/src/useTrueFoundryAgentMessages.ts +3 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truefoundry/assistant-ui-runtime",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "TrueFoundry Gateway agent runtime adapter for assistant-ui",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"peerDependencies": {
|
|
51
51
|
"@types/react": "*",
|
|
52
52
|
"react": "^18 || ^19",
|
|
53
|
-
"truefoundry-gateway-sdk": "^0.4.0-rc.
|
|
53
|
+
"truefoundry-gateway-sdk": "^0.4.0-rc.5"
|
|
54
54
|
},
|
|
55
55
|
"peerDependenciesMeta": {
|
|
56
56
|
"@types/react": {
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"@types/react": "^19.2.17",
|
|
64
64
|
"jsdom": "^29.1.1",
|
|
65
65
|
"react": "^19.2.4",
|
|
66
|
-
"truefoundry-gateway-sdk": "0.4.0-rc.
|
|
66
|
+
"truefoundry-gateway-sdk": "0.4.0-rc.5",
|
|
67
67
|
"tsup": "^8.5.0",
|
|
68
68
|
"typescript": "^5.9.3",
|
|
69
69
|
"vitest": "^4.1.9"
|
|
@@ -12,11 +12,11 @@ describe("user message branch helpers", () => {
|
|
|
12
12
|
expect(parseTurnIdFromMessageId("turn-abc-user")).toBe("turn-abc");
|
|
13
13
|
});
|
|
14
14
|
|
|
15
|
-
it("resolveBranchPreviousTurnId returns
|
|
15
|
+
it("resolveBranchPreviousTurnId returns \"none\" for the first turn", () => {
|
|
16
16
|
const turns: SessionTurnRecord[] = [
|
|
17
17
|
{ id: "a", createdAt: "", state: { status: "done", requiredActions: [], completedAt: "" } },
|
|
18
18
|
];
|
|
19
|
-
expect(resolveBranchPreviousTurnId(turns, "a")).
|
|
19
|
+
expect(resolveBranchPreviousTurnId(turns, "a")).toBe("none");
|
|
20
20
|
});
|
|
21
21
|
|
|
22
22
|
it("resolveBranchPreviousTurnId returns the prior turn id", () => {
|
|
@@ -1276,24 +1276,24 @@ export async function buildSnapshotBeforeTurnIndex(
|
|
|
1276
1276
|
return snapshot;
|
|
1277
1277
|
}
|
|
1278
1278
|
|
|
1279
|
-
/** Gateway turn id to branch from when resubmitting at `turnIndex` (
|
|
1279
|
+
/** Gateway turn id to branch from when resubmitting at `turnIndex` (`"none"` for first turn). */
|
|
1280
1280
|
export async function resolveGatewayBranchPreviousTurnId(
|
|
1281
1281
|
session: AgentSession,
|
|
1282
1282
|
turnIndex: number,
|
|
1283
1283
|
orderedTurns?: Turn[],
|
|
1284
|
-
): Promise<string
|
|
1284
|
+
): Promise<string> {
|
|
1285
1285
|
if (turnIndex <= 0) {
|
|
1286
|
-
return
|
|
1286
|
+
return "none";
|
|
1287
1287
|
}
|
|
1288
1288
|
const turns = orderedTurns ?? (await listSessionTurnsOrdered(session));
|
|
1289
|
-
return turns[turnIndex - 1]?.id ??
|
|
1289
|
+
return turns[turnIndex - 1]?.id ?? "none";
|
|
1290
1290
|
}
|
|
1291
1291
|
|
|
1292
1292
|
/** Resolves `previousTurnId` by turn id so partial history windows stay correct. */
|
|
1293
1293
|
export async function resolveGatewayBranchPreviousTurnIdForTurn(
|
|
1294
1294
|
session: AgentSession,
|
|
1295
1295
|
turnId: string,
|
|
1296
|
-
): Promise<string
|
|
1296
|
+
): Promise<string> {
|
|
1297
1297
|
const turns = await listSessionTurnsOrdered(session);
|
|
1298
1298
|
const turnIndex = turns.findIndex((turn) => turn.id === turnId);
|
|
1299
1299
|
return resolveGatewayBranchPreviousTurnId(session, turnIndex, turns);
|
|
@@ -1456,14 +1456,14 @@ export function parseTurnIdFromMessageId(messageId: string): string {
|
|
|
1456
1456
|
return messageId.replace(/-user$/, "");
|
|
1457
1457
|
}
|
|
1458
1458
|
|
|
1459
|
-
/** Parent turn id for branching before `turnId`; `
|
|
1459
|
+
/** Parent turn id for branching before `turnId`; `"none"` when editing the first turn. */
|
|
1460
1460
|
export function resolveBranchPreviousTurnId(
|
|
1461
1461
|
turns: readonly SessionTurnRecord[],
|
|
1462
1462
|
turnId: string,
|
|
1463
|
-
): string
|
|
1463
|
+
): string {
|
|
1464
1464
|
const turnIndex = turns.findIndex((turn) => turn.id === turnId);
|
|
1465
1465
|
if (turnIndex <= 0) {
|
|
1466
|
-
return
|
|
1466
|
+
return "none";
|
|
1467
1467
|
}
|
|
1468
1468
|
return turns[turnIndex - 1]!.id;
|
|
1469
1469
|
}
|
package/src/streamTurn.test.ts
CHANGED
|
@@ -150,7 +150,7 @@ describe("streamTurn", () => {
|
|
|
150
150
|
});
|
|
151
151
|
});
|
|
152
152
|
|
|
153
|
-
it("forwards previousTurnId
|
|
153
|
+
it("forwards previousTurnId \"none\" when branching from root", async () => {
|
|
154
154
|
const execute = vi.fn(() => (async function* () {})());
|
|
155
155
|
const prepareTurn = vi.fn(() => ({ execute }));
|
|
156
156
|
const session = {
|
|
@@ -162,14 +162,14 @@ describe("streamTurn", () => {
|
|
|
162
162
|
streamTurnContent(
|
|
163
163
|
session,
|
|
164
164
|
new PeerThreadFoldState(),
|
|
165
|
-
{ userMessage: "first", previousTurnId:
|
|
165
|
+
{ userMessage: "first", previousTurnId: "none" },
|
|
166
166
|
new AbortController().signal,
|
|
167
167
|
),
|
|
168
168
|
);
|
|
169
169
|
|
|
170
170
|
expect(prepareTurn).toHaveBeenCalledWith({
|
|
171
171
|
input: [{ type: "user.message", content: "first" }],
|
|
172
|
-
previousTurnId:
|
|
172
|
+
previousTurnId: "none",
|
|
173
173
|
});
|
|
174
174
|
});
|
|
175
175
|
|
package/src/streamTurn.ts
CHANGED
|
@@ -18,10 +18,10 @@ export type StreamTurnOptions = {
|
|
|
18
18
|
resumeMcpAuth?: boolean;
|
|
19
19
|
inputs?: RequiredActionInput[];
|
|
20
20
|
/**
|
|
21
|
-
* Branch anchor for `prepareTurn`. Omit for `"auto"`. Pass `
|
|
22
|
-
* root turn — sent as `previous_turn_id:
|
|
21
|
+
* Branch anchor for `prepareTurn`. Omit for `"auto"`. Pass `"none"` for a fresh
|
|
22
|
+
* root turn — sent as `previous_turn_id: "none"` on the wire.
|
|
23
23
|
*/
|
|
24
|
-
previousTurnId?:
|
|
24
|
+
previousTurnId?: TruefoundryGatewayApi.PreviousTurnIdInput;
|
|
25
25
|
/** Extra headers for the createTurn request (`execute` request options). */
|
|
26
26
|
headers?: Record<string, string>;
|
|
27
27
|
};
|
|
@@ -62,18 +62,9 @@ export async function* streamTurnContent(
|
|
|
62
62
|
*/
|
|
63
63
|
onTurnIdAvailable?: (turnId: string) => void,
|
|
64
64
|
): AsyncGenerator<TurnStreamUpdate> {
|
|
65
|
-
// When previousTurnId is explicitly null, pass it through to prepareTurn so the
|
|
66
|
-
// SDK serializer emits `previous_turn_id: null` on the wire (first turn in session).
|
|
67
|
-
// The SDK type doesn't admit null, but the Fern serializer handles it correctly.
|
|
68
|
-
const previousTurnId: TruefoundryGatewayApi.PreviousTurnIdInput | null | undefined =
|
|
69
|
-
options.previousTurnId === null
|
|
70
|
-
? null
|
|
71
|
-
: (options.previousTurnId ?? "auto");
|
|
72
65
|
const turn = session.prepareTurn({
|
|
73
66
|
input: buildTurnInput(options),
|
|
74
|
-
|
|
75
|
-
? { previousTurnId: previousTurnId as TruefoundryGatewayApi.PreviousTurnIdInput }
|
|
76
|
-
: {}),
|
|
67
|
+
previousTurnId: options.previousTurnId ?? "auto",
|
|
77
68
|
});
|
|
78
69
|
|
|
79
70
|
const onAbort = bindAbort(session, abortSignal);
|
|
@@ -23,7 +23,7 @@ export function createTrueFoundryThreadListAdapter(options: {
|
|
|
23
23
|
const threads = page.data.map((session) => ({
|
|
24
24
|
status: "regular" as const,
|
|
25
25
|
remoteId: session.id,
|
|
26
|
-
title: session.title,
|
|
26
|
+
title: session.title ?? undefined,
|
|
27
27
|
lastMessageAt: new Date(session.updatedAt),
|
|
28
28
|
}));
|
|
29
29
|
return {
|
|
@@ -42,7 +42,7 @@ export function createTrueFoundryThreadListAdapter(options: {
|
|
|
42
42
|
return {
|
|
43
43
|
status: "regular" as const,
|
|
44
44
|
remoteId: session.id,
|
|
45
|
-
title: session.title,
|
|
45
|
+
title: session.title ?? undefined,
|
|
46
46
|
lastMessageAt: new Date(session.updatedAt),
|
|
47
47
|
};
|
|
48
48
|
},
|
|
@@ -80,7 +80,7 @@ export type UseTrueFoundryAgentMessagesOptions = {
|
|
|
80
80
|
export type SendTurnOptions =
|
|
81
81
|
| {
|
|
82
82
|
userMessage: UserMessageContent;
|
|
83
|
-
previousTurnId?: string
|
|
83
|
+
previousTurnId?: string;
|
|
84
84
|
/**
|
|
85
85
|
* When branching (edit/reset), the already-rewound history to send from.
|
|
86
86
|
* Applied atomically with `pendingUser` so a stale React snapshot cannot
|
|
@@ -596,7 +596,7 @@ export function useTrueFoundryAgentMessages({
|
|
|
596
596
|
isContinuation && continuationTurnId != null
|
|
597
597
|
? continuationTurnId
|
|
598
598
|
: generateId();
|
|
599
|
-
// First turns must send previousTurnId:
|
|
599
|
+
// First turns must send previousTurnId: "none".
|
|
600
600
|
const isFirstTurnInSession =
|
|
601
601
|
"userMessage" in options &&
|
|
602
602
|
options.previousTurnId === undefined &&
|
|
@@ -697,7 +697,7 @@ export function useTrueFoundryAgentMessages({
|
|
|
697
697
|
...(options.previousTurnId !== undefined
|
|
698
698
|
? { previousTurnId: options.previousTurnId }
|
|
699
699
|
: isFirstTurnInSession
|
|
700
|
-
? { previousTurnId:
|
|
700
|
+
? { previousTurnId: "none" }
|
|
701
701
|
: {}),
|
|
702
702
|
...streamHeaders,
|
|
703
703
|
},
|