@truefoundry/assistant-ui-runtime 0.1.5 → 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 +330 -236
- 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 +10 -2
- package/src/askUserQuestion.ts +3 -3
- package/src/buildEditedUserMessageContent.test.ts +2 -2
- package/src/collectPending.ts +1 -1
- package/src/convertTurnMessages.test.ts +141 -196
- package/src/convertTurnMessages.ts +130 -76
- 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 +172 -155
- package/src/streamTurn.ts +51 -48
- 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 +7 -7
- package/src/turnEventHelpers.ts +1 -1
- package/src/types.ts +2 -16
- package/src/useTrueFoundryAgentMessages.test.tsx +38 -70
- package/src/useTrueFoundryAgentMessages.ts +32 -44
- 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
package/dist/index.js
CHANGED
|
@@ -88,9 +88,10 @@ function findApprovalRequiredInTurn(turn) {
|
|
|
88
88
|
if (turn.state.status !== "done") {
|
|
89
89
|
return void 0;
|
|
90
90
|
}
|
|
91
|
-
|
|
91
|
+
const found = turn.state.requiredActions?.find(
|
|
92
92
|
(action) => action.type === "tool.approval_required"
|
|
93
93
|
);
|
|
94
|
+
return found?.type === "tool.approval_required" ? found : void 0;
|
|
94
95
|
}
|
|
95
96
|
function toolCallPartHasPendingApproval(part) {
|
|
96
97
|
return hasPendingToolApproval(part.approval);
|
|
@@ -250,10 +251,93 @@ function toTrueFoundryApprovalInputs(message, response, defaultThreadId = ROOT_T
|
|
|
250
251
|
return collectApprovalInputs(updated, defaultThreadId);
|
|
251
252
|
}
|
|
252
253
|
|
|
253
|
-
// src/
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
}
|
|
254
|
+
// src/server/eventUtils.ts
|
|
255
|
+
function isEventDelta(event) {
|
|
256
|
+
return typeof event.type === "string" && event.type.endsWith(".delta");
|
|
257
|
+
}
|
|
258
|
+
function mergeEventDelta(base, delta) {
|
|
259
|
+
if (base.id !== delta.id) {
|
|
260
|
+
throw new Error(
|
|
261
|
+
`Cannot merge delta into a different event: base id "${base.id}" != delta id "${delta.id}".`
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
if (delta.type === "model.message.delta" && base.type === "model.message") {
|
|
265
|
+
mergeModelMessageDelta(base, delta);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
function asToolInfo(value) {
|
|
269
|
+
if (value == null || typeof value !== "object") {
|
|
270
|
+
return void 0;
|
|
271
|
+
}
|
|
272
|
+
return value;
|
|
273
|
+
}
|
|
274
|
+
function mergeModelMessageDelta(base, delta) {
|
|
275
|
+
if (delta.content) {
|
|
276
|
+
if (base.content === void 0 || base.content === null || typeof base.content === "string") {
|
|
277
|
+
base.content = (base.content ?? "") + delta.content;
|
|
278
|
+
} else {
|
|
279
|
+
const last = base.content[base.content.length - 1];
|
|
280
|
+
if (last && last.type === "text") {
|
|
281
|
+
last.text += delta.content;
|
|
282
|
+
} else {
|
|
283
|
+
base.content.push({ type: "text", text: delta.content });
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
if (delta.refusal) {
|
|
288
|
+
base.refusal = (base.refusal ?? "") + delta.refusal;
|
|
289
|
+
}
|
|
290
|
+
if (delta.toolCalls) {
|
|
291
|
+
base.toolCalls ??= [];
|
|
292
|
+
for (const d of delta.toolCalls) {
|
|
293
|
+
let tc = base.toolCalls[d.index];
|
|
294
|
+
if (tc === void 0) {
|
|
295
|
+
const toolInfo2 = asToolInfo(d.toolInfo);
|
|
296
|
+
tc = {
|
|
297
|
+
id: d.id ?? "",
|
|
298
|
+
type: d.type ?? "function",
|
|
299
|
+
function: {
|
|
300
|
+
name: d.function?.name ?? "",
|
|
301
|
+
arguments: ""
|
|
302
|
+
},
|
|
303
|
+
...toolInfo2 != null ? { toolInfo: toolInfo2 } : {}
|
|
304
|
+
};
|
|
305
|
+
base.toolCalls[d.index] = tc;
|
|
306
|
+
}
|
|
307
|
+
if (d.id) {
|
|
308
|
+
tc.id = d.id;
|
|
309
|
+
}
|
|
310
|
+
if (d.type) {
|
|
311
|
+
tc.type = d.type;
|
|
312
|
+
}
|
|
313
|
+
if (d.function?.name) {
|
|
314
|
+
tc.function.name = d.function.name;
|
|
315
|
+
}
|
|
316
|
+
if (d.function?.arguments) {
|
|
317
|
+
tc.function.arguments += d.function.arguments;
|
|
318
|
+
}
|
|
319
|
+
const toolInfo = asToolInfo(d.toolInfo);
|
|
320
|
+
if (toolInfo != null) {
|
|
321
|
+
tc.toolInfo = toolInfo;
|
|
322
|
+
}
|
|
323
|
+
if (d.providerSpecificFields) {
|
|
324
|
+
tc.providerSpecificFields = {
|
|
325
|
+
...tc.providerSpecificFields ?? {},
|
|
326
|
+
...d.providerSpecificFields
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
if (delta.finishReason) {
|
|
332
|
+
base.finishReason = delta.finishReason;
|
|
333
|
+
}
|
|
334
|
+
if (delta.reasoningContent) {
|
|
335
|
+
base.reasoningContent = (base.reasoningContent ?? "") + delta.reasoningContent;
|
|
336
|
+
}
|
|
337
|
+
if (delta.usage) {
|
|
338
|
+
base.usage = delta.usage;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
257
341
|
|
|
258
342
|
// src/askUserQuestion.ts
|
|
259
343
|
function parseAskUserQuestionArgs(argsText) {
|
|
@@ -283,7 +367,6 @@ function isCreateSubAgentToolCall(toolCall) {
|
|
|
283
367
|
}
|
|
284
368
|
|
|
285
369
|
// src/modelMessageImageContent.ts
|
|
286
|
-
import { isEventDelta, mergeEventDelta } from "truefoundry-gateway-sdk/agents";
|
|
287
370
|
function parseDataUriMime(data) {
|
|
288
371
|
if (!data.startsWith("data:")) {
|
|
289
372
|
return "image/png";
|
|
@@ -545,7 +628,7 @@ function ingestEventIntoBucket(bucket, message) {
|
|
|
545
628
|
if (isTurnScopedEvent(message)) {
|
|
546
629
|
return;
|
|
547
630
|
}
|
|
548
|
-
if (
|
|
631
|
+
if (isEventDelta(message)) {
|
|
549
632
|
const base = bucket.events.get(message.id);
|
|
550
633
|
if (base != null) {
|
|
551
634
|
mergeStreamEventDelta(base, message);
|
|
@@ -899,9 +982,10 @@ function findResponseRequiredInTurn(turn) {
|
|
|
899
982
|
if (turn.state.status !== "done") {
|
|
900
983
|
return void 0;
|
|
901
984
|
}
|
|
902
|
-
|
|
985
|
+
const found = turn.state.requiredActions?.find(
|
|
903
986
|
(action) => action.type === "tool.response_required"
|
|
904
987
|
);
|
|
988
|
+
return found?.type === "tool.response_required" ? found : void 0;
|
|
905
989
|
}
|
|
906
990
|
function applyToolResponseToToolCall(part, content) {
|
|
907
991
|
return { ...part, result: content };
|
|
@@ -1150,6 +1234,21 @@ function deriveSandboxId(messages) {
|
|
|
1150
1234
|
return void 0;
|
|
1151
1235
|
}
|
|
1152
1236
|
|
|
1237
|
+
// src/listPages.ts
|
|
1238
|
+
async function drainListPages(fetchPage) {
|
|
1239
|
+
const items = [];
|
|
1240
|
+
let pageToken;
|
|
1241
|
+
for (; ; ) {
|
|
1242
|
+
const page = await fetchPage(pageToken);
|
|
1243
|
+
items.push(...page.data);
|
|
1244
|
+
if (page.nextPageToken == null || page.nextPageToken === "") {
|
|
1245
|
+
break;
|
|
1246
|
+
}
|
|
1247
|
+
pageToken = page.nextPageToken;
|
|
1248
|
+
}
|
|
1249
|
+
return items;
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1153
1252
|
// src/extractTurnUserText.ts
|
|
1154
1253
|
function extractTurnUserText(input) {
|
|
1155
1254
|
const parts = [];
|
|
@@ -1187,9 +1286,10 @@ function buildMcpAuthTextParts(servers) {
|
|
|
1187
1286
|
return [{ type: "text", text }];
|
|
1188
1287
|
}
|
|
1189
1288
|
function findMcpAuthRequired(requiredActions) {
|
|
1190
|
-
|
|
1289
|
+
const found = requiredActions?.find(
|
|
1191
1290
|
(action) => action.type === "mcp.auth_required"
|
|
1192
1291
|
);
|
|
1292
|
+
return found?.type === "mcp.auth_required" ? found : void 0;
|
|
1193
1293
|
}
|
|
1194
1294
|
function mcpAuthAssistantStatus() {
|
|
1195
1295
|
return { type: "requires-action", reason: "interrupt" };
|
|
@@ -1329,28 +1429,28 @@ function oldestCompleteTurnGroupState(itemsAsc) {
|
|
|
1329
1429
|
}
|
|
1330
1430
|
return extractTurnUserText(created.event.input) != null ? "user-group" : "continuation";
|
|
1331
1431
|
}
|
|
1332
|
-
async function fetchSessionEventsPage(
|
|
1333
|
-
const page = await
|
|
1432
|
+
async function fetchSessionEventsPage(server, sessionId, options) {
|
|
1433
|
+
const page = await server.listEvents({
|
|
1434
|
+
sessionId,
|
|
1334
1435
|
limit: SESSION_EVENTS_PAGE_SIZE,
|
|
1335
1436
|
...options?.lastTurnId != null ? { lastTurnId: options.lastTurnId } : {},
|
|
1336
1437
|
...options?.pageToken != null ? { pageToken: options.pageToken } : {}
|
|
1337
1438
|
});
|
|
1338
|
-
const
|
|
1339
|
-
const
|
|
1340
|
-
const hasOlder = typeof page.hasNextPage === "function" ? page.hasNextPage() : olderPageToken != null && olderPageToken !== "";
|
|
1439
|
+
const olderPageToken = page.nextPageToken;
|
|
1440
|
+
const hasOlder = olderPageToken != null && olderPageToken !== "";
|
|
1341
1441
|
return {
|
|
1342
1442
|
itemsNewestFirst: page.data,
|
|
1343
1443
|
...olderPageToken != null && olderPageToken !== "" ? { olderPageToken } : {},
|
|
1344
1444
|
hasOlder
|
|
1345
1445
|
};
|
|
1346
1446
|
}
|
|
1347
|
-
async function fetchSessionEventsWindow(
|
|
1447
|
+
async function fetchSessionEventsWindow(server, sessionId, options) {
|
|
1348
1448
|
let itemsNewestFirst = [];
|
|
1349
1449
|
let pageToken = options?.pageToken;
|
|
1350
1450
|
let olderPageToken;
|
|
1351
1451
|
let hasOlder = false;
|
|
1352
1452
|
for (let pageCount = 0; pageCount < MAX_HISTORY_BOUNDARY_PAGES; pageCount++) {
|
|
1353
|
-
const page = await fetchSessionEventsPage(
|
|
1453
|
+
const page = await fetchSessionEventsPage(server, sessionId, {
|
|
1354
1454
|
...options,
|
|
1355
1455
|
...pageToken != null ? { pageToken } : {}
|
|
1356
1456
|
});
|
|
@@ -1378,14 +1478,15 @@ async function fetchSessionEventsWindow(session, options) {
|
|
|
1378
1478
|
hasOlder
|
|
1379
1479
|
};
|
|
1380
1480
|
}
|
|
1381
|
-
async function fetchAllSessionEvents(
|
|
1382
|
-
const items =
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1481
|
+
async function fetchAllSessionEvents(server, sessionId, options) {
|
|
1482
|
+
const items = await drainListPages(
|
|
1483
|
+
(pageToken) => server.listEvents({
|
|
1484
|
+
sessionId,
|
|
1485
|
+
limit: SESSION_EVENTS_PAGE_SIZE,
|
|
1486
|
+
...options?.lastTurnId != null ? { lastTurnId: options.lastTurnId } : {},
|
|
1487
|
+
...pageToken != null ? { pageToken } : {}
|
|
1488
|
+
})
|
|
1489
|
+
);
|
|
1389
1490
|
items.reverse();
|
|
1390
1491
|
return items;
|
|
1391
1492
|
}
|
|
@@ -1520,11 +1621,11 @@ function attachRunningTurn(snapshot, runningTurn) {
|
|
|
1520
1621
|
} : {}
|
|
1521
1622
|
});
|
|
1522
1623
|
}
|
|
1523
|
-
async function buildSnapshotFromSessionEvents(
|
|
1524
|
-
const turnsPage = await
|
|
1624
|
+
async function buildSnapshotFromSessionEvents(server, sessionId, onProgress) {
|
|
1625
|
+
const turnsPage = await server.listTurns({ sessionId, limit: 1 });
|
|
1525
1626
|
const newestTurn = turnsPage.data[0];
|
|
1526
1627
|
const runningTurn = newestTurn?.state?.status === "running" ? newestTurn : void 0;
|
|
1527
|
-
const window = await fetchSessionEventsWindow(
|
|
1628
|
+
const window = await fetchSessionEventsWindow(server, sessionId);
|
|
1528
1629
|
const historyPagination = {
|
|
1529
1630
|
hasOlder: window.hasOlder,
|
|
1530
1631
|
...window.olderPageToken != null ? { olderPageToken: window.olderPageToken } : {}
|
|
@@ -1537,12 +1638,12 @@ async function buildSnapshotFromSessionEvents(session, onProgress) {
|
|
|
1537
1638
|
});
|
|
1538
1639
|
return attachRunningTurn(withHistory, runningTurn);
|
|
1539
1640
|
}
|
|
1540
|
-
async function prependOlderSessionHistory(
|
|
1641
|
+
async function prependOlderSessionHistory(server, sessionId, snapshot) {
|
|
1541
1642
|
const pagination = snapshot.historyPagination;
|
|
1542
1643
|
if (pagination?.hasOlder !== true || pagination.olderPageToken == null) {
|
|
1543
1644
|
return snapshot;
|
|
1544
1645
|
}
|
|
1545
|
-
const window = await fetchSessionEventsWindow(
|
|
1646
|
+
const window = await fetchSessionEventsWindow(server, sessionId, {
|
|
1546
1647
|
pageToken: pagination.olderPageToken
|
|
1547
1648
|
});
|
|
1548
1649
|
if (window.itemsAsc.length === 0) {
|
|
@@ -1694,22 +1795,36 @@ function buildAssistantMessage(turnId, content, createdAt, status, custom = {},
|
|
|
1694
1795
|
}
|
|
1695
1796
|
};
|
|
1696
1797
|
}
|
|
1697
|
-
async function ingestTurnEventsIntoFold(
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1798
|
+
async function ingestTurnEventsIntoFold(server, sessionId, turnId, foldState) {
|
|
1799
|
+
if (server.listTurnEvents == null) {
|
|
1800
|
+
return;
|
|
1801
|
+
}
|
|
1802
|
+
const events = await drainListPages(
|
|
1803
|
+
(pageToken) => server.listTurnEvents({
|
|
1804
|
+
sessionId,
|
|
1805
|
+
turnId,
|
|
1806
|
+
order: "asc",
|
|
1807
|
+
limit: TURN_EVENTS_PAGE_SIZE,
|
|
1808
|
+
...pageToken != null ? { pageToken } : {}
|
|
1809
|
+
})
|
|
1810
|
+
);
|
|
1811
|
+
for (const event of events) {
|
|
1702
1812
|
ingestTurnEvent(foldState, event);
|
|
1703
1813
|
}
|
|
1704
1814
|
}
|
|
1705
|
-
async function fetchTurnEvents(
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
order: "asc",
|
|
1709
|
-
limit: TURN_EVENTS_PAGE_SIZE
|
|
1710
|
-
})) {
|
|
1711
|
-
events.push(event);
|
|
1815
|
+
async function fetchTurnEvents(server, sessionId, turnId) {
|
|
1816
|
+
if (server.listTurnEvents == null) {
|
|
1817
|
+
return [];
|
|
1712
1818
|
}
|
|
1819
|
+
const events = await drainListPages(
|
|
1820
|
+
(pageToken) => server.listTurnEvents({
|
|
1821
|
+
sessionId,
|
|
1822
|
+
turnId,
|
|
1823
|
+
order: "asc",
|
|
1824
|
+
limit: TURN_EVENTS_PAGE_SIZE,
|
|
1825
|
+
...pageToken != null ? { pageToken } : {}
|
|
1826
|
+
})
|
|
1827
|
+
);
|
|
1713
1828
|
return events;
|
|
1714
1829
|
}
|
|
1715
1830
|
function ingestCollectedEventsIntoFold(foldState, events) {
|
|
@@ -1717,16 +1832,18 @@ function ingestCollectedEventsIntoFold(foldState, events) {
|
|
|
1717
1832
|
ingestTurnEvent(foldState, event);
|
|
1718
1833
|
}
|
|
1719
1834
|
}
|
|
1720
|
-
async function fetchAllTurnEventsWithConcurrency(turns, concurrency) {
|
|
1835
|
+
async function fetchAllTurnEventsWithConcurrency(server, sessionId, turns, concurrency) {
|
|
1721
1836
|
const results = new Array(turns.length);
|
|
1722
1837
|
const pool = /* @__PURE__ */ new Set();
|
|
1723
1838
|
for (let i = 0; i < turns.length; i++) {
|
|
1724
1839
|
const idx = i;
|
|
1725
1840
|
const turn = turns[idx];
|
|
1726
|
-
const p = fetchTurnEvents(turn).then(
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1841
|
+
const p = fetchTurnEvents(server, sessionId, turn.id).then(
|
|
1842
|
+
(events) => {
|
|
1843
|
+
results[idx] = events;
|
|
1844
|
+
pool.delete(p);
|
|
1845
|
+
}
|
|
1846
|
+
);
|
|
1730
1847
|
pool.add(p);
|
|
1731
1848
|
if (pool.size >= concurrency) await Promise.race(pool);
|
|
1732
1849
|
}
|
|
@@ -2011,13 +2128,18 @@ function ingestTurnsIntoSnapshot(snapshot, turns, eventArrays) {
|
|
|
2011
2128
|
}
|
|
2012
2129
|
return runningTurn;
|
|
2013
2130
|
}
|
|
2014
|
-
async function buildSnapshotFromSession(
|
|
2015
|
-
const snapshot = await buildSnapshotFromSessionEvents(
|
|
2131
|
+
async function buildSnapshotFromSession(server, sessionId, concurrency = DEFAULT_LIST_EVENTS_CONCURRENCY) {
|
|
2132
|
+
const snapshot = await buildSnapshotFromSessionEvents(server, sessionId);
|
|
2016
2133
|
if (snapshot.runningTurn == null) {
|
|
2017
2134
|
return snapshot;
|
|
2018
2135
|
}
|
|
2019
2136
|
const turn = snapshot.runningTurn;
|
|
2020
|
-
const eventArrays = await fetchAllTurnEventsWithConcurrency(
|
|
2137
|
+
const eventArrays = await fetchAllTurnEventsWithConcurrency(
|
|
2138
|
+
server,
|
|
2139
|
+
sessionId,
|
|
2140
|
+
[turn],
|
|
2141
|
+
concurrency
|
|
2142
|
+
);
|
|
2021
2143
|
ingestTurnsIntoSnapshot(snapshot, [turn], eventArrays);
|
|
2022
2144
|
return replaceSessionSnapshot(snapshot, {
|
|
2023
2145
|
runningTurn: turn,
|
|
@@ -2026,59 +2148,67 @@ async function buildSnapshotFromSession(session, concurrency = DEFAULT_LIST_EVEN
|
|
|
2026
2148
|
pendingUser: void 0
|
|
2027
2149
|
});
|
|
2028
2150
|
}
|
|
2029
|
-
async function buildSnapshotBeforeTurn(
|
|
2030
|
-
const turns = await listSessionTurnsOrdered(
|
|
2151
|
+
async function buildSnapshotBeforeTurn(server, sessionId, beforeTurnId, concurrency = DEFAULT_LIST_EVENTS_CONCURRENCY) {
|
|
2152
|
+
const turns = await listSessionTurnsOrdered(server, sessionId);
|
|
2031
2153
|
const beforeIndex = turns.findIndex((turn) => turn.id === beforeTurnId);
|
|
2032
2154
|
if (beforeIndex === -1) {
|
|
2033
2155
|
throw new Error(`Turn ${beforeTurnId} not found in session`);
|
|
2034
2156
|
}
|
|
2035
|
-
return buildSnapshotBeforeTurnIndex(
|
|
2157
|
+
return buildSnapshotBeforeTurnIndex(
|
|
2158
|
+
server,
|
|
2159
|
+
sessionId,
|
|
2160
|
+
beforeIndex,
|
|
2161
|
+
concurrency,
|
|
2162
|
+
turns
|
|
2163
|
+
);
|
|
2036
2164
|
}
|
|
2037
|
-
async function buildSnapshotBeforeTurnIndex(
|
|
2165
|
+
async function buildSnapshotBeforeTurnIndex(server, sessionId, turnIndex, _concurrency = DEFAULT_LIST_EVENTS_CONCURRENCY, orderedTurns) {
|
|
2038
2166
|
if (turnIndex <= 0) {
|
|
2039
2167
|
return createEmptySessionSnapshot();
|
|
2040
2168
|
}
|
|
2041
|
-
const turns = orderedTurns ?? await listSessionTurnsOrdered(
|
|
2169
|
+
const turns = orderedTurns ?? await listSessionTurnsOrdered(server, sessionId);
|
|
2042
2170
|
const turnsToInclude = turns.slice(0, turnIndex);
|
|
2043
2171
|
const lastTurnId = turnsToInclude.at(-1)?.id;
|
|
2044
2172
|
if (lastTurnId == null) {
|
|
2045
2173
|
return createEmptySessionSnapshot();
|
|
2046
2174
|
}
|
|
2047
|
-
const items = await fetchAllSessionEvents(
|
|
2175
|
+
const items = await fetchAllSessionEvents(server, sessionId, { lastTurnId });
|
|
2048
2176
|
const snapshot = createEmptySessionSnapshot();
|
|
2049
2177
|
ingestSessionEventsIntoSnapshot(snapshot, items);
|
|
2050
2178
|
return snapshot;
|
|
2051
2179
|
}
|
|
2052
|
-
async function resolveGatewayBranchPreviousTurnId(
|
|
2180
|
+
async function resolveGatewayBranchPreviousTurnId(server, sessionId, turnIndex, orderedTurns) {
|
|
2053
2181
|
if (turnIndex <= 0) {
|
|
2054
2182
|
return "none";
|
|
2055
2183
|
}
|
|
2056
|
-
const turns = orderedTurns ?? await listSessionTurnsOrdered(
|
|
2184
|
+
const turns = orderedTurns ?? await listSessionTurnsOrdered(server, sessionId);
|
|
2057
2185
|
return turns[turnIndex - 1]?.id ?? "none";
|
|
2058
2186
|
}
|
|
2059
|
-
async function resolveGatewayBranchPreviousTurnIdForTurn(
|
|
2060
|
-
const turns = await listSessionTurnsOrdered(
|
|
2187
|
+
async function resolveGatewayBranchPreviousTurnIdForTurn(server, sessionId, turnId) {
|
|
2188
|
+
const turns = await listSessionTurnsOrdered(server, sessionId);
|
|
2061
2189
|
const turnIndex = turns.findIndex((turn) => turn.id === turnId);
|
|
2062
|
-
return resolveGatewayBranchPreviousTurnId(
|
|
2190
|
+
return resolveGatewayBranchPreviousTurnId(server, sessionId, turnIndex, turns);
|
|
2063
2191
|
}
|
|
2064
|
-
async function listSessionTurnsOrdered(
|
|
2065
|
-
const turns =
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2192
|
+
async function listSessionTurnsOrdered(server, sessionId) {
|
|
2193
|
+
const turns = await drainListPages(
|
|
2194
|
+
(pageToken) => server.listTurns({
|
|
2195
|
+
sessionId,
|
|
2196
|
+
...pageToken != null ? { pageToken } : {}
|
|
2197
|
+
})
|
|
2198
|
+
);
|
|
2069
2199
|
turns.reverse();
|
|
2070
2200
|
return turns;
|
|
2071
2201
|
}
|
|
2072
|
-
async function buildTurnAssistantContent(turn, foldState) {
|
|
2202
|
+
async function buildTurnAssistantContent(server, sessionId, turn, foldState) {
|
|
2073
2203
|
const state = foldState ?? new PeerThreadFoldState();
|
|
2074
2204
|
const beforeCount = state.threads.get(ROOT_THREAD_ID)?.modelMessageIds.length ?? 0;
|
|
2075
|
-
await ingestTurnEventsIntoFold(
|
|
2205
|
+
await ingestTurnEventsIntoFold(server, sessionId, turn.id, state);
|
|
2076
2206
|
const afterIds = state.threads.get(ROOT_THREAD_ID)?.modelMessageIds ?? [];
|
|
2077
2207
|
const rootModelMessageIds = afterIds.slice(beforeCount);
|
|
2078
2208
|
return buildTurnUpdateFromFold(state, turn, rootModelMessageIds).content;
|
|
2079
2209
|
}
|
|
2080
|
-
async function convertTurnsToThreadMessages(
|
|
2081
|
-
const snapshot = await buildSnapshotFromSession(
|
|
2210
|
+
async function convertTurnsToThreadMessages(server, sessionId) {
|
|
2211
|
+
const snapshot = await buildSnapshotFromSession(server, sessionId);
|
|
2082
2212
|
const messages = projectSessionMessages(snapshot);
|
|
2083
2213
|
return {
|
|
2084
2214
|
messages,
|
|
@@ -2218,7 +2348,7 @@ function buildMcpAuthUpdate(pendingMcpAuth, foldState, groupRootBaseline) {
|
|
|
2218
2348
|
metadata: { custom: mcpAuthMessageCustom(pendingMcpAuth.mcpServers) }
|
|
2219
2349
|
};
|
|
2220
2350
|
}
|
|
2221
|
-
async function* streamTurnEvents(stream, foldState, groupRootBaseline) {
|
|
2351
|
+
async function* streamTurnEvents(stream, foldState, groupRootBaseline, onTurnIdAvailable) {
|
|
2222
2352
|
let pendingMcpAuth;
|
|
2223
2353
|
let sandboxId;
|
|
2224
2354
|
let sandboxIdYielded = false;
|
|
@@ -2239,6 +2369,10 @@ async function* streamTurnEvents(stream, foldState, groupRootBaseline) {
|
|
|
2239
2369
|
};
|
|
2240
2370
|
for await (const data of stream) {
|
|
2241
2371
|
const event = data.event;
|
|
2372
|
+
if (event.type === "turn.created") {
|
|
2373
|
+
onTurnIdAvailable?.(event.turnId);
|
|
2374
|
+
continue;
|
|
2375
|
+
}
|
|
2242
2376
|
if (event.type === "sandbox.created") {
|
|
2243
2377
|
sandboxId = event.sandboxId;
|
|
2244
2378
|
continue;
|
|
@@ -2326,30 +2460,25 @@ function repositoryItemsFromMessages(messages) {
|
|
|
2326
2460
|
return items;
|
|
2327
2461
|
}
|
|
2328
2462
|
|
|
2329
|
-
// src/private/getGatewayFromPrivateClient.ts
|
|
2330
|
-
function getGatewayFromPrivateClient(privateClient) {
|
|
2331
|
-
const internal = privateClient;
|
|
2332
|
-
if (internal.client == null) {
|
|
2333
|
-
throw new Error("PrivateAgentSessionClient is missing an internal gateway client.");
|
|
2334
|
-
}
|
|
2335
|
-
return internal.client;
|
|
2336
|
-
}
|
|
2337
|
-
|
|
2338
2463
|
// src/private/draftSessionBridge.ts
|
|
2339
2464
|
var DRAFT_SESSION_LAST_UPDATED_AT_HEADER = "x-tfy-session-last-updated-at";
|
|
2340
|
-
function createDraftSessionBridge(
|
|
2465
|
+
function createDraftSessionBridge(server) {
|
|
2341
2466
|
return {
|
|
2342
2467
|
async getDraftAgentSpec(draftSessionId) {
|
|
2343
|
-
const
|
|
2344
|
-
|
|
2468
|
+
const session = await server.getSession({ sessionId: draftSessionId });
|
|
2469
|
+
if (session.agentSpec == null) {
|
|
2470
|
+
throw new Error(
|
|
2471
|
+
`Session ${draftSessionId} has no agentSpec (isMutable=${session.isMutable}).`
|
|
2472
|
+
);
|
|
2473
|
+
}
|
|
2474
|
+
return session.agentSpec;
|
|
2345
2475
|
},
|
|
2346
2476
|
async syncAgentSpec(draftSessionId, agentSpec) {
|
|
2347
|
-
const
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
return response.data.updatedAt;
|
|
2477
|
+
const updated = await server.updateSession({
|
|
2478
|
+
sessionId: draftSessionId,
|
|
2479
|
+
agentSpec
|
|
2480
|
+
});
|
|
2481
|
+
return updated.updatedAt;
|
|
2353
2482
|
}
|
|
2354
2483
|
};
|
|
2355
2484
|
}
|
|
@@ -2385,39 +2514,43 @@ function sessionListStartTimestamp() {
|
|
|
2385
2514
|
// src/private/truefoundryDraftThreadListAdapter.ts
|
|
2386
2515
|
var THREAD_LIST_PAGE_SIZE = 20;
|
|
2387
2516
|
function createTrueFoundryDraftThreadListAdapter(options) {
|
|
2388
|
-
const {
|
|
2517
|
+
const { server, defaultAgentSpec, getAgentSpec } = options;
|
|
2389
2518
|
return {
|
|
2390
2519
|
async list({ after } = {}) {
|
|
2391
|
-
const page = await
|
|
2520
|
+
const page = await server.listSessions({
|
|
2392
2521
|
limit: THREAD_LIST_PAGE_SIZE,
|
|
2393
2522
|
pageToken: after,
|
|
2394
2523
|
startTimestamp: sessionListStartTimestamp()
|
|
2395
2524
|
});
|
|
2396
|
-
const threads = page.data.map((draft) => ({
|
|
2525
|
+
const threads = page.data.filter((session) => session.isMutable).map((draft) => ({
|
|
2397
2526
|
status: "regular",
|
|
2398
2527
|
remoteId: draft.id,
|
|
2399
|
-
title: draftSessionTitle(
|
|
2528
|
+
title: draftSessionTitle({
|
|
2529
|
+
title: draft.title,
|
|
2530
|
+
agentSpec: draft.agentSpec ?? defaultAgentSpec
|
|
2531
|
+
}),
|
|
2400
2532
|
lastMessageAt: new Date(draft.updatedAt)
|
|
2401
2533
|
}));
|
|
2402
2534
|
return {
|
|
2403
2535
|
threads,
|
|
2404
|
-
nextCursor: page.
|
|
2536
|
+
nextCursor: page.nextPageToken ?? void 0
|
|
2405
2537
|
};
|
|
2406
2538
|
},
|
|
2407
2539
|
async initialize(_threadId) {
|
|
2408
|
-
const draft = await
|
|
2540
|
+
const draft = await server.createSession({
|
|
2409
2541
|
agentSpec: getAgentSpec?.() ?? defaultAgentSpec
|
|
2410
2542
|
});
|
|
2411
2543
|
return { remoteId: draft.id, externalId: void 0 };
|
|
2412
2544
|
},
|
|
2413
2545
|
async fetch(remoteId) {
|
|
2414
|
-
const draft = await
|
|
2415
|
-
draftSessionId: remoteId
|
|
2416
|
-
});
|
|
2546
|
+
const draft = await server.getSession({ sessionId: remoteId });
|
|
2417
2547
|
return {
|
|
2418
2548
|
status: "regular",
|
|
2419
2549
|
remoteId: draft.id,
|
|
2420
|
-
title: draftSessionTitle(
|
|
2550
|
+
title: draftSessionTitle({
|
|
2551
|
+
title: draft.title,
|
|
2552
|
+
agentSpec: draft.agentSpec ?? defaultAgentSpec
|
|
2553
|
+
}),
|
|
2421
2554
|
lastMessageAt: new Date(draft.updatedAt)
|
|
2422
2555
|
};
|
|
2423
2556
|
},
|
|
@@ -2450,30 +2583,12 @@ var EMPTY_DRAFT_EXTRAS = {
|
|
|
2450
2583
|
}
|
|
2451
2584
|
};
|
|
2452
2585
|
|
|
2453
|
-
// src/private/bindDraftAgentSession.ts
|
|
2454
|
-
var inflightByDraftId = /* @__PURE__ */ new Map();
|
|
2455
|
-
async function bindDraftAgentSession(privateClient, draftSessionId) {
|
|
2456
|
-
let inflight = inflightByDraftId.get(draftSessionId);
|
|
2457
|
-
if (inflight == null) {
|
|
2458
|
-
inflight = privateClient.getDraftSession({ draftSessionId }).then((draft) => draft).finally(() => {
|
|
2459
|
-
if (inflightByDraftId.get(draftSessionId) === inflight) {
|
|
2460
|
-
inflightByDraftId.delete(draftSessionId);
|
|
2461
|
-
}
|
|
2462
|
-
});
|
|
2463
|
-
inflightByDraftId.set(draftSessionId, inflight);
|
|
2464
|
-
}
|
|
2465
|
-
return inflight;
|
|
2466
|
-
}
|
|
2467
|
-
|
|
2468
2586
|
// src/sessions.ts
|
|
2469
2587
|
var inflightBySessionId = /* @__PURE__ */ new Map();
|
|
2470
|
-
function getSession(
|
|
2471
|
-
if (options?.privateClient != null) {
|
|
2472
|
-
return bindDraftAgentSession(options.privateClient, sessionId);
|
|
2473
|
-
}
|
|
2588
|
+
function getSession(server, sessionId) {
|
|
2474
2589
|
let inflight = inflightBySessionId.get(sessionId);
|
|
2475
2590
|
if (inflight == null) {
|
|
2476
|
-
inflight =
|
|
2591
|
+
inflight = server.getSession({ sessionId }).finally(() => {
|
|
2477
2592
|
if (inflightBySessionId.get(sessionId) === inflight) {
|
|
2478
2593
|
inflightBySessionId.delete(sessionId);
|
|
2479
2594
|
}
|
|
@@ -2486,10 +2601,10 @@ function getSession(client, sessionId, options) {
|
|
|
2486
2601
|
// src/truefoundryThreadListAdapter.ts
|
|
2487
2602
|
var THREAD_LIST_PAGE_SIZE2 = 20;
|
|
2488
2603
|
function createTrueFoundryThreadListAdapter(options) {
|
|
2489
|
-
const {
|
|
2604
|
+
const { server, agentName } = options;
|
|
2490
2605
|
return {
|
|
2491
2606
|
async list({ after } = {}) {
|
|
2492
|
-
const page = await
|
|
2607
|
+
const page = await server.listSessions({
|
|
2493
2608
|
agentName,
|
|
2494
2609
|
limit: THREAD_LIST_PAGE_SIZE2,
|
|
2495
2610
|
pageToken: after,
|
|
@@ -2503,15 +2618,15 @@ function createTrueFoundryThreadListAdapter(options) {
|
|
|
2503
2618
|
}));
|
|
2504
2619
|
return {
|
|
2505
2620
|
threads,
|
|
2506
|
-
nextCursor: page.
|
|
2621
|
+
nextCursor: page.nextPageToken ?? void 0
|
|
2507
2622
|
};
|
|
2508
2623
|
},
|
|
2509
2624
|
async initialize(_threadId) {
|
|
2510
|
-
const session = await
|
|
2625
|
+
const session = await server.createSession({ agentName });
|
|
2511
2626
|
return { remoteId: session.id, externalId: void 0 };
|
|
2512
2627
|
},
|
|
2513
2628
|
async fetch(remoteId) {
|
|
2514
|
-
const session = await getSession(
|
|
2629
|
+
const session = await getSession(server, remoteId);
|
|
2515
2630
|
return {
|
|
2516
2631
|
status: "regular",
|
|
2517
2632
|
remoteId: session.id,
|
|
@@ -2550,15 +2665,9 @@ function resolveTrueFoundryAgentConfig(options) {
|
|
|
2550
2665
|
}
|
|
2551
2666
|
function resolveTrueFoundryAgentRuntimeOptions(options) {
|
|
2552
2667
|
const agent = resolveTrueFoundryAgentConfig(options);
|
|
2553
|
-
if (agent.mode === "draft" && options.privateClient == null) {
|
|
2554
|
-
throw new Error(
|
|
2555
|
-
"Draft agent mode requires a `privateClient` PrivateAgentSessionClient."
|
|
2556
|
-
);
|
|
2557
|
-
}
|
|
2558
2668
|
return {
|
|
2559
2669
|
...options,
|
|
2560
|
-
agent
|
|
2561
|
-
privateClient: options.privateClient
|
|
2670
|
+
agent
|
|
2562
2671
|
};
|
|
2563
2672
|
}
|
|
2564
2673
|
|
|
@@ -2769,18 +2878,15 @@ import { useCallback as useCallback2, useEffect as useEffect2, useMemo as useMem
|
|
|
2769
2878
|
|
|
2770
2879
|
// src/loadSessionSnapshot.ts
|
|
2771
2880
|
var inflightBySessionId2 = /* @__PURE__ */ new Map();
|
|
2772
|
-
function loadSessionSnapshot(
|
|
2773
|
-
|
|
2774
|
-
let inflight = inflightBySessionId2.get(cacheKey);
|
|
2881
|
+
function loadSessionSnapshot(server, sessionId, onProgress) {
|
|
2882
|
+
let inflight = inflightBySessionId2.get(sessionId);
|
|
2775
2883
|
if (inflight == null) {
|
|
2776
|
-
inflight = getSession(
|
|
2777
|
-
(
|
|
2778
|
-
|
|
2779
|
-
if (inflightBySessionId2.get(cacheKey) === inflight) {
|
|
2780
|
-
inflightBySessionId2.delete(cacheKey);
|
|
2884
|
+
inflight = getSession(server, sessionId).then(() => buildSnapshotFromSessionEvents(server, sessionId, onProgress)).finally(() => {
|
|
2885
|
+
if (inflightBySessionId2.get(sessionId) === inflight) {
|
|
2886
|
+
inflightBySessionId2.delete(sessionId);
|
|
2781
2887
|
}
|
|
2782
2888
|
});
|
|
2783
|
-
inflightBySessionId2.set(
|
|
2889
|
+
inflightBySessionId2.set(sessionId, inflight);
|
|
2784
2890
|
}
|
|
2785
2891
|
return inflight;
|
|
2786
2892
|
}
|
|
@@ -2818,9 +2924,9 @@ function buildTurnInput(options) {
|
|
|
2818
2924
|
}
|
|
2819
2925
|
return [{ type: "user.message", content: options.userMessage ?? "" }];
|
|
2820
2926
|
}
|
|
2821
|
-
function bindAbort(
|
|
2927
|
+
function bindAbort(server, sessionId, abortSignal) {
|
|
2822
2928
|
const onAbort = () => {
|
|
2823
|
-
void
|
|
2929
|
+
void server.cancelSession({ sessionId }).catch(() => void 0);
|
|
2824
2930
|
};
|
|
2825
2931
|
if (abortSignal.aborted) {
|
|
2826
2932
|
onAbort();
|
|
@@ -2829,40 +2935,35 @@ function bindAbort(session, abortSignal) {
|
|
|
2829
2935
|
abortSignal.addEventListener("abort", onAbort, { once: true });
|
|
2830
2936
|
return onAbort;
|
|
2831
2937
|
}
|
|
2832
|
-
async function* streamTurnContent(
|
|
2833
|
-
const
|
|
2834
|
-
input: buildTurnInput(options),
|
|
2835
|
-
previousTurnId: options.previousTurnId ?? "auto"
|
|
2836
|
-
});
|
|
2837
|
-
const onAbort = bindAbort(session, abortSignal);
|
|
2938
|
+
async function* streamTurnContent(server, sessionId, foldState, options, abortSignal, groupRootBaseline, onTurnIdAvailable) {
|
|
2939
|
+
const onAbort = bindAbort(server, sessionId, abortSignal);
|
|
2838
2940
|
if (abortSignal.aborted) {
|
|
2839
2941
|
return;
|
|
2840
2942
|
}
|
|
2841
2943
|
let turnIdNotified = false;
|
|
2842
|
-
const
|
|
2843
|
-
if (!turnIdNotified
|
|
2844
|
-
onTurnIdAvailable?.(
|
|
2944
|
+
const notifyTurnId = (turnId) => {
|
|
2945
|
+
if (!turnIdNotified) {
|
|
2946
|
+
onTurnIdAvailable?.(turnId);
|
|
2845
2947
|
turnIdNotified = true;
|
|
2846
2948
|
}
|
|
2847
2949
|
};
|
|
2950
|
+
const stream = server.prepareAndExecuteTurn({
|
|
2951
|
+
sessionId,
|
|
2952
|
+
input: buildTurnInput(options),
|
|
2953
|
+
previousTurnId: options.previousTurnId ?? "auto",
|
|
2954
|
+
abortSignal,
|
|
2955
|
+
...options.headers != null ? { headers: options.headers } : {}
|
|
2956
|
+
});
|
|
2848
2957
|
try {
|
|
2849
2958
|
for await (const update of streamTurnEvents(
|
|
2850
|
-
|
|
2851
|
-
{ stream: true },
|
|
2852
|
-
{
|
|
2853
|
-
abortSignal,
|
|
2854
|
-
...options.headers != null ? { headers: options.headers } : {}
|
|
2855
|
-
}
|
|
2856
|
-
),
|
|
2959
|
+
stream,
|
|
2857
2960
|
foldState,
|
|
2858
|
-
groupRootBaseline
|
|
2961
|
+
groupRootBaseline,
|
|
2962
|
+
notifyTurnId
|
|
2859
2963
|
)) {
|
|
2860
|
-
notifyTurnIdIfAvailable();
|
|
2861
2964
|
yield update;
|
|
2862
2965
|
}
|
|
2863
|
-
notifyTurnIdIfAvailable();
|
|
2864
2966
|
} catch (error) {
|
|
2865
|
-
notifyTurnIdIfAvailable();
|
|
2866
2967
|
if (error instanceof Error && error.name === "AbortError") {
|
|
2867
2968
|
return;
|
|
2868
2969
|
}
|
|
@@ -2871,9 +2972,14 @@ async function* streamTurnContent(session, foldState, options, abortSignal, grou
|
|
|
2871
2972
|
abortSignal.removeEventListener("abort", onAbort);
|
|
2872
2973
|
}
|
|
2873
2974
|
}
|
|
2874
|
-
async function* resumeTurnStream(
|
|
2975
|
+
async function* resumeTurnStream(server, sessionId, turnId, foldState, abortSignal, afterSequenceNumber, groupRootBaseline) {
|
|
2976
|
+
if (server.subscribeToTurn == null) {
|
|
2977
|
+
throw new Error(
|
|
2978
|
+
"resumeTurnStream requires AgentChatServer.subscribeToTurn"
|
|
2979
|
+
);
|
|
2980
|
+
}
|
|
2875
2981
|
const onAbort = () => {
|
|
2876
|
-
void
|
|
2982
|
+
void server.cancelSession({ sessionId }).catch(() => void 0);
|
|
2877
2983
|
};
|
|
2878
2984
|
if (abortSignal.aborted) {
|
|
2879
2985
|
onAbort();
|
|
@@ -2882,10 +2988,12 @@ async function* resumeTurnStream(turn, foldState, abortSignal, afterSequenceNumb
|
|
|
2882
2988
|
abortSignal.addEventListener("abort", onAbort, { once: true });
|
|
2883
2989
|
try {
|
|
2884
2990
|
yield* streamTurnEvents(
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2991
|
+
server.subscribeToTurn({
|
|
2992
|
+
sessionId,
|
|
2993
|
+
turnId,
|
|
2994
|
+
...afterSequenceNumber != null ? { afterSequenceNumber } : {},
|
|
2995
|
+
abortSignal
|
|
2996
|
+
}),
|
|
2889
2997
|
foldState,
|
|
2890
2998
|
groupRootBaseline
|
|
2891
2999
|
);
|
|
@@ -3021,20 +3129,15 @@ function resolveTurnInput(snapshot, turnId) {
|
|
|
3021
3129
|
return void 0;
|
|
3022
3130
|
}
|
|
3023
3131
|
function useTrueFoundryAgentMessages({
|
|
3024
|
-
|
|
3132
|
+
server,
|
|
3025
3133
|
sessionId,
|
|
3026
3134
|
isMain,
|
|
3027
3135
|
listEventsConcurrency,
|
|
3028
3136
|
onError,
|
|
3029
3137
|
initializeSession,
|
|
3030
3138
|
resolveConversationSessionId,
|
|
3031
|
-
privateClient,
|
|
3032
3139
|
getTurnHeaders
|
|
3033
3140
|
}) {
|
|
3034
|
-
const sessionOptions = useMemo2(
|
|
3035
|
-
() => privateClient != null ? { privateClient } : void 0,
|
|
3036
|
-
[privateClient]
|
|
3037
|
-
);
|
|
3038
3141
|
const [snapshot, setSnapshot] = useState2(createEmptySessionSnapshot);
|
|
3039
3142
|
const [isRunning, setIsRunning] = useState2(false);
|
|
3040
3143
|
const [isLoading, setIsLoading] = useState2(false);
|
|
@@ -3194,9 +3297,8 @@ function useTrueFoundryAgentMessages({
|
|
|
3194
3297
|
resolveConversationSessionIdRef.current
|
|
3195
3298
|
);
|
|
3196
3299
|
const loadedSnapshot = await loadSessionSnapshot(
|
|
3197
|
-
|
|
3300
|
+
server,
|
|
3198
3301
|
conversationSessionId,
|
|
3199
|
-
sessionOptions,
|
|
3200
3302
|
(snap) => {
|
|
3201
3303
|
if (generation === loadGenerationRef.current) {
|
|
3202
3304
|
setSnapshot(snap);
|
|
@@ -3215,7 +3317,9 @@ function useTrueFoundryAgentMessages({
|
|
|
3215
3317
|
const isContinuation = !extractTurnUserText(turn.input);
|
|
3216
3318
|
void runStream(
|
|
3217
3319
|
(signal) => resumeTurnStream(
|
|
3218
|
-
|
|
3320
|
+
server,
|
|
3321
|
+
conversationSessionId,
|
|
3322
|
+
turn.id,
|
|
3219
3323
|
loadedSnapshot.fold,
|
|
3220
3324
|
signal,
|
|
3221
3325
|
void 0,
|
|
@@ -3235,7 +3339,7 @@ function useTrueFoundryAgentMessages({
|
|
|
3235
3339
|
setIsLoading(false);
|
|
3236
3340
|
}
|
|
3237
3341
|
}
|
|
3238
|
-
}, [
|
|
3342
|
+
}, [server, runStream, sessionId, loadRetryTrigger, isMain]);
|
|
3239
3343
|
useEffect2(() => {
|
|
3240
3344
|
void load().catch(() => void 0);
|
|
3241
3345
|
}, [load]);
|
|
@@ -3254,7 +3358,6 @@ function useTrueFoundryAgentMessages({
|
|
|
3254
3358
|
activeSessionId,
|
|
3255
3359
|
resolveConversationSessionIdRef.current
|
|
3256
3360
|
);
|
|
3257
|
-
const session = await getSession(client, conversationSessionId, sessionOptions);
|
|
3258
3361
|
const turnHeaders = await getTurnHeadersRef.current?.();
|
|
3259
3362
|
const streamHeaders = turnHeaders != null ? { headers: turnHeaders } : {};
|
|
3260
3363
|
const isContinuation = "inputs" in options || "resumeMcpAuth" in options && options.resumeMcpAuth === true;
|
|
@@ -3315,7 +3418,8 @@ function useTrueFoundryAgentMessages({
|
|
|
3315
3418
|
(signal) => {
|
|
3316
3419
|
if ("inputs" in options) {
|
|
3317
3420
|
return streamTurnContent(
|
|
3318
|
-
|
|
3421
|
+
server,
|
|
3422
|
+
conversationSessionId,
|
|
3319
3423
|
snapshotRef.current.fold,
|
|
3320
3424
|
{ inputs: options.inputs, ...streamHeaders },
|
|
3321
3425
|
signal,
|
|
@@ -3324,7 +3428,8 @@ function useTrueFoundryAgentMessages({
|
|
|
3324
3428
|
}
|
|
3325
3429
|
if ("resumeMcpAuth" in options) {
|
|
3326
3430
|
return streamTurnContent(
|
|
3327
|
-
|
|
3431
|
+
server,
|
|
3432
|
+
conversationSessionId,
|
|
3328
3433
|
snapshotRef.current.fold,
|
|
3329
3434
|
{ resumeMcpAuth: true, ...streamHeaders },
|
|
3330
3435
|
signal,
|
|
@@ -3332,11 +3437,12 @@ function useTrueFoundryAgentMessages({
|
|
|
3332
3437
|
);
|
|
3333
3438
|
}
|
|
3334
3439
|
return streamTurnContent(
|
|
3335
|
-
|
|
3440
|
+
server,
|
|
3441
|
+
conversationSessionId,
|
|
3336
3442
|
snapshotRef.current.fold,
|
|
3337
3443
|
{
|
|
3338
3444
|
userMessage: options.userMessage,
|
|
3339
|
-
...options.previousTurnId !== void 0 ? { previousTurnId: options.previousTurnId } : isFirstTurnInSession ? { previousTurnId: "none" } : {},
|
|
3445
|
+
...options.previousTurnId !== void 0 ? { previousTurnId: options.previousTurnId ?? "none" } : isFirstTurnInSession ? { previousTurnId: "none" } : {},
|
|
3340
3446
|
...streamHeaders
|
|
3341
3447
|
},
|
|
3342
3448
|
signal,
|
|
@@ -3362,7 +3468,7 @@ function useTrueFoundryAgentMessages({
|
|
|
3362
3468
|
isContinuation
|
|
3363
3469
|
);
|
|
3364
3470
|
},
|
|
3365
|
-
[
|
|
3471
|
+
[server, runStream, sessionId]
|
|
3366
3472
|
);
|
|
3367
3473
|
const cancel = useCallback2(async () => {
|
|
3368
3474
|
if (sessionId == null) {
|
|
@@ -3373,10 +3479,9 @@ function useTrueFoundryAgentMessages({
|
|
|
3373
3479
|
sessionId,
|
|
3374
3480
|
resolveConversationSessionIdRef.current
|
|
3375
3481
|
);
|
|
3376
|
-
|
|
3377
|
-
await session.cancel().catch(() => void 0);
|
|
3482
|
+
await server.cancelSession({ sessionId: conversationSessionId }).catch(() => void 0);
|
|
3378
3483
|
await activeRunRef.current?.catch(() => void 0);
|
|
3379
|
-
}, [
|
|
3484
|
+
}, [server, sessionId]);
|
|
3380
3485
|
const isRunningRef = useRef2(isRunning);
|
|
3381
3486
|
isRunningRef.current = isRunning;
|
|
3382
3487
|
const trySendCollectedRequiredActions = useCallback2(
|
|
@@ -3438,7 +3543,9 @@ function useTrueFoundryAgentMessages({
|
|
|
3438
3543
|
}
|
|
3439
3544
|
await runStream(
|
|
3440
3545
|
(signal) => resumeTurnStream(
|
|
3441
|
-
|
|
3546
|
+
server,
|
|
3547
|
+
turn.sessionId,
|
|
3548
|
+
turn.id,
|
|
3442
3549
|
snapshotRef.current.fold,
|
|
3443
3550
|
signal,
|
|
3444
3551
|
void 0,
|
|
@@ -3447,7 +3554,7 @@ function useTrueFoundryAgentMessages({
|
|
|
3447
3554
|
{ current: turn.id },
|
|
3448
3555
|
true
|
|
3449
3556
|
);
|
|
3450
|
-
}, [runStream]);
|
|
3557
|
+
}, [runStream, server]);
|
|
3451
3558
|
const branchFromTurn = useCallback2(
|
|
3452
3559
|
async (turnId, userMessage) => {
|
|
3453
3560
|
let activeSessionId = sessionId;
|
|
@@ -3461,13 +3568,14 @@ function useTrueFoundryAgentMessages({
|
|
|
3461
3568
|
activeSessionId,
|
|
3462
3569
|
resolveConversationSessionIdRef.current
|
|
3463
3570
|
);
|
|
3464
|
-
const session = await getSession(client, conversationSessionId, sessionOptions);
|
|
3465
3571
|
const previousTurnId = await resolveGatewayBranchPreviousTurnIdForTurn(
|
|
3466
|
-
|
|
3572
|
+
server,
|
|
3573
|
+
conversationSessionId,
|
|
3467
3574
|
turnId
|
|
3468
3575
|
);
|
|
3469
3576
|
const rewound = await buildSnapshotBeforeTurn(
|
|
3470
|
-
|
|
3577
|
+
server,
|
|
3578
|
+
conversationSessionId,
|
|
3471
3579
|
turnId,
|
|
3472
3580
|
listEventsConcurrency
|
|
3473
3581
|
);
|
|
@@ -3482,11 +3590,10 @@ function useTrueFoundryAgentMessages({
|
|
|
3482
3590
|
},
|
|
3483
3591
|
[
|
|
3484
3592
|
cancel,
|
|
3485
|
-
|
|
3593
|
+
server,
|
|
3486
3594
|
listEventsConcurrency,
|
|
3487
3595
|
sendTurn,
|
|
3488
|
-
sessionId
|
|
3489
|
-
sessionOptions
|
|
3596
|
+
sessionId
|
|
3490
3597
|
]
|
|
3491
3598
|
);
|
|
3492
3599
|
const resetFromTurn = useCallback2(
|
|
@@ -3542,13 +3649,9 @@ function useTrueFoundryAgentMessages({
|
|
|
3542
3649
|
sessionId,
|
|
3543
3650
|
resolveConversationSessionIdRef.current
|
|
3544
3651
|
);
|
|
3545
|
-
const session = await getSession(
|
|
3546
|
-
client,
|
|
3547
|
-
conversationSessionId,
|
|
3548
|
-
sessionOptions
|
|
3549
|
-
);
|
|
3550
3652
|
const next = await prependOlderSessionHistory(
|
|
3551
|
-
|
|
3653
|
+
server,
|
|
3654
|
+
conversationSessionId,
|
|
3552
3655
|
snapshotRef.current
|
|
3553
3656
|
);
|
|
3554
3657
|
if (generation !== loadGenerationRef.current) {
|
|
@@ -3569,7 +3672,7 @@ function useTrueFoundryAgentMessages({
|
|
|
3569
3672
|
})();
|
|
3570
3673
|
loadOlderInflightRef.current = run;
|
|
3571
3674
|
return run;
|
|
3572
|
-
}, [
|
|
3675
|
+
}, [server, isMain, sessionId]);
|
|
3573
3676
|
return {
|
|
3574
3677
|
messages,
|
|
3575
3678
|
isRunning,
|
|
@@ -3592,16 +3695,15 @@ function useTrueFoundryAgentMessages({
|
|
|
3592
3695
|
// src/useTrueFoundryAgentRuntime.ts
|
|
3593
3696
|
function useTrueFoundryAgentRuntimeImpl(options, pendingAgentSpecRef) {
|
|
3594
3697
|
const {
|
|
3595
|
-
|
|
3698
|
+
server,
|
|
3596
3699
|
agent,
|
|
3597
|
-
privateClient,
|
|
3598
3700
|
adapters,
|
|
3599
3701
|
onError,
|
|
3600
3702
|
listEventsConcurrency,
|
|
3601
3703
|
...sharedOptions
|
|
3602
3704
|
} = options;
|
|
3603
3705
|
const draftBridgeRef = useRef3(
|
|
3604
|
-
agent.mode === "draft"
|
|
3706
|
+
agent.mode === "draft" ? createDraftSessionBridge(server) : null
|
|
3605
3707
|
);
|
|
3606
3708
|
const draftSessionId = useAuiState(
|
|
3607
3709
|
(state) => agent.mode === "draft" ? state.threadListItem.remoteId ?? void 0 : void 0
|
|
@@ -3652,13 +3754,12 @@ function useTrueFoundryAgentRuntimeImpl(options, pendingAgentSpecRef) {
|
|
|
3652
3754
|
resetFromTurn,
|
|
3653
3755
|
retryLoad
|
|
3654
3756
|
} = useTrueFoundryAgentMessages({
|
|
3655
|
-
|
|
3757
|
+
server,
|
|
3656
3758
|
sessionId,
|
|
3657
3759
|
isMain,
|
|
3658
3760
|
listEventsConcurrency,
|
|
3659
3761
|
onError,
|
|
3660
3762
|
initializeSession,
|
|
3661
|
-
privateClient: agent.mode === "draft" ? privateClient : void 0,
|
|
3662
3763
|
getTurnHeaders: agent.mode === "draft" ? getTurnHeaders : void 0
|
|
3663
3764
|
});
|
|
3664
3765
|
if (agent.mode === "draft" && draftSpec.agentSpec != null) {
|
|
@@ -3680,9 +3781,9 @@ function useTrueFoundryAgentRuntimeImpl(options, pendingAgentSpecRef) {
|
|
|
3680
3781
|
);
|
|
3681
3782
|
const downloadSandboxFile = useCallback3(
|
|
3682
3783
|
async (path) => {
|
|
3683
|
-
if (
|
|
3784
|
+
if (server.downloadSandboxFile == null) {
|
|
3684
3785
|
const error = new Error(
|
|
3685
|
-
"Downloading a sandbox file requires
|
|
3786
|
+
"Downloading a sandbox file requires AgentChatServer.downloadSandboxFile."
|
|
3686
3787
|
);
|
|
3687
3788
|
onError?.(error);
|
|
3688
3789
|
throw error;
|
|
@@ -3692,10 +3793,9 @@ function useTrueFoundryAgentRuntimeImpl(options, pendingAgentSpecRef) {
|
|
|
3692
3793
|
onError?.(error);
|
|
3693
3794
|
throw error;
|
|
3694
3795
|
}
|
|
3695
|
-
|
|
3696
|
-
return await response.blob();
|
|
3796
|
+
return await server.downloadSandboxFile(sandboxId, { path });
|
|
3697
3797
|
},
|
|
3698
|
-
[
|
|
3798
|
+
[server, sandboxId, onError]
|
|
3699
3799
|
);
|
|
3700
3800
|
const draftExtras = useMemo3(() => {
|
|
3701
3801
|
if (agent.mode !== "draft") {
|
|
@@ -3780,7 +3880,7 @@ function useTrueFoundryAgentRuntimeImpl(options, pendingAgentSpecRef) {
|
|
|
3780
3880
|
}
|
|
3781
3881
|
function useTrueFoundryAgentRuntime(options) {
|
|
3782
3882
|
const resolved = resolveTrueFoundryAgentRuntimeOptions(options);
|
|
3783
|
-
const {
|
|
3883
|
+
const { server, agent } = resolved;
|
|
3784
3884
|
const pendingAgentSpecRef = useRef3(
|
|
3785
3885
|
agent.mode === "draft" ? agent.defaultAgentSpec : void 0
|
|
3786
3886
|
);
|
|
@@ -3788,23 +3888,18 @@ function useTrueFoundryAgentRuntime(options) {
|
|
|
3788
3888
|
const namedAgentName = agent.mode === "named" ? agent.agentName : void 0;
|
|
3789
3889
|
const threadListAdapter = useMemo3(() => {
|
|
3790
3890
|
if (agentMode === "draft") {
|
|
3791
|
-
if (privateClient == null) {
|
|
3792
|
-
throw new Error(
|
|
3793
|
-
"Draft agent mode requires a `privateClient` PrivateAgentSessionClient."
|
|
3794
|
-
);
|
|
3795
|
-
}
|
|
3796
3891
|
const draftAgent = agent;
|
|
3797
3892
|
return createTrueFoundryDraftThreadListAdapter({
|
|
3798
|
-
|
|
3893
|
+
server,
|
|
3799
3894
|
defaultAgentSpec: draftAgent.defaultAgentSpec,
|
|
3800
3895
|
getAgentSpec: () => pendingAgentSpecRef.current ?? draftAgent.defaultAgentSpec
|
|
3801
3896
|
});
|
|
3802
3897
|
}
|
|
3803
3898
|
return createTrueFoundryThreadListAdapter({
|
|
3804
|
-
|
|
3899
|
+
server,
|
|
3805
3900
|
agentName: namedAgentName
|
|
3806
3901
|
});
|
|
3807
|
-
}, [agentMode, namedAgentName,
|
|
3902
|
+
}, [agentMode, namedAgentName, server]);
|
|
3808
3903
|
return useRemoteThreadListRuntime({
|
|
3809
3904
|
allowNesting: true,
|
|
3810
3905
|
adapter: threadListAdapter,
|
|
@@ -3818,16 +3913,19 @@ function useTrueFoundryAgentRuntime(options) {
|
|
|
3818
3913
|
// src/truefoundryOwnedSessionsThreadListAdapter.ts
|
|
3819
3914
|
var THREAD_LIST_PAGE_SIZE3 = 20;
|
|
3820
3915
|
function ownedSessionTitle(session) {
|
|
3821
|
-
if (session.
|
|
3822
|
-
return draftSessionTitle(
|
|
3916
|
+
if (session.isMutable && session.agentSpec != null) {
|
|
3917
|
+
return draftSessionTitle({
|
|
3918
|
+
title: session.title,
|
|
3919
|
+
agentSpec: session.agentSpec
|
|
3920
|
+
});
|
|
3823
3921
|
}
|
|
3824
|
-
return session.title ?? session.agentName;
|
|
3922
|
+
return session.title ?? session.agentName ?? session.id;
|
|
3825
3923
|
}
|
|
3826
3924
|
function createTrueFoundryOwnedSessionsThreadListAdapter(options) {
|
|
3827
|
-
const {
|
|
3925
|
+
const { server } = options;
|
|
3828
3926
|
return {
|
|
3829
3927
|
async list({ after } = {}) {
|
|
3830
|
-
const page = await
|
|
3928
|
+
const page = await server.listSessions({
|
|
3831
3929
|
limit: THREAD_LIST_PAGE_SIZE3,
|
|
3832
3930
|
pageToken: after,
|
|
3833
3931
|
startTimestamp: sessionListStartTimestamp()
|
|
@@ -3840,7 +3938,7 @@ function createTrueFoundryOwnedSessionsThreadListAdapter(options) {
|
|
|
3840
3938
|
}));
|
|
3841
3939
|
return {
|
|
3842
3940
|
threads,
|
|
3843
|
-
nextCursor: page.
|
|
3941
|
+
nextCursor: page.nextPageToken ?? void 0
|
|
3844
3942
|
};
|
|
3845
3943
|
},
|
|
3846
3944
|
async initialize() {
|
|
@@ -3849,14 +3947,12 @@ function createTrueFoundryOwnedSessionsThreadListAdapter(options) {
|
|
|
3849
3947
|
);
|
|
3850
3948
|
},
|
|
3851
3949
|
async fetch(remoteId) {
|
|
3852
|
-
const
|
|
3853
|
-
draftSessionId: remoteId
|
|
3854
|
-
});
|
|
3950
|
+
const session = await server.getSession({ sessionId: remoteId });
|
|
3855
3951
|
return {
|
|
3856
3952
|
status: "regular",
|
|
3857
|
-
remoteId:
|
|
3858
|
-
title:
|
|
3859
|
-
lastMessageAt: new Date(
|
|
3953
|
+
remoteId: session.id,
|
|
3954
|
+
title: ownedSessionTitle(session),
|
|
3955
|
+
lastMessageAt: new Date(session.updatedAt)
|
|
3860
3956
|
};
|
|
3861
3957
|
},
|
|
3862
3958
|
async rename() {
|
|
@@ -3873,9 +3969,6 @@ function createTrueFoundryOwnedSessionsThreadListAdapter(options) {
|
|
|
3873
3969
|
};
|
|
3874
3970
|
}
|
|
3875
3971
|
|
|
3876
|
-
// src/index.ts
|
|
3877
|
-
import { PrivateAgentSessionClient } from "truefoundry-gateway-sdk/agents/private";
|
|
3878
|
-
|
|
3879
3972
|
// src/hooks.ts
|
|
3880
3973
|
import { useMemo as useMemo4 } from "react";
|
|
3881
3974
|
import { useAui as useAui2 } from "@assistant-ui/store";
|
|
@@ -4020,7 +4113,6 @@ var trueFoundryAttachmentAdapter = {
|
|
|
4020
4113
|
}
|
|
4021
4114
|
};
|
|
4022
4115
|
export {
|
|
4023
|
-
PrivateAgentSessionClient,
|
|
4024
4116
|
ROOT_THREAD_ID,
|
|
4025
4117
|
TOOL_RESPONSE_THREAD_ID_CUSTOM_KEY,
|
|
4026
4118
|
buildEditedUserMessageContent,
|
|
@@ -4038,7 +4130,9 @@ export {
|
|
|
4038
4130
|
findPausedAssistantMessage,
|
|
4039
4131
|
getSession,
|
|
4040
4132
|
getTurnMessageContent,
|
|
4133
|
+
isEventDelta,
|
|
4041
4134
|
mergeAgentSpec,
|
|
4135
|
+
mergeEventDelta,
|
|
4042
4136
|
messageHasPendingApprovals,
|
|
4043
4137
|
messageHasPendingRequiredActions,
|
|
4044
4138
|
messageHasPendingResponses,
|