@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.
Files changed (58) hide show
  1. package/README.md +374 -190
  2. package/dist/index.d.ts +32 -29
  3. package/dist/index.js +330 -236
  4. package/dist/index.js.map +1 -1
  5. package/dist/plugins/truefoundry-agent-server-adapter/index.d.ts +30 -0
  6. package/dist/plugins/truefoundry-agent-server-adapter/index.js +198 -0
  7. package/dist/plugins/truefoundry-agent-server-adapter/index.js.map +1 -0
  8. package/dist/types-VUBzoJT2.d.ts +462 -0
  9. package/package.json +10 -2
  10. package/src/askUserQuestion.ts +3 -3
  11. package/src/buildEditedUserMessageContent.test.ts +2 -2
  12. package/src/collectPending.ts +1 -1
  13. package/src/convertTurnMessages.test.ts +141 -196
  14. package/src/convertTurnMessages.ts +130 -76
  15. package/src/createSubAgent.ts +1 -1
  16. package/src/draftAgentConfig.test.ts +26 -29
  17. package/src/extractTurnUserText.ts +1 -1
  18. package/src/foldPeerThreads.test.ts +1 -1
  19. package/src/foldPeerThreads.ts +3 -2
  20. package/src/index.ts +39 -4
  21. package/src/listPages.ts +21 -0
  22. package/src/loadSessionSnapshot.test.ts +9 -8
  23. package/src/loadSessionSnapshot.ts +9 -14
  24. package/src/mcpAuth.ts +6 -3
  25. package/src/messageCustomMetadata.ts +1 -1
  26. package/src/modelMessageContent.ts +1 -1
  27. package/src/modelMessageImageContent.test.ts +1 -1
  28. package/src/modelMessageImageContent.ts +7 -6
  29. package/src/plugins/truefoundry-agent-server-adapter/index.ts +285 -0
  30. package/src/private/agentSpec.ts +8 -3
  31. package/src/private/draftSessionBridge.ts +14 -13
  32. package/src/private/truefoundryDraftThreadListAdapter.test.ts +44 -49
  33. package/src/private/truefoundryDraftThreadListAdapter.ts +22 -16
  34. package/src/requiredActionInputs.ts +1 -1
  35. package/src/requiredActionsFromActiveUpdate.test.ts +1 -1
  36. package/src/server/eventUtils.ts +120 -0
  37. package/src/server/events.ts +246 -0
  38. package/src/server/index.ts +66 -0
  39. package/src/server/types.ts +313 -0
  40. package/src/sessionSnapshot.ts +1 -1
  41. package/src/sessions.ts +5 -21
  42. package/src/streamTurn.test.ts +172 -155
  43. package/src/streamTurn.ts +51 -48
  44. package/src/toolApproval.ts +4 -4
  45. package/src/toolResponse.ts +4 -4
  46. package/src/truefoundryExtras.ts +1 -1
  47. package/src/truefoundryOwnedSessionsThreadListAdapter.test.ts +26 -29
  48. package/src/truefoundryOwnedSessionsThreadListAdapter.ts +18 -23
  49. package/src/truefoundryThreadListAdapter.test.ts +16 -18
  50. package/src/truefoundryThreadListAdapter.ts +7 -7
  51. package/src/turnEventHelpers.ts +1 -1
  52. package/src/types.ts +2 -16
  53. package/src/useTrueFoundryAgentMessages.test.tsx +38 -70
  54. package/src/useTrueFoundryAgentMessages.ts +32 -44
  55. package/src/useTrueFoundryAgentRuntime.ts +11 -28
  56. package/src/private/bindDraftAgentSession.test.ts +0 -54
  57. package/src/private/bindDraftAgentSession.ts +0 -28
  58. 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
- return turn.state.requiredActions?.find(
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/foldPeerThreads.ts
254
- import {
255
- isEventDelta as isEventDelta2
256
- } from "truefoundry-gateway-sdk/agents";
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 (isEventDelta2(message)) {
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
- return turn.state.requiredActions?.find(
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
- return requiredActions?.find(
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(session, options) {
1333
- const page = await session.listEvents({
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 response = page.response;
1339
- const olderPageToken = response.pagination?.nextPageToken;
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(session, options) {
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(session, {
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(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
- }
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(session, onProgress) {
1524
- const turnsPage = await session.listTurns({ limit: 1 });
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(session);
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(session, snapshot) {
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(session, {
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(foldState, turn) {
1698
- for await (const event of await turn.listEvents({
1699
- order: "asc",
1700
- limit: TURN_EVENTS_PAGE_SIZE
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(turn) {
1706
- const events = [];
1707
- for await (const event of await turn.listEvents({
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((events) => {
1727
- results[idx] = events;
1728
- pool.delete(p);
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(session, concurrency = DEFAULT_LIST_EVENTS_CONCURRENCY) {
2015
- const snapshot = await buildSnapshotFromSessionEvents(session);
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([turn], concurrency);
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(session, beforeTurnId, concurrency = DEFAULT_LIST_EVENTS_CONCURRENCY) {
2030
- const turns = await listSessionTurnsOrdered(session);
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(session, beforeIndex, concurrency, turns);
2157
+ return buildSnapshotBeforeTurnIndex(
2158
+ server,
2159
+ sessionId,
2160
+ beforeIndex,
2161
+ concurrency,
2162
+ turns
2163
+ );
2036
2164
  }
2037
- async function buildSnapshotBeforeTurnIndex(session, turnIndex, _concurrency = DEFAULT_LIST_EVENTS_CONCURRENCY, orderedTurns) {
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(session);
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(session, { lastTurnId });
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(session, turnIndex, orderedTurns) {
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(session);
2184
+ const turns = orderedTurns ?? await listSessionTurnsOrdered(server, sessionId);
2057
2185
  return turns[turnIndex - 1]?.id ?? "none";
2058
2186
  }
2059
- async function resolveGatewayBranchPreviousTurnIdForTurn(session, turnId) {
2060
- const turns = await listSessionTurnsOrdered(session);
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(session, turnIndex, turns);
2190
+ return resolveGatewayBranchPreviousTurnId(server, sessionId, turnIndex, turns);
2063
2191
  }
2064
- async function listSessionTurnsOrdered(session) {
2065
- const turns = [];
2066
- for await (const turn of await session.listTurns()) {
2067
- turns.push(turn);
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(state, turn);
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(session) {
2081
- const snapshot = await buildSnapshotFromSession(session);
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(privateClient) {
2465
+ function createDraftSessionBridge(server) {
2341
2466
  return {
2342
2467
  async getDraftAgentSpec(draftSessionId) {
2343
- const draft = await privateClient.getDraftSession({ draftSessionId });
2344
- return draft.agentSpec;
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 gateway = getGatewayFromPrivateClient(privateClient);
2348
- const response = await gateway.agents.private.draftSessions.update(
2349
- draftSessionId,
2350
- { agentSpec }
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 { privateClient, defaultAgentSpec, getAgentSpec } = options;
2517
+ const { server, defaultAgentSpec, getAgentSpec } = options;
2389
2518
  return {
2390
2519
  async list({ after } = {}) {
2391
- const page = await privateClient.listDraftSessions({
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(draft),
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.response.pagination.nextPageToken ?? void 0
2536
+ nextCursor: page.nextPageToken ?? void 0
2405
2537
  };
2406
2538
  },
2407
2539
  async initialize(_threadId) {
2408
- const draft = await privateClient.createDraftSession({
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 privateClient.getDraftSession({
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(draft),
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(client, sessionId, options) {
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 = client.getSession({ sessionId }).finally(() => {
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 { client, agentName } = options;
2604
+ const { server, agentName } = options;
2490
2605
  return {
2491
2606
  async list({ after } = {}) {
2492
- const page = await client.listSessions({
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.response.pagination.nextPageToken ?? void 0
2621
+ nextCursor: page.nextPageToken ?? void 0
2507
2622
  };
2508
2623
  },
2509
2624
  async initialize(_threadId) {
2510
- const session = await client.createSession({ agentName });
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(client, remoteId);
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(client, sessionId, sessionOptions, onProgress) {
2773
- const cacheKey = sessionOptions?.privateClient != null ? `draft:${sessionId}` : sessionId;
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(client, sessionId, sessionOptions).then(
2777
- (session) => buildSnapshotFromSessionEvents(session, onProgress)
2778
- ).finally(() => {
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(cacheKey, inflight);
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(session, abortSignal) {
2927
+ function bindAbort(server, sessionId, abortSignal) {
2822
2928
  const onAbort = () => {
2823
- void session.cancel().catch(() => void 0);
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(session, foldState, options, abortSignal, groupRootBaseline, onTurnIdAvailable) {
2833
- const turn = session.prepareTurn({
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 notifyTurnIdIfAvailable = () => {
2843
- if (!turnIdNotified && turn.id != null) {
2844
- onTurnIdAvailable?.(turn.id);
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
- turn.execute(
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(turn, foldState, abortSignal, afterSequenceNumber, groupRootBaseline) {
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 turn.session.cancel().catch(() => void 0);
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
- turn.stream(
2886
- afterSequenceNumber != null ? { afterSequenceNumber } : {},
2887
- { abortSignal }
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
- client,
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
- client,
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
- turn,
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
- }, [client, runStream, sessionId, sessionOptions, loadRetryTrigger, isMain]);
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
- session,
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
- session,
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
- session,
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
- [client, runStream, sessionId, sessionOptions]
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
- const session = await getSession(client, conversationSessionId, sessionOptions);
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
- }, [client, sessionId, sessionOptions]);
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
- turn,
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
- session,
3572
+ server,
3573
+ conversationSessionId,
3467
3574
  turnId
3468
3575
  );
3469
3576
  const rewound = await buildSnapshotBeforeTurn(
3470
- session,
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
- client,
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
- session,
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
- }, [client, isMain, sessionId, sessionOptions]);
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
- client,
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" && privateClient != null ? createDraftSessionBridge(privateClient) : null
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
- client,
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 (privateClient == null) {
3784
+ if (server.downloadSandboxFile == null) {
3684
3785
  const error = new Error(
3685
- "Downloading a sandbox file requires a `privateClient` PrivateAgentSessionClient."
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
- const response = await privateClient.downloadSandboxFile(sandboxId, { path });
3696
- return await response.blob();
3796
+ return await server.downloadSandboxFile(sandboxId, { path });
3697
3797
  },
3698
- [privateClient, sandboxId, onError]
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 { client, agent, privateClient } = resolved;
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
- privateClient,
3893
+ server,
3799
3894
  defaultAgentSpec: draftAgent.defaultAgentSpec,
3800
3895
  getAgentSpec: () => pendingAgentSpecRef.current ?? draftAgent.defaultAgentSpec
3801
3896
  });
3802
3897
  }
3803
3898
  return createTrueFoundryThreadListAdapter({
3804
- client,
3899
+ server,
3805
3900
  agentName: namedAgentName
3806
3901
  });
3807
- }, [agentMode, namedAgentName, client, privateClient]);
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.type === "session/draft") {
3822
- return draftSessionTitle(session);
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 { privateClient } = options;
3925
+ const { server } = options;
3828
3926
  return {
3829
3927
  async list({ after } = {}) {
3830
- const page = await privateClient.listOwnedSessions({
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.response.pagination.nextPageToken ?? void 0
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 draft = await privateClient.getDraftSession({
3853
- draftSessionId: remoteId
3854
- });
3950
+ const session = await server.getSession({ sessionId: remoteId });
3855
3951
  return {
3856
3952
  status: "regular",
3857
- remoteId: draft.id,
3858
- title: draftSessionTitle(draft),
3859
- lastMessageAt: new Date(draft.updatedAt)
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,