@truefoundry/assistant-ui-runtime 0.1.1 → 0.1.2
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 +31 -0
- package/dist/index.d.ts +11 -2
- package/dist/index.js +470 -112
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/convertTurnMessages.test.ts +146 -7
- package/src/convertTurnMessages.ts +442 -164
- package/src/hooks.ts +18 -0
- package/src/index.ts +1 -0
- package/src/private/bindDraftAgentSession.test.ts +3 -2
- package/src/private/draftSessionBridge.ts +8 -2
- package/src/private/useDraftAgentSpec.test.tsx +153 -0
- package/src/private/useDraftAgentSpec.ts +80 -3
- package/src/sessionSnapshot.ts +21 -1
- package/src/streamTurn.test.ts +34 -0
- package/src/streamTurn.ts +9 -1
- package/src/truefoundryExtras.ts +3 -0
- package/src/useTrueFoundryAgentMessages.test.tsx +50 -0
- package/src/useTrueFoundryAgentMessages.ts +85 -10
- package/src/useTrueFoundryAgentRuntime.ts +25 -1
package/dist/index.js
CHANGED
|
@@ -1304,6 +1304,280 @@ function replaceSessionSnapshot(snapshot, patch) {
|
|
|
1304
1304
|
// src/convertTurnMessages.ts
|
|
1305
1305
|
var TURN_EVENTS_PAGE_SIZE = 25;
|
|
1306
1306
|
var SESSION_EVENTS_PAGE_SIZE = 100;
|
|
1307
|
+
var MAX_HISTORY_BOUNDARY_PAGES = 10;
|
|
1308
|
+
function trimIncompleteLeadingEvents(itemsAsc) {
|
|
1309
|
+
const start = itemsAsc.findIndex((item) => item.event.type === "turn.created");
|
|
1310
|
+
if (start === -1) {
|
|
1311
|
+
return [];
|
|
1312
|
+
}
|
|
1313
|
+
return itemsAsc.slice(start);
|
|
1314
|
+
}
|
|
1315
|
+
function oldestCompleteTurnGroupState(itemsAsc) {
|
|
1316
|
+
const trimmed = trimIncompleteLeadingEvents(itemsAsc);
|
|
1317
|
+
if (trimmed.length === 0) {
|
|
1318
|
+
return "incomplete";
|
|
1319
|
+
}
|
|
1320
|
+
const created = trimmed[0];
|
|
1321
|
+
if (created?.event.type !== "turn.created") {
|
|
1322
|
+
return "incomplete";
|
|
1323
|
+
}
|
|
1324
|
+
const hasDone = trimmed.some(
|
|
1325
|
+
(item) => item.turnId === created.turnId && item.event.type === "turn.done"
|
|
1326
|
+
);
|
|
1327
|
+
if (!hasDone) {
|
|
1328
|
+
return "incomplete";
|
|
1329
|
+
}
|
|
1330
|
+
return extractTurnUserText(created.event.input) != null ? "user-group" : "continuation";
|
|
1331
|
+
}
|
|
1332
|
+
async function fetchSessionEventsPage(session, options) {
|
|
1333
|
+
const page = await session.listEvents({
|
|
1334
|
+
limit: SESSION_EVENTS_PAGE_SIZE,
|
|
1335
|
+
...options?.lastTurnId != null ? { lastTurnId: options.lastTurnId } : {},
|
|
1336
|
+
...options?.pageToken != null ? { pageToken: options.pageToken } : {}
|
|
1337
|
+
});
|
|
1338
|
+
const response = page.response;
|
|
1339
|
+
const olderPageToken = response.pagination?.nextPageToken;
|
|
1340
|
+
const hasOlder = typeof page.hasNextPage === "function" ? page.hasNextPage() : olderPageToken != null && olderPageToken !== "";
|
|
1341
|
+
return {
|
|
1342
|
+
itemsNewestFirst: page.data,
|
|
1343
|
+
...olderPageToken != null && olderPageToken !== "" ? { olderPageToken } : {},
|
|
1344
|
+
hasOlder
|
|
1345
|
+
};
|
|
1346
|
+
}
|
|
1347
|
+
async function fetchSessionEventsWindow(session, options) {
|
|
1348
|
+
let itemsNewestFirst = [];
|
|
1349
|
+
let pageToken = options?.pageToken;
|
|
1350
|
+
let olderPageToken;
|
|
1351
|
+
let hasOlder = false;
|
|
1352
|
+
for (let pageCount = 0; pageCount < MAX_HISTORY_BOUNDARY_PAGES; pageCount++) {
|
|
1353
|
+
const page = await fetchSessionEventsPage(session, {
|
|
1354
|
+
...options,
|
|
1355
|
+
...pageToken != null ? { pageToken } : {}
|
|
1356
|
+
});
|
|
1357
|
+
itemsNewestFirst = [...itemsNewestFirst, ...page.itemsNewestFirst];
|
|
1358
|
+
olderPageToken = page.olderPageToken;
|
|
1359
|
+
hasOlder = page.hasOlder;
|
|
1360
|
+
const itemsAsc2 = trimIncompleteLeadingEvents([...itemsNewestFirst].reverse());
|
|
1361
|
+
const groupState = oldestCompleteTurnGroupState(itemsAsc2);
|
|
1362
|
+
if (groupState === "user-group" || !hasOlder) {
|
|
1363
|
+
return {
|
|
1364
|
+
itemsAsc: itemsAsc2,
|
|
1365
|
+
...olderPageToken != null ? { olderPageToken } : {},
|
|
1366
|
+
hasOlder
|
|
1367
|
+
};
|
|
1368
|
+
}
|
|
1369
|
+
if (olderPageToken == null) {
|
|
1370
|
+
return { itemsAsc: itemsAsc2, hasOlder: false };
|
|
1371
|
+
}
|
|
1372
|
+
pageToken = olderPageToken;
|
|
1373
|
+
}
|
|
1374
|
+
const itemsAsc = trimIncompleteLeadingEvents([...itemsNewestFirst].reverse());
|
|
1375
|
+
return {
|
|
1376
|
+
itemsAsc,
|
|
1377
|
+
...olderPageToken != null ? { olderPageToken } : {},
|
|
1378
|
+
hasOlder
|
|
1379
|
+
};
|
|
1380
|
+
}
|
|
1381
|
+
async function fetchAllSessionEvents(session, options) {
|
|
1382
|
+
const items = [];
|
|
1383
|
+
for await (const item of await session.listEvents({
|
|
1384
|
+
limit: SESSION_EVENTS_PAGE_SIZE,
|
|
1385
|
+
...options?.lastTurnId != null ? { lastTurnId: options.lastTurnId } : {}
|
|
1386
|
+
})) {
|
|
1387
|
+
items.push(item);
|
|
1388
|
+
}
|
|
1389
|
+
items.reverse();
|
|
1390
|
+
return items;
|
|
1391
|
+
}
|
|
1392
|
+
function cloneThreadBucket(bucket) {
|
|
1393
|
+
return {
|
|
1394
|
+
events: new Map(bucket.events),
|
|
1395
|
+
modelMessageIds: [...bucket.modelMessageIds],
|
|
1396
|
+
toolResults: new Map(bucket.toolResults),
|
|
1397
|
+
pendingApprovals: new Map(bucket.pendingApprovals),
|
|
1398
|
+
approvalDecisions: new Map(bucket.approvalDecisions),
|
|
1399
|
+
pendingResponses: new Map(bucket.pendingResponses),
|
|
1400
|
+
done: bucket.done,
|
|
1401
|
+
...bucket.title != null ? { title: bucket.title } : {},
|
|
1402
|
+
...bucket.agentInfo != null ? { agentInfo: bucket.agentInfo } : {}
|
|
1403
|
+
};
|
|
1404
|
+
}
|
|
1405
|
+
function prependFoldState(older, newer) {
|
|
1406
|
+
const result = new PeerThreadFoldState();
|
|
1407
|
+
const threadIds = /* @__PURE__ */ new Set([...older.threads.keys(), ...newer.threads.keys()]);
|
|
1408
|
+
for (const threadId of threadIds) {
|
|
1409
|
+
const olderBucket = older.threads.get(threadId);
|
|
1410
|
+
const newerBucket = newer.threads.get(threadId);
|
|
1411
|
+
if (olderBucket == null && newerBucket != null) {
|
|
1412
|
+
result.threads.set(threadId, cloneThreadBucket(newerBucket));
|
|
1413
|
+
continue;
|
|
1414
|
+
}
|
|
1415
|
+
if (newerBucket == null && olderBucket != null) {
|
|
1416
|
+
result.threads.set(threadId, cloneThreadBucket(olderBucket));
|
|
1417
|
+
continue;
|
|
1418
|
+
}
|
|
1419
|
+
if (olderBucket == null || newerBucket == null) {
|
|
1420
|
+
continue;
|
|
1421
|
+
}
|
|
1422
|
+
result.threads.set(threadId, {
|
|
1423
|
+
events: new Map([...olderBucket.events, ...newerBucket.events]),
|
|
1424
|
+
modelMessageIds: [
|
|
1425
|
+
...olderBucket.modelMessageIds,
|
|
1426
|
+
...newerBucket.modelMessageIds
|
|
1427
|
+
],
|
|
1428
|
+
toolResults: new Map([
|
|
1429
|
+
...olderBucket.toolResults,
|
|
1430
|
+
...newerBucket.toolResults
|
|
1431
|
+
]),
|
|
1432
|
+
pendingApprovals: new Map([
|
|
1433
|
+
...olderBucket.pendingApprovals,
|
|
1434
|
+
...newerBucket.pendingApprovals
|
|
1435
|
+
]),
|
|
1436
|
+
approvalDecisions: new Map([
|
|
1437
|
+
...olderBucket.approvalDecisions,
|
|
1438
|
+
...newerBucket.approvalDecisions
|
|
1439
|
+
]),
|
|
1440
|
+
pendingResponses: new Map([
|
|
1441
|
+
...olderBucket.pendingResponses,
|
|
1442
|
+
...newerBucket.pendingResponses
|
|
1443
|
+
]),
|
|
1444
|
+
done: newerBucket.done || olderBucket.done,
|
|
1445
|
+
...newerBucket.title != null || olderBucket.title != null ? { title: newerBucket.title ?? olderBucket.title } : {},
|
|
1446
|
+
...newerBucket.agentInfo != null || olderBucket.agentInfo != null ? { agentInfo: newerBucket.agentInfo ?? olderBucket.agentInfo } : {}
|
|
1447
|
+
});
|
|
1448
|
+
}
|
|
1449
|
+
for (const [threadId, link] of older.threadParents) {
|
|
1450
|
+
result.threadParents.set(threadId, link);
|
|
1451
|
+
}
|
|
1452
|
+
for (const [threadId, link] of newer.threadParents) {
|
|
1453
|
+
result.threadParents.set(threadId, link);
|
|
1454
|
+
}
|
|
1455
|
+
return result;
|
|
1456
|
+
}
|
|
1457
|
+
function ingestSessionEventsIntoSnapshot(snapshot, items, onTurnComplete) {
|
|
1458
|
+
let currentTurnId = null;
|
|
1459
|
+
let currentCreatedEvent = null;
|
|
1460
|
+
let currentContentEvents = [];
|
|
1461
|
+
let beforeCount = 0;
|
|
1462
|
+
for (const item of items) {
|
|
1463
|
+
const { turnId, event } = item;
|
|
1464
|
+
if (event.type === "turn.created") {
|
|
1465
|
+
currentTurnId = turnId;
|
|
1466
|
+
currentCreatedEvent = event;
|
|
1467
|
+
currentContentEvents = [];
|
|
1468
|
+
beforeCount = snapshot.fold.threads.get(ROOT_THREAD_ID)?.modelMessageIds.length ?? 0;
|
|
1469
|
+
} else if (event.type === "turn.done") {
|
|
1470
|
+
if (currentTurnId == null || currentCreatedEvent == null) {
|
|
1471
|
+
continue;
|
|
1472
|
+
}
|
|
1473
|
+
const afterBucket = snapshot.fold.threads.get(ROOT_THREAD_ID);
|
|
1474
|
+
const rootModelMessageIds = (afterBucket?.modelMessageIds ?? []).slice(
|
|
1475
|
+
beforeCount
|
|
1476
|
+
);
|
|
1477
|
+
const sandboxEvent = currentContentEvents.find(
|
|
1478
|
+
(ev) => ev.type === "sandbox.created"
|
|
1479
|
+
);
|
|
1480
|
+
applyUserToolResponsesToFold(
|
|
1481
|
+
snapshot.fold,
|
|
1482
|
+
currentCreatedEvent.input ?? []
|
|
1483
|
+
);
|
|
1484
|
+
snapshot.turns.push(
|
|
1485
|
+
sessionEventsToSessionRecord(
|
|
1486
|
+
currentTurnId,
|
|
1487
|
+
currentCreatedEvent,
|
|
1488
|
+
event,
|
|
1489
|
+
rootModelMessageIds,
|
|
1490
|
+
sandboxEvent?.sandboxId
|
|
1491
|
+
)
|
|
1492
|
+
);
|
|
1493
|
+
onTurnComplete?.(replaceSessionSnapshot(snapshot, {}));
|
|
1494
|
+
currentTurnId = null;
|
|
1495
|
+
currentCreatedEvent = null;
|
|
1496
|
+
currentContentEvents = [];
|
|
1497
|
+
} else {
|
|
1498
|
+
if (currentTurnId != null) {
|
|
1499
|
+
ingestTurnEvent(snapshot.fold, event);
|
|
1500
|
+
currentContentEvents.push(event);
|
|
1501
|
+
}
|
|
1502
|
+
}
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
function attachRunningTurn(snapshot, runningTurn) {
|
|
1506
|
+
if (runningTurn == null) {
|
|
1507
|
+
return snapshot;
|
|
1508
|
+
}
|
|
1509
|
+
const pendingUserText = extractTurnUserText(runningTurn.input);
|
|
1510
|
+
return replaceSessionSnapshot(snapshot, {
|
|
1511
|
+
runningTurn,
|
|
1512
|
+
unstable_resume: true,
|
|
1513
|
+
groupRootBaseline: computeGroupRootBaseline(snapshot.turns),
|
|
1514
|
+
...pendingUserText ? {
|
|
1515
|
+
pendingUser: {
|
|
1516
|
+
turnId: runningTurn.id,
|
|
1517
|
+
content: extractTurnUserMessageContent(runningTurn.input),
|
|
1518
|
+
createdAt: new Date(runningTurn.createdAt)
|
|
1519
|
+
}
|
|
1520
|
+
} : {}
|
|
1521
|
+
});
|
|
1522
|
+
}
|
|
1523
|
+
async function buildSnapshotFromSessionEvents(session, onProgress) {
|
|
1524
|
+
const turnsPage = await session.listTurns({ limit: 1 });
|
|
1525
|
+
const newestTurn = turnsPage.data[0];
|
|
1526
|
+
const runningTurn = newestTurn?.state?.status === "running" ? newestTurn : void 0;
|
|
1527
|
+
const window = await fetchSessionEventsWindow(session);
|
|
1528
|
+
const historyPagination = {
|
|
1529
|
+
hasOlder: window.hasOlder,
|
|
1530
|
+
...window.olderPageToken != null ? { olderPageToken: window.olderPageToken } : {}
|
|
1531
|
+
};
|
|
1532
|
+
const snapshot = createEmptySessionSnapshot();
|
|
1533
|
+
ingestSessionEventsIntoSnapshot(snapshot, window.itemsAsc, onProgress);
|
|
1534
|
+
const withHistory = replaceSessionSnapshot(snapshot, {
|
|
1535
|
+
historyEvents: window.itemsAsc,
|
|
1536
|
+
historyPagination
|
|
1537
|
+
});
|
|
1538
|
+
return attachRunningTurn(withHistory, runningTurn);
|
|
1539
|
+
}
|
|
1540
|
+
async function prependOlderSessionHistory(session, snapshot) {
|
|
1541
|
+
const pagination = snapshot.historyPagination;
|
|
1542
|
+
if (pagination?.hasOlder !== true || pagination.olderPageToken == null) {
|
|
1543
|
+
return snapshot;
|
|
1544
|
+
}
|
|
1545
|
+
const window = await fetchSessionEventsWindow(session, {
|
|
1546
|
+
pageToken: pagination.olderPageToken
|
|
1547
|
+
});
|
|
1548
|
+
if (window.itemsAsc.length === 0) {
|
|
1549
|
+
return replaceSessionSnapshot(snapshot, {
|
|
1550
|
+
historyPagination: { hasOlder: false }
|
|
1551
|
+
});
|
|
1552
|
+
}
|
|
1553
|
+
const olderSnap = createEmptySessionSnapshot();
|
|
1554
|
+
ingestSessionEventsIntoSnapshot(olderSnap, window.itemsAsc);
|
|
1555
|
+
const existingIds = new Set(snapshot.turns.map((turn) => turn.id));
|
|
1556
|
+
const olderTurns = olderSnap.turns.filter((turn) => !existingIds.has(turn.id));
|
|
1557
|
+
const mergedFold = prependFoldState(olderSnap.fold, snapshot.fold);
|
|
1558
|
+
const historyEvents = [
|
|
1559
|
+
...window.itemsAsc,
|
|
1560
|
+
...snapshot.historyEvents ?? []
|
|
1561
|
+
];
|
|
1562
|
+
const olderRootIds = olderTurns.flatMap(
|
|
1563
|
+
(turn) => turn.rootModelMessageIds ?? []
|
|
1564
|
+
);
|
|
1565
|
+
return replaceSessionSnapshot(snapshot, {
|
|
1566
|
+
fold: mergedFold,
|
|
1567
|
+
turns: [...olderTurns, ...snapshot.turns],
|
|
1568
|
+
historyEvents,
|
|
1569
|
+
historyPagination: {
|
|
1570
|
+
hasOlder: window.hasOlder,
|
|
1571
|
+
...window.olderPageToken != null ? { olderPageToken: window.olderPageToken } : {}
|
|
1572
|
+
},
|
|
1573
|
+
...snapshot.groupRootBaseline != null ? {
|
|
1574
|
+
groupRootBaseline: [
|
|
1575
|
+
...olderRootIds,
|
|
1576
|
+
...snapshot.groupRootBaseline
|
|
1577
|
+
]
|
|
1578
|
+
} : {}
|
|
1579
|
+
});
|
|
1580
|
+
}
|
|
1307
1581
|
function assistantStatusFromTurnState(state) {
|
|
1308
1582
|
switch (state.status) {
|
|
1309
1583
|
case "done":
|
|
@@ -1710,92 +1984,6 @@ function projectSessionMessages(snapshot, options) {
|
|
|
1710
1984
|
);
|
|
1711
1985
|
}
|
|
1712
1986
|
var DEFAULT_LIST_EVENTS_CONCURRENCY = 5;
|
|
1713
|
-
async function fetchAllSessionEvents(session, options) {
|
|
1714
|
-
const items = [];
|
|
1715
|
-
for await (const item of await session.listEvents({
|
|
1716
|
-
limit: SESSION_EVENTS_PAGE_SIZE,
|
|
1717
|
-
...options?.lastTurnId != null ? { lastTurnId: options.lastTurnId } : {}
|
|
1718
|
-
})) {
|
|
1719
|
-
items.push(item);
|
|
1720
|
-
}
|
|
1721
|
-
items.reverse();
|
|
1722
|
-
return items;
|
|
1723
|
-
}
|
|
1724
|
-
function ingestSessionEventsIntoSnapshot(snapshot, items, onTurnComplete) {
|
|
1725
|
-
let currentTurnId = null;
|
|
1726
|
-
let currentCreatedEvent = null;
|
|
1727
|
-
let currentContentEvents = [];
|
|
1728
|
-
let beforeCount = 0;
|
|
1729
|
-
for (const item of items) {
|
|
1730
|
-
const { turnId, event } = item;
|
|
1731
|
-
if (event.type === "turn.created") {
|
|
1732
|
-
currentTurnId = turnId;
|
|
1733
|
-
currentCreatedEvent = event;
|
|
1734
|
-
currentContentEvents = [];
|
|
1735
|
-
beforeCount = snapshot.fold.threads.get(ROOT_THREAD_ID)?.modelMessageIds.length ?? 0;
|
|
1736
|
-
} else if (event.type === "turn.done") {
|
|
1737
|
-
if (currentTurnId == null || currentCreatedEvent == null) {
|
|
1738
|
-
continue;
|
|
1739
|
-
}
|
|
1740
|
-
const afterBucket = snapshot.fold.threads.get(ROOT_THREAD_ID);
|
|
1741
|
-
const rootModelMessageIds = (afterBucket?.modelMessageIds ?? []).slice(
|
|
1742
|
-
beforeCount
|
|
1743
|
-
);
|
|
1744
|
-
const sandboxEvent = currentContentEvents.find(
|
|
1745
|
-
(ev) => ev.type === "sandbox.created"
|
|
1746
|
-
);
|
|
1747
|
-
applyUserToolResponsesToFold(
|
|
1748
|
-
snapshot.fold,
|
|
1749
|
-
currentCreatedEvent.input ?? []
|
|
1750
|
-
);
|
|
1751
|
-
snapshot.turns.push(
|
|
1752
|
-
sessionEventsToSessionRecord(
|
|
1753
|
-
currentTurnId,
|
|
1754
|
-
currentCreatedEvent,
|
|
1755
|
-
event,
|
|
1756
|
-
rootModelMessageIds,
|
|
1757
|
-
sandboxEvent?.sandboxId
|
|
1758
|
-
)
|
|
1759
|
-
);
|
|
1760
|
-
onTurnComplete?.(replaceSessionSnapshot(snapshot, {}));
|
|
1761
|
-
currentTurnId = null;
|
|
1762
|
-
currentCreatedEvent = null;
|
|
1763
|
-
currentContentEvents = [];
|
|
1764
|
-
} else {
|
|
1765
|
-
if (currentTurnId != null) {
|
|
1766
|
-
ingestTurnEvent(snapshot.fold, event);
|
|
1767
|
-
currentContentEvents.push(event);
|
|
1768
|
-
}
|
|
1769
|
-
}
|
|
1770
|
-
}
|
|
1771
|
-
}
|
|
1772
|
-
async function buildSnapshotFromSessionEvents(session, onProgress) {
|
|
1773
|
-
let runningTurn;
|
|
1774
|
-
for await (const turn of await session.listTurns({ limit: 1 })) {
|
|
1775
|
-
if (turn.state?.status === "running") {
|
|
1776
|
-
runningTurn = turn;
|
|
1777
|
-
}
|
|
1778
|
-
}
|
|
1779
|
-
const items = await fetchAllSessionEvents(session);
|
|
1780
|
-
const snapshot = createEmptySessionSnapshot();
|
|
1781
|
-
ingestSessionEventsIntoSnapshot(snapshot, items, onProgress);
|
|
1782
|
-
if (runningTurn == null) {
|
|
1783
|
-
return snapshot;
|
|
1784
|
-
}
|
|
1785
|
-
const pendingUserText = extractTurnUserText(runningTurn.input);
|
|
1786
|
-
return replaceSessionSnapshot(snapshot, {
|
|
1787
|
-
runningTurn,
|
|
1788
|
-
unstable_resume: true,
|
|
1789
|
-
groupRootBaseline: computeGroupRootBaseline(snapshot.turns),
|
|
1790
|
-
...pendingUserText ? {
|
|
1791
|
-
pendingUser: {
|
|
1792
|
-
turnId: runningTurn.id,
|
|
1793
|
-
content: extractTurnUserMessageContent(runningTurn.input),
|
|
1794
|
-
createdAt: new Date(runningTurn.createdAt)
|
|
1795
|
-
}
|
|
1796
|
-
} : {}
|
|
1797
|
-
});
|
|
1798
|
-
}
|
|
1799
1987
|
function ingestTurnsIntoSnapshot(snapshot, turns, eventArrays) {
|
|
1800
1988
|
let runningTurn;
|
|
1801
1989
|
for (let i = 0; i < turns.length; i++) {
|
|
@@ -1834,9 +2022,18 @@ async function buildSnapshotFromSession(session, concurrency = DEFAULT_LIST_EVEN
|
|
|
1834
2022
|
return replaceSessionSnapshot(snapshot, {
|
|
1835
2023
|
runningTurn: turn,
|
|
1836
2024
|
unstable_resume: true,
|
|
1837
|
-
groupRootBaseline: computeGroupRootBaseline(snapshot.turns)
|
|
2025
|
+
groupRootBaseline: computeGroupRootBaseline(snapshot.turns),
|
|
2026
|
+
pendingUser: void 0
|
|
1838
2027
|
});
|
|
1839
2028
|
}
|
|
2029
|
+
async function buildSnapshotBeforeTurn(session, beforeTurnId, concurrency = DEFAULT_LIST_EVENTS_CONCURRENCY) {
|
|
2030
|
+
const turns = await listSessionTurnsOrdered(session);
|
|
2031
|
+
const beforeIndex = turns.findIndex((turn) => turn.id === beforeTurnId);
|
|
2032
|
+
if (beforeIndex === -1) {
|
|
2033
|
+
throw new Error(`Turn ${beforeTurnId} not found in session`);
|
|
2034
|
+
}
|
|
2035
|
+
return buildSnapshotBeforeTurnIndex(session, beforeIndex, concurrency, turns);
|
|
2036
|
+
}
|
|
1840
2037
|
async function buildSnapshotBeforeTurnIndex(session, turnIndex, _concurrency = DEFAULT_LIST_EVENTS_CONCURRENCY, orderedTurns) {
|
|
1841
2038
|
if (turnIndex <= 0) {
|
|
1842
2039
|
return createEmptySessionSnapshot();
|
|
@@ -1859,6 +2056,11 @@ async function resolveGatewayBranchPreviousTurnId(session, turnIndex, orderedTur
|
|
|
1859
2056
|
const turns = orderedTurns ?? await listSessionTurnsOrdered(session);
|
|
1860
2057
|
return turns[turnIndex - 1]?.id ?? null;
|
|
1861
2058
|
}
|
|
2059
|
+
async function resolveGatewayBranchPreviousTurnIdForTurn(session, turnId) {
|
|
2060
|
+
const turns = await listSessionTurnsOrdered(session);
|
|
2061
|
+
const turnIndex = turns.findIndex((turn) => turn.id === turnId);
|
|
2062
|
+
return resolveGatewayBranchPreviousTurnId(session, turnIndex, turns);
|
|
2063
|
+
}
|
|
1862
2064
|
async function listSessionTurnsOrdered(session) {
|
|
1863
2065
|
const turns = [];
|
|
1864
2066
|
for await (const turn of await session.listTurns()) {
|
|
@@ -2125,6 +2327,7 @@ function repositoryItemsFromMessages(messages) {
|
|
|
2125
2327
|
}
|
|
2126
2328
|
|
|
2127
2329
|
// src/private/draftSessionBridge.ts
|
|
2330
|
+
var DRAFT_SESSION_LAST_UPDATED_AT_HEADER = "x-tfy-session-last-updated-at";
|
|
2128
2331
|
function createDraftSessionBridge(gateway) {
|
|
2129
2332
|
async function getDraft(draftSessionId) {
|
|
2130
2333
|
const response = await gateway.agents.private.draftSessions.get(draftSessionId);
|
|
@@ -2136,7 +2339,11 @@ function createDraftSessionBridge(gateway) {
|
|
|
2136
2339
|
return draft.agentSpec;
|
|
2137
2340
|
},
|
|
2138
2341
|
async syncAgentSpec(draftSessionId, agentSpec) {
|
|
2139
|
-
await gateway.agents.private.draftSessions.update(
|
|
2342
|
+
const response = await gateway.agents.private.draftSessions.update(
|
|
2343
|
+
draftSessionId,
|
|
2344
|
+
{ agentSpec }
|
|
2345
|
+
);
|
|
2346
|
+
return response.data.updatedAt;
|
|
2140
2347
|
}
|
|
2141
2348
|
};
|
|
2142
2349
|
}
|
|
@@ -3392,6 +3599,29 @@ function useDraftAgentSpec({
|
|
|
3392
3599
|
const syncGenerationRef = useRef(0);
|
|
3393
3600
|
const loadedDraftIdRef = useRef(void 0);
|
|
3394
3601
|
const localDirtyRef = useRef(false);
|
|
3602
|
+
const lastUpdatedAtRef = useRef(void 0);
|
|
3603
|
+
const pendingFlushRef = useRef(void 0);
|
|
3604
|
+
const inFlightFlushRef = useRef(void 0);
|
|
3605
|
+
const activeDraftIdRef = useRef(draftSessionId);
|
|
3606
|
+
useEffect(() => {
|
|
3607
|
+
const previousDraftId = activeDraftIdRef.current;
|
|
3608
|
+
if (previousDraftId === draftSessionId) {
|
|
3609
|
+
return;
|
|
3610
|
+
}
|
|
3611
|
+
activeDraftIdRef.current = draftSessionId;
|
|
3612
|
+
syncGenerationRef.current++;
|
|
3613
|
+
if (syncTimeoutRef.current != null) {
|
|
3614
|
+
clearTimeout(syncTimeoutRef.current);
|
|
3615
|
+
syncTimeoutRef.current = void 0;
|
|
3616
|
+
}
|
|
3617
|
+
pendingFlushRef.current = void 0;
|
|
3618
|
+
inFlightFlushRef.current = void 0;
|
|
3619
|
+
lastUpdatedAtRef.current = void 0;
|
|
3620
|
+
setIsSpecSyncing(false);
|
|
3621
|
+
if (previousDraftId != null) {
|
|
3622
|
+
localDirtyRef.current = false;
|
|
3623
|
+
}
|
|
3624
|
+
}, [draftSessionId]);
|
|
3395
3625
|
useEffect(() => {
|
|
3396
3626
|
if (!enabled || draftBridge == null) {
|
|
3397
3627
|
return;
|
|
@@ -3440,10 +3670,11 @@ function useDraftAgentSpec({
|
|
|
3440
3670
|
}
|
|
3441
3671
|
setIsSpecSyncing(true);
|
|
3442
3672
|
try {
|
|
3443
|
-
await draftBridge.syncAgentSpec(draftId, spec);
|
|
3673
|
+
const updatedAt = await draftBridge.syncAgentSpec(draftId, spec);
|
|
3444
3674
|
if (generation !== syncGenerationRef.current) {
|
|
3445
3675
|
return;
|
|
3446
3676
|
}
|
|
3677
|
+
lastUpdatedAtRef.current = updatedAt || (/* @__PURE__ */ new Date()).toISOString();
|
|
3447
3678
|
setSpecError(null);
|
|
3448
3679
|
onAgentSpecChange?.(spec);
|
|
3449
3680
|
} catch (error) {
|
|
@@ -3465,14 +3696,47 @@ function useDraftAgentSpec({
|
|
|
3465
3696
|
clearTimeout(syncTimeoutRef.current);
|
|
3466
3697
|
}
|
|
3467
3698
|
const generation = ++syncGenerationRef.current;
|
|
3699
|
+
const flush = () => {
|
|
3700
|
+
pendingFlushRef.current = void 0;
|
|
3701
|
+
syncTimeoutRef.current = void 0;
|
|
3702
|
+
const promise = flushSpecSync(draftId, spec, generation).finally(() => {
|
|
3703
|
+
if (inFlightFlushRef.current === promise) {
|
|
3704
|
+
inFlightFlushRef.current = void 0;
|
|
3705
|
+
}
|
|
3706
|
+
});
|
|
3707
|
+
inFlightFlushRef.current = promise;
|
|
3708
|
+
return promise;
|
|
3709
|
+
};
|
|
3710
|
+
pendingFlushRef.current = flush;
|
|
3468
3711
|
syncTimeoutRef.current = setTimeout(() => {
|
|
3469
|
-
void
|
|
3712
|
+
void flush();
|
|
3470
3713
|
}, SPEC_SYNC_DEBOUNCE_MS);
|
|
3471
3714
|
},
|
|
3472
3715
|
[flushSpecSync]
|
|
3473
3716
|
);
|
|
3474
3717
|
const scheduleSpecSyncRef = useRef(scheduleSpecSync);
|
|
3475
3718
|
scheduleSpecSyncRef.current = scheduleSpecSync;
|
|
3719
|
+
const flushPendingSpecSyncNow = useCallback(async () => {
|
|
3720
|
+
if (syncTimeoutRef.current != null) {
|
|
3721
|
+
clearTimeout(syncTimeoutRef.current);
|
|
3722
|
+
syncTimeoutRef.current = void 0;
|
|
3723
|
+
}
|
|
3724
|
+
const pending = pendingFlushRef.current;
|
|
3725
|
+
if (pending != null) {
|
|
3726
|
+
pendingFlushRef.current = void 0;
|
|
3727
|
+
await pending();
|
|
3728
|
+
return;
|
|
3729
|
+
}
|
|
3730
|
+
if (inFlightFlushRef.current != null) {
|
|
3731
|
+
await inFlightFlushRef.current;
|
|
3732
|
+
}
|
|
3733
|
+
}, []);
|
|
3734
|
+
const takeTurnHeaderTimestamp = useCallback(async () => {
|
|
3735
|
+
await flushPendingSpecSyncNow();
|
|
3736
|
+
const updatedAt = lastUpdatedAtRef.current;
|
|
3737
|
+
lastUpdatedAtRef.current = void 0;
|
|
3738
|
+
return updatedAt;
|
|
3739
|
+
}, [flushPendingSpecSyncNow]);
|
|
3476
3740
|
useEffect(
|
|
3477
3741
|
() => () => {
|
|
3478
3742
|
if (syncTimeoutRef.current != null) {
|
|
@@ -3501,7 +3765,8 @@ function useDraftAgentSpec({
|
|
|
3501
3765
|
draftSessionId: enabled ? draftSessionId : void 0,
|
|
3502
3766
|
isSpecSyncing: enabled ? isSpecSyncing : false,
|
|
3503
3767
|
specError: enabled ? specError : null,
|
|
3504
|
-
updateAgentSpec
|
|
3768
|
+
updateAgentSpec,
|
|
3769
|
+
takeTurnHeaderTimestamp
|
|
3505
3770
|
}),
|
|
3506
3771
|
[
|
|
3507
3772
|
agentSpec,
|
|
@@ -3509,6 +3774,7 @@ function useDraftAgentSpec({
|
|
|
3509
3774
|
enabled,
|
|
3510
3775
|
isSpecSyncing,
|
|
3511
3776
|
specError,
|
|
3777
|
+
takeTurnHeaderTimestamp,
|
|
3512
3778
|
updateAgentSpec
|
|
3513
3779
|
]
|
|
3514
3780
|
);
|
|
@@ -3593,7 +3859,13 @@ async function* streamTurnContent(session, foldState, options, abortSignal, grou
|
|
|
3593
3859
|
}
|
|
3594
3860
|
try {
|
|
3595
3861
|
yield* streamTurnEvents(
|
|
3596
|
-
turn.execute(
|
|
3862
|
+
turn.execute(
|
|
3863
|
+
{ stream: true },
|
|
3864
|
+
{
|
|
3865
|
+
abortSignal,
|
|
3866
|
+
...options.headers != null ? { headers: options.headers } : {}
|
|
3867
|
+
}
|
|
3868
|
+
),
|
|
3597
3869
|
foldState,
|
|
3598
3870
|
groupRootBaseline
|
|
3599
3871
|
);
|
|
@@ -3745,16 +4017,6 @@ async function resolveActiveSessionId(remoteId, resolveConversationSessionId) {
|
|
|
3745
4017
|
}
|
|
3746
4018
|
return remoteId;
|
|
3747
4019
|
}
|
|
3748
|
-
function findTurnIndex(snapshot, turnId) {
|
|
3749
|
-
const committedIndex = snapshot.turns.findIndex((turn) => turn.id === turnId);
|
|
3750
|
-
if (committedIndex !== -1) {
|
|
3751
|
-
return committedIndex;
|
|
3752
|
-
}
|
|
3753
|
-
if (snapshot.pendingUser?.turnId === turnId) {
|
|
3754
|
-
return snapshot.turns.length;
|
|
3755
|
-
}
|
|
3756
|
-
throw new Error(`Turn ${turnId} not found in session snapshot`);
|
|
3757
|
-
}
|
|
3758
4020
|
function resolveTurnInput(snapshot, turnId) {
|
|
3759
4021
|
const turnRecord = snapshot.turns.find((turn) => turn.id === turnId);
|
|
3760
4022
|
if (turnRecord?.input != null) {
|
|
@@ -3773,7 +4035,8 @@ function useTrueFoundryAgentMessages({
|
|
|
3773
4035
|
onError,
|
|
3774
4036
|
initializeSession,
|
|
3775
4037
|
resolveConversationSessionId,
|
|
3776
|
-
draftGateway
|
|
4038
|
+
draftGateway,
|
|
4039
|
+
getTurnHeaders
|
|
3777
4040
|
}) {
|
|
3778
4041
|
const sessionOptions = useMemo2(
|
|
3779
4042
|
() => draftGateway != null ? { draftGateway } : void 0,
|
|
@@ -3782,15 +4045,19 @@ function useTrueFoundryAgentMessages({
|
|
|
3782
4045
|
const [snapshot, setSnapshot] = useState2(createEmptySessionSnapshot);
|
|
3783
4046
|
const [isRunning, setIsRunning] = useState2(false);
|
|
3784
4047
|
const [isLoading, setIsLoading] = useState2(false);
|
|
4048
|
+
const [isLoadingOlderHistory, setIsLoadingOlderHistory] = useState2(false);
|
|
3785
4049
|
const [loadRetryTrigger, setLoadRetryTrigger] = useState2(0);
|
|
3786
4050
|
const snapshotRef = useRef2(snapshot);
|
|
3787
4051
|
snapshotRef.current = snapshot;
|
|
4052
|
+
const loadOlderInflightRef = useRef2(null);
|
|
3788
4053
|
const onErrorRef = useRef2(onError);
|
|
3789
4054
|
onErrorRef.current = onError;
|
|
3790
4055
|
const resolveConversationSessionIdRef = useRef2(resolveConversationSessionId);
|
|
3791
4056
|
resolveConversationSessionIdRef.current = resolveConversationSessionId;
|
|
3792
4057
|
const initializeSessionRef = useRef2(initializeSession);
|
|
3793
4058
|
initializeSessionRef.current = initializeSession;
|
|
4059
|
+
const getTurnHeadersRef = useRef2(getTurnHeaders);
|
|
4060
|
+
getTurnHeadersRef.current = getTurnHeaders;
|
|
3794
4061
|
const createdAtByMessageIdRef = useRef2(/* @__PURE__ */ new Map());
|
|
3795
4062
|
const abortControllerRef = useRef2(null);
|
|
3796
4063
|
const activeRunRef = useRef2(null);
|
|
@@ -3920,9 +4187,11 @@ function useTrueFoundryAgentMessages({
|
|
|
3920
4187
|
const generation = ++loadGenerationRef.current;
|
|
3921
4188
|
++streamGenerationRef.current;
|
|
3922
4189
|
abortControllerRef.current?.abort();
|
|
4190
|
+
loadOlderInflightRef.current = null;
|
|
3923
4191
|
createdAtByMessageIdRef.current = /* @__PURE__ */ new Map();
|
|
3924
4192
|
setSnapshot(createEmptySessionSnapshot());
|
|
3925
4193
|
setIsLoading(true);
|
|
4194
|
+
setIsLoadingOlderHistory(false);
|
|
3926
4195
|
try {
|
|
3927
4196
|
const conversationSessionId = await resolveActiveSessionId(
|
|
3928
4197
|
sessionId,
|
|
@@ -3990,6 +4259,8 @@ function useTrueFoundryAgentMessages({
|
|
|
3990
4259
|
resolveConversationSessionIdRef.current
|
|
3991
4260
|
);
|
|
3992
4261
|
const session = await getSession(client, conversationSessionId, sessionOptions);
|
|
4262
|
+
const turnHeaders = await getTurnHeadersRef.current?.();
|
|
4263
|
+
const streamHeaders = turnHeaders != null ? { headers: turnHeaders } : {};
|
|
3993
4264
|
const isContinuation = "inputs" in options || "resumeMcpAuth" in options && options.resumeMcpAuth === true;
|
|
3994
4265
|
const continuationTurnId = snapshotRef.current.activeStream?.turnId;
|
|
3995
4266
|
const turnId = isContinuation && continuationTurnId != null ? continuationTurnId : generateId();
|
|
@@ -4048,7 +4319,7 @@ function useTrueFoundryAgentMessages({
|
|
|
4048
4319
|
return streamTurnContent(
|
|
4049
4320
|
session,
|
|
4050
4321
|
snapshotRef.current.fold,
|
|
4051
|
-
{ inputs: options.inputs },
|
|
4322
|
+
{ inputs: options.inputs, ...streamHeaders },
|
|
4052
4323
|
signal,
|
|
4053
4324
|
groupRootBaseline
|
|
4054
4325
|
);
|
|
@@ -4057,7 +4328,7 @@ function useTrueFoundryAgentMessages({
|
|
|
4057
4328
|
return streamTurnContent(
|
|
4058
4329
|
session,
|
|
4059
4330
|
snapshotRef.current.fold,
|
|
4060
|
-
{ resumeMcpAuth: true },
|
|
4331
|
+
{ resumeMcpAuth: true, ...streamHeaders },
|
|
4061
4332
|
signal,
|
|
4062
4333
|
groupRootBaseline
|
|
4063
4334
|
);
|
|
@@ -4067,7 +4338,8 @@ function useTrueFoundryAgentMessages({
|
|
|
4067
4338
|
snapshotRef.current.fold,
|
|
4068
4339
|
{
|
|
4069
4340
|
userMessage: options.userMessage,
|
|
4070
|
-
...options.previousTurnId !== void 0 ? { previousTurnId: options.previousTurnId } : {}
|
|
4341
|
+
...options.previousTurnId !== void 0 ? { previousTurnId: options.previousTurnId } : {},
|
|
4342
|
+
...streamHeaders
|
|
4071
4343
|
},
|
|
4072
4344
|
signal,
|
|
4073
4345
|
groupRootBaseline
|
|
@@ -4171,20 +4443,19 @@ function useTrueFoundryAgentMessages({
|
|
|
4171
4443
|
}
|
|
4172
4444
|
const committed = commitActiveStream(snapshotRef.current);
|
|
4173
4445
|
setSnapshot(committed);
|
|
4174
|
-
const turnIndex = findTurnIndex(committed, turnId);
|
|
4175
4446
|
await cancel();
|
|
4176
4447
|
const conversationSessionId = await resolveActiveSessionId(
|
|
4177
4448
|
activeSessionId,
|
|
4178
4449
|
resolveConversationSessionIdRef.current
|
|
4179
4450
|
);
|
|
4180
4451
|
const session = await getSession(client, conversationSessionId, sessionOptions);
|
|
4181
|
-
const previousTurnId = await
|
|
4452
|
+
const previousTurnId = await resolveGatewayBranchPreviousTurnIdForTurn(
|
|
4182
4453
|
session,
|
|
4183
|
-
|
|
4454
|
+
turnId
|
|
4184
4455
|
);
|
|
4185
|
-
const rewound = await
|
|
4456
|
+
const rewound = await buildSnapshotBeforeTurn(
|
|
4186
4457
|
session,
|
|
4187
|
-
|
|
4458
|
+
turnId,
|
|
4188
4459
|
listEventsConcurrency
|
|
4189
4460
|
);
|
|
4190
4461
|
createdAtByMessageIdRef.current = /* @__PURE__ */ new Map();
|
|
@@ -4235,10 +4506,64 @@ function useTrueFoundryAgentMessages({
|
|
|
4235
4506
|
const retryLoad = useCallback2(() => {
|
|
4236
4507
|
setLoadRetryTrigger((n) => n + 1);
|
|
4237
4508
|
}, []);
|
|
4509
|
+
const hasOlderHistory = snapshot.historyPagination?.hasOlder === true;
|
|
4510
|
+
const loadOlderHistory = useCallback2(async () => {
|
|
4511
|
+
if (sessionId == null || isMain === false) {
|
|
4512
|
+
return;
|
|
4513
|
+
}
|
|
4514
|
+
if (loadOlderInflightRef.current != null) {
|
|
4515
|
+
return loadOlderInflightRef.current;
|
|
4516
|
+
}
|
|
4517
|
+
const current = snapshotRef.current;
|
|
4518
|
+
if (current.historyPagination?.hasOlder !== true) {
|
|
4519
|
+
return;
|
|
4520
|
+
}
|
|
4521
|
+
if (current.historyPagination.olderPageToken == null) {
|
|
4522
|
+
return;
|
|
4523
|
+
}
|
|
4524
|
+
const generation = loadGenerationRef.current;
|
|
4525
|
+
setIsLoadingOlderHistory(true);
|
|
4526
|
+
const run = (async () => {
|
|
4527
|
+
try {
|
|
4528
|
+
const conversationSessionId = await resolveActiveSessionId(
|
|
4529
|
+
sessionId,
|
|
4530
|
+
resolveConversationSessionIdRef.current
|
|
4531
|
+
);
|
|
4532
|
+
const session = await getSession(
|
|
4533
|
+
client,
|
|
4534
|
+
conversationSessionId,
|
|
4535
|
+
sessionOptions
|
|
4536
|
+
);
|
|
4537
|
+
const next = await prependOlderSessionHistory(
|
|
4538
|
+
session,
|
|
4539
|
+
snapshotRef.current
|
|
4540
|
+
);
|
|
4541
|
+
if (generation !== loadGenerationRef.current) {
|
|
4542
|
+
return;
|
|
4543
|
+
}
|
|
4544
|
+
setSnapshot(next);
|
|
4545
|
+
} catch (error) {
|
|
4546
|
+
if (generation === loadGenerationRef.current) {
|
|
4547
|
+
onErrorRef.current?.(error);
|
|
4548
|
+
}
|
|
4549
|
+
throw error;
|
|
4550
|
+
} finally {
|
|
4551
|
+
if (generation === loadGenerationRef.current) {
|
|
4552
|
+
setIsLoadingOlderHistory(false);
|
|
4553
|
+
}
|
|
4554
|
+
loadOlderInflightRef.current = null;
|
|
4555
|
+
}
|
|
4556
|
+
})();
|
|
4557
|
+
loadOlderInflightRef.current = run;
|
|
4558
|
+
return run;
|
|
4559
|
+
}, [client, isMain, sessionId, sessionOptions]);
|
|
4238
4560
|
return {
|
|
4239
4561
|
messages,
|
|
4240
4562
|
isRunning,
|
|
4241
4563
|
isLoading,
|
|
4564
|
+
isLoadingOlderHistory,
|
|
4565
|
+
hasOlderHistory,
|
|
4566
|
+
loadOlderHistory,
|
|
4242
4567
|
retryLoad,
|
|
4243
4568
|
sendTurn,
|
|
4244
4569
|
cancel,
|
|
@@ -4279,6 +4604,18 @@ function useTrueFoundryAgentRuntimeImpl(options, pendingAgentSpecRef) {
|
|
|
4279
4604
|
onAgentSpecChange: agent.mode === "draft" ? agent.onAgentSpecChange : void 0,
|
|
4280
4605
|
onError
|
|
4281
4606
|
});
|
|
4607
|
+
const takeTurnHeaderTimestampRef = useRef3(draftSpec.takeTurnHeaderTimestamp);
|
|
4608
|
+
takeTurnHeaderTimestampRef.current = draftSpec.takeTurnHeaderTimestamp;
|
|
4609
|
+
const getTurnHeaders = useCallback3(async () => {
|
|
4610
|
+
if (agent.mode !== "draft") {
|
|
4611
|
+
return void 0;
|
|
4612
|
+
}
|
|
4613
|
+
const updatedAt = await takeTurnHeaderTimestampRef.current();
|
|
4614
|
+
if (updatedAt == null) {
|
|
4615
|
+
return void 0;
|
|
4616
|
+
}
|
|
4617
|
+
return { [DRAFT_SESSION_LAST_UPDATED_AT_HEADER]: updatedAt };
|
|
4618
|
+
}, [agent.mode]);
|
|
4282
4619
|
const aui = useAui();
|
|
4283
4620
|
const initializeSession = useCallback3(
|
|
4284
4621
|
() => aui.threadListItem().initialize(),
|
|
@@ -4290,6 +4627,9 @@ function useTrueFoundryAgentRuntimeImpl(options, pendingAgentSpecRef) {
|
|
|
4290
4627
|
messages,
|
|
4291
4628
|
isRunning,
|
|
4292
4629
|
isLoading,
|
|
4630
|
+
isLoadingOlderHistory,
|
|
4631
|
+
hasOlderHistory,
|
|
4632
|
+
loadOlderHistory,
|
|
4293
4633
|
sendTurn,
|
|
4294
4634
|
cancel,
|
|
4295
4635
|
respondToToolApproval,
|
|
@@ -4305,7 +4645,8 @@ function useTrueFoundryAgentRuntimeImpl(options, pendingAgentSpecRef) {
|
|
|
4305
4645
|
listEventsConcurrency,
|
|
4306
4646
|
onError,
|
|
4307
4647
|
initializeSession,
|
|
4308
|
-
draftGateway: agent.mode === "draft" ? gateway : void 0
|
|
4648
|
+
draftGateway: agent.mode === "draft" ? gateway : void 0,
|
|
4649
|
+
getTurnHeaders: agent.mode === "draft" ? getTurnHeaders : void 0
|
|
4309
4650
|
});
|
|
4310
4651
|
if (agent.mode === "draft" && draftSpec.agentSpec != null) {
|
|
4311
4652
|
pendingAgentSpecRef.current = draftSpec.agentSpec;
|
|
@@ -4374,6 +4715,9 @@ function useTrueFoundryAgentRuntimeImpl(options, pendingAgentSpecRef) {
|
|
|
4374
4715
|
onError?.(error);
|
|
4375
4716
|
}),
|
|
4376
4717
|
reload: retryLoad,
|
|
4718
|
+
hasOlderHistory,
|
|
4719
|
+
isLoadingOlderHistory,
|
|
4720
|
+
loadOlderHistory,
|
|
4377
4721
|
draft: draftExtras
|
|
4378
4722
|
}),
|
|
4379
4723
|
unstable_enableToolInvocations: true,
|
|
@@ -4522,6 +4866,19 @@ var useTrueFoundryReload = () => {
|
|
|
4522
4866
|
const aui = useAui2();
|
|
4523
4867
|
return () => trueFoundryExtras.get(aui).reload();
|
|
4524
4868
|
};
|
|
4869
|
+
var useTrueFoundryHistoryPagination = () => {
|
|
4870
|
+
const extras = trueFoundryExtras.use((e) => e, void 0);
|
|
4871
|
+
return useMemo4(
|
|
4872
|
+
() => ({
|
|
4873
|
+
hasOlderHistory: extras?.hasOlderHistory ?? false,
|
|
4874
|
+
isLoadingOlderHistory: extras?.isLoadingOlderHistory ?? false,
|
|
4875
|
+
loadOlderHistory: extras?.loadOlderHistory ?? (async () => {
|
|
4876
|
+
throw new Error("TrueFoundry runtime is not ready yet");
|
|
4877
|
+
})
|
|
4878
|
+
}),
|
|
4879
|
+
[extras]
|
|
4880
|
+
);
|
|
4881
|
+
};
|
|
4525
4882
|
var useTrueFoundryResetFromTurn = () => {
|
|
4526
4883
|
const aui = useAui2();
|
|
4527
4884
|
return (turnId) => trueFoundryExtras.get(aui).resetFromTurn(turnId);
|
|
@@ -4619,6 +4976,7 @@ export {
|
|
|
4619
4976
|
useTrueFoundryApprovals,
|
|
4620
4977
|
useTrueFoundryCancel,
|
|
4621
4978
|
useTrueFoundryDownloadSandboxFile,
|
|
4979
|
+
useTrueFoundryHistoryPagination,
|
|
4622
4980
|
useTrueFoundryMcpAuth,
|
|
4623
4981
|
useTrueFoundryReload,
|
|
4624
4982
|
useTrueFoundryResetFromTurn,
|