@truefoundry/assistant-ui-runtime 0.1.4 → 0.1.6-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/README.md +374 -190
  2. package/dist/index.d.ts +32 -29
  3. package/dist/index.js +334 -241
  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 +12 -4
  10. package/src/askUserQuestion.ts +3 -3
  11. package/src/collectPending.ts +1 -1
  12. package/src/convertTurnMessages.test.ts +141 -196
  13. package/src/convertTurnMessages.ts +131 -77
  14. package/src/createSubAgent.ts +1 -1
  15. package/src/draftAgentConfig.test.ts +26 -29
  16. package/src/extractTurnUserText.ts +1 -1
  17. package/src/foldPeerThreads.test.ts +1 -1
  18. package/src/foldPeerThreads.ts +3 -2
  19. package/src/index.ts +39 -4
  20. package/src/listPages.ts +21 -0
  21. package/src/loadSessionSnapshot.test.ts +9 -8
  22. package/src/loadSessionSnapshot.ts +9 -14
  23. package/src/mcpAuth.ts +6 -3
  24. package/src/messageCustomMetadata.ts +1 -1
  25. package/src/modelMessageContent.ts +1 -1
  26. package/src/modelMessageImageContent.test.ts +1 -1
  27. package/src/modelMessageImageContent.ts +7 -6
  28. package/src/plugins/truefoundry-agent-server-adapter/index.ts +285 -0
  29. package/src/private/agentSpec.ts +8 -3
  30. package/src/private/draftSessionBridge.ts +14 -13
  31. package/src/private/truefoundryDraftThreadListAdapter.test.ts +44 -49
  32. package/src/private/truefoundryDraftThreadListAdapter.ts +22 -16
  33. package/src/requiredActionInputs.ts +1 -1
  34. package/src/requiredActionsFromActiveUpdate.test.ts +1 -1
  35. package/src/server/eventUtils.ts +120 -0
  36. package/src/server/events.ts +246 -0
  37. package/src/server/index.ts +66 -0
  38. package/src/server/types.ts +313 -0
  39. package/src/sessionSnapshot.ts +1 -1
  40. package/src/sessions.ts +5 -21
  41. package/src/streamTurn.test.ts +175 -158
  42. package/src/streamTurn.ts +51 -57
  43. package/src/toolApproval.ts +4 -4
  44. package/src/toolResponse.ts +4 -4
  45. package/src/truefoundryExtras.ts +1 -1
  46. package/src/truefoundryOwnedSessionsThreadListAdapter.test.ts +26 -29
  47. package/src/truefoundryOwnedSessionsThreadListAdapter.ts +18 -23
  48. package/src/truefoundryThreadListAdapter.test.ts +16 -18
  49. package/src/truefoundryThreadListAdapter.ts +9 -9
  50. package/src/turnEventHelpers.ts +1 -1
  51. package/src/types.ts +2 -16
  52. package/src/useTrueFoundryAgentMessages.test.tsx +38 -70
  53. package/src/useTrueFoundryAgentMessages.ts +33 -45
  54. package/src/useTrueFoundryAgentRuntime.ts +11 -28
  55. package/src/private/bindDraftAgentSession.test.ts +0 -54
  56. package/src/private/bindDraftAgentSession.ts +0 -28
  57. 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
- return null;
2182
+ return "none";
2055
2183
  }
2056
- const turns = orderedTurns ?? await listSessionTurnsOrdered(session);
2057
- return turns[turnIndex - 1]?.id ?? null;
2184
+ const turns = orderedTurns ?? await listSessionTurnsOrdered(server, sessionId);
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,
@@ -2498,24 +2613,24 @@ function createTrueFoundryThreadListAdapter(options) {
2498
2613
  const threads = page.data.map((session) => ({
2499
2614
  status: "regular",
2500
2615
  remoteId: session.id,
2501
- title: session.title,
2616
+ title: session.title ?? void 0,
2502
2617
  lastMessageAt: new Date(session.updatedAt)
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,
2518
- title: session.title,
2633
+ title: session.title ?? void 0,
2519
2634
  lastMessageAt: new Date(session.updatedAt)
2520
2635
  };
2521
2636
  },
@@ -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,41 +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 previousTurnId = options.previousTurnId === null ? null : options.previousTurnId ?? "auto";
2834
- const turn = session.prepareTurn({
2835
- input: buildTurnInput(options),
2836
- ...previousTurnId !== void 0 ? { previousTurnId } : {}
2837
- });
2838
- const onAbort = bindAbort(session, abortSignal);
2938
+ async function* streamTurnContent(server, sessionId, foldState, options, abortSignal, groupRootBaseline, onTurnIdAvailable) {
2939
+ const onAbort = bindAbort(server, sessionId, abortSignal);
2839
2940
  if (abortSignal.aborted) {
2840
2941
  return;
2841
2942
  }
2842
2943
  let turnIdNotified = false;
2843
- const notifyTurnIdIfAvailable = () => {
2844
- if (!turnIdNotified && turn.id != null) {
2845
- onTurnIdAvailable?.(turn.id);
2944
+ const notifyTurnId = (turnId) => {
2945
+ if (!turnIdNotified) {
2946
+ onTurnIdAvailable?.(turnId);
2846
2947
  turnIdNotified = true;
2847
2948
  }
2848
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
+ });
2849
2957
  try {
2850
2958
  for await (const update of streamTurnEvents(
2851
- turn.execute(
2852
- { stream: true },
2853
- {
2854
- abortSignal,
2855
- ...options.headers != null ? { headers: options.headers } : {}
2856
- }
2857
- ),
2959
+ stream,
2858
2960
  foldState,
2859
- groupRootBaseline
2961
+ groupRootBaseline,
2962
+ notifyTurnId
2860
2963
  )) {
2861
- notifyTurnIdIfAvailable();
2862
2964
  yield update;
2863
2965
  }
2864
- notifyTurnIdIfAvailable();
2865
2966
  } catch (error) {
2866
- notifyTurnIdIfAvailable();
2867
2967
  if (error instanceof Error && error.name === "AbortError") {
2868
2968
  return;
2869
2969
  }
@@ -2872,9 +2972,14 @@ async function* streamTurnContent(session, foldState, options, abortSignal, grou
2872
2972
  abortSignal.removeEventListener("abort", onAbort);
2873
2973
  }
2874
2974
  }
2875
- 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
+ }
2876
2981
  const onAbort = () => {
2877
- void turn.session.cancel().catch(() => void 0);
2982
+ void server.cancelSession({ sessionId }).catch(() => void 0);
2878
2983
  };
2879
2984
  if (abortSignal.aborted) {
2880
2985
  onAbort();
@@ -2883,10 +2988,12 @@ async function* resumeTurnStream(turn, foldState, abortSignal, afterSequenceNumb
2883
2988
  abortSignal.addEventListener("abort", onAbort, { once: true });
2884
2989
  try {
2885
2990
  yield* streamTurnEvents(
2886
- turn.stream(
2887
- afterSequenceNumber != null ? { afterSequenceNumber } : {},
2888
- { abortSignal }
2889
- ),
2991
+ server.subscribeToTurn({
2992
+ sessionId,
2993
+ turnId,
2994
+ ...afterSequenceNumber != null ? { afterSequenceNumber } : {},
2995
+ abortSignal
2996
+ }),
2890
2997
  foldState,
2891
2998
  groupRootBaseline
2892
2999
  );
@@ -3022,20 +3129,15 @@ function resolveTurnInput(snapshot, turnId) {
3022
3129
  return void 0;
3023
3130
  }
3024
3131
  function useTrueFoundryAgentMessages({
3025
- client,
3132
+ server,
3026
3133
  sessionId,
3027
3134
  isMain,
3028
3135
  listEventsConcurrency,
3029
3136
  onError,
3030
3137
  initializeSession,
3031
3138
  resolveConversationSessionId,
3032
- privateClient,
3033
3139
  getTurnHeaders
3034
3140
  }) {
3035
- const sessionOptions = useMemo2(
3036
- () => privateClient != null ? { privateClient } : void 0,
3037
- [privateClient]
3038
- );
3039
3141
  const [snapshot, setSnapshot] = useState2(createEmptySessionSnapshot);
3040
3142
  const [isRunning, setIsRunning] = useState2(false);
3041
3143
  const [isLoading, setIsLoading] = useState2(false);
@@ -3195,9 +3297,8 @@ function useTrueFoundryAgentMessages({
3195
3297
  resolveConversationSessionIdRef.current
3196
3298
  );
3197
3299
  const loadedSnapshot = await loadSessionSnapshot(
3198
- client,
3300
+ server,
3199
3301
  conversationSessionId,
3200
- sessionOptions,
3201
3302
  (snap) => {
3202
3303
  if (generation === loadGenerationRef.current) {
3203
3304
  setSnapshot(snap);
@@ -3216,7 +3317,9 @@ function useTrueFoundryAgentMessages({
3216
3317
  const isContinuation = !extractTurnUserText(turn.input);
3217
3318
  void runStream(
3218
3319
  (signal) => resumeTurnStream(
3219
- turn,
3320
+ server,
3321
+ conversationSessionId,
3322
+ turn.id,
3220
3323
  loadedSnapshot.fold,
3221
3324
  signal,
3222
3325
  void 0,
@@ -3236,7 +3339,7 @@ function useTrueFoundryAgentMessages({
3236
3339
  setIsLoading(false);
3237
3340
  }
3238
3341
  }
3239
- }, [client, runStream, sessionId, sessionOptions, loadRetryTrigger, isMain]);
3342
+ }, [server, runStream, sessionId, loadRetryTrigger, isMain]);
3240
3343
  useEffect2(() => {
3241
3344
  void load().catch(() => void 0);
3242
3345
  }, [load]);
@@ -3255,7 +3358,6 @@ function useTrueFoundryAgentMessages({
3255
3358
  activeSessionId,
3256
3359
  resolveConversationSessionIdRef.current
3257
3360
  );
3258
- const session = await getSession(client, conversationSessionId, sessionOptions);
3259
3361
  const turnHeaders = await getTurnHeadersRef.current?.();
3260
3362
  const streamHeaders = turnHeaders != null ? { headers: turnHeaders } : {};
3261
3363
  const isContinuation = "inputs" in options || "resumeMcpAuth" in options && options.resumeMcpAuth === true;
@@ -3316,7 +3418,8 @@ function useTrueFoundryAgentMessages({
3316
3418
  (signal) => {
3317
3419
  if ("inputs" in options) {
3318
3420
  return streamTurnContent(
3319
- session,
3421
+ server,
3422
+ conversationSessionId,
3320
3423
  snapshotRef.current.fold,
3321
3424
  { inputs: options.inputs, ...streamHeaders },
3322
3425
  signal,
@@ -3325,7 +3428,8 @@ function useTrueFoundryAgentMessages({
3325
3428
  }
3326
3429
  if ("resumeMcpAuth" in options) {
3327
3430
  return streamTurnContent(
3328
- session,
3431
+ server,
3432
+ conversationSessionId,
3329
3433
  snapshotRef.current.fold,
3330
3434
  { resumeMcpAuth: true, ...streamHeaders },
3331
3435
  signal,
@@ -3333,11 +3437,12 @@ function useTrueFoundryAgentMessages({
3333
3437
  );
3334
3438
  }
3335
3439
  return streamTurnContent(
3336
- session,
3440
+ server,
3441
+ conversationSessionId,
3337
3442
  snapshotRef.current.fold,
3338
3443
  {
3339
3444
  userMessage: options.userMessage,
3340
- ...options.previousTurnId !== void 0 ? { previousTurnId: options.previousTurnId } : isFirstTurnInSession ? { previousTurnId: null } : {},
3445
+ ...options.previousTurnId !== void 0 ? { previousTurnId: options.previousTurnId ?? "none" } : isFirstTurnInSession ? { previousTurnId: "none" } : {},
3341
3446
  ...streamHeaders
3342
3447
  },
3343
3448
  signal,
@@ -3363,7 +3468,7 @@ function useTrueFoundryAgentMessages({
3363
3468
  isContinuation
3364
3469
  );
3365
3470
  },
3366
- [client, runStream, sessionId, sessionOptions]
3471
+ [server, runStream, sessionId]
3367
3472
  );
3368
3473
  const cancel = useCallback2(async () => {
3369
3474
  if (sessionId == null) {
@@ -3374,10 +3479,9 @@ function useTrueFoundryAgentMessages({
3374
3479
  sessionId,
3375
3480
  resolveConversationSessionIdRef.current
3376
3481
  );
3377
- const session = await getSession(client, conversationSessionId, sessionOptions);
3378
- await session.cancel().catch(() => void 0);
3482
+ await server.cancelSession({ sessionId: conversationSessionId }).catch(() => void 0);
3379
3483
  await activeRunRef.current?.catch(() => void 0);
3380
- }, [client, sessionId, sessionOptions]);
3484
+ }, [server, sessionId]);
3381
3485
  const isRunningRef = useRef2(isRunning);
3382
3486
  isRunningRef.current = isRunning;
3383
3487
  const trySendCollectedRequiredActions = useCallback2(
@@ -3439,7 +3543,9 @@ function useTrueFoundryAgentMessages({
3439
3543
  }
3440
3544
  await runStream(
3441
3545
  (signal) => resumeTurnStream(
3442
- turn,
3546
+ server,
3547
+ turn.sessionId,
3548
+ turn.id,
3443
3549
  snapshotRef.current.fold,
3444
3550
  signal,
3445
3551
  void 0,
@@ -3448,7 +3554,7 @@ function useTrueFoundryAgentMessages({
3448
3554
  { current: turn.id },
3449
3555
  true
3450
3556
  );
3451
- }, [runStream]);
3557
+ }, [runStream, server]);
3452
3558
  const branchFromTurn = useCallback2(
3453
3559
  async (turnId, userMessage) => {
3454
3560
  let activeSessionId = sessionId;
@@ -3462,13 +3568,14 @@ function useTrueFoundryAgentMessages({
3462
3568
  activeSessionId,
3463
3569
  resolveConversationSessionIdRef.current
3464
3570
  );
3465
- const session = await getSession(client, conversationSessionId, sessionOptions);
3466
3571
  const previousTurnId = await resolveGatewayBranchPreviousTurnIdForTurn(
3467
- session,
3572
+ server,
3573
+ conversationSessionId,
3468
3574
  turnId
3469
3575
  );
3470
3576
  const rewound = await buildSnapshotBeforeTurn(
3471
- session,
3577
+ server,
3578
+ conversationSessionId,
3472
3579
  turnId,
3473
3580
  listEventsConcurrency
3474
3581
  );
@@ -3483,11 +3590,10 @@ function useTrueFoundryAgentMessages({
3483
3590
  },
3484
3591
  [
3485
3592
  cancel,
3486
- client,
3593
+ server,
3487
3594
  listEventsConcurrency,
3488
3595
  sendTurn,
3489
- sessionId,
3490
- sessionOptions
3596
+ sessionId
3491
3597
  ]
3492
3598
  );
3493
3599
  const resetFromTurn = useCallback2(
@@ -3543,13 +3649,9 @@ function useTrueFoundryAgentMessages({
3543
3649
  sessionId,
3544
3650
  resolveConversationSessionIdRef.current
3545
3651
  );
3546
- const session = await getSession(
3547
- client,
3548
- conversationSessionId,
3549
- sessionOptions
3550
- );
3551
3652
  const next = await prependOlderSessionHistory(
3552
- session,
3653
+ server,
3654
+ conversationSessionId,
3553
3655
  snapshotRef.current
3554
3656
  );
3555
3657
  if (generation !== loadGenerationRef.current) {
@@ -3570,7 +3672,7 @@ function useTrueFoundryAgentMessages({
3570
3672
  })();
3571
3673
  loadOlderInflightRef.current = run;
3572
3674
  return run;
3573
- }, [client, isMain, sessionId, sessionOptions]);
3675
+ }, [server, isMain, sessionId]);
3574
3676
  return {
3575
3677
  messages,
3576
3678
  isRunning,
@@ -3593,16 +3695,15 @@ function useTrueFoundryAgentMessages({
3593
3695
  // src/useTrueFoundryAgentRuntime.ts
3594
3696
  function useTrueFoundryAgentRuntimeImpl(options, pendingAgentSpecRef) {
3595
3697
  const {
3596
- client,
3698
+ server,
3597
3699
  agent,
3598
- privateClient,
3599
3700
  adapters,
3600
3701
  onError,
3601
3702
  listEventsConcurrency,
3602
3703
  ...sharedOptions
3603
3704
  } = options;
3604
3705
  const draftBridgeRef = useRef3(
3605
- agent.mode === "draft" && privateClient != null ? createDraftSessionBridge(privateClient) : null
3706
+ agent.mode === "draft" ? createDraftSessionBridge(server) : null
3606
3707
  );
3607
3708
  const draftSessionId = useAuiState(
3608
3709
  (state) => agent.mode === "draft" ? state.threadListItem.remoteId ?? void 0 : void 0
@@ -3653,13 +3754,12 @@ function useTrueFoundryAgentRuntimeImpl(options, pendingAgentSpecRef) {
3653
3754
  resetFromTurn,
3654
3755
  retryLoad
3655
3756
  } = useTrueFoundryAgentMessages({
3656
- client,
3757
+ server,
3657
3758
  sessionId,
3658
3759
  isMain,
3659
3760
  listEventsConcurrency,
3660
3761
  onError,
3661
3762
  initializeSession,
3662
- privateClient: agent.mode === "draft" ? privateClient : void 0,
3663
3763
  getTurnHeaders: agent.mode === "draft" ? getTurnHeaders : void 0
3664
3764
  });
3665
3765
  if (agent.mode === "draft" && draftSpec.agentSpec != null) {
@@ -3681,9 +3781,9 @@ function useTrueFoundryAgentRuntimeImpl(options, pendingAgentSpecRef) {
3681
3781
  );
3682
3782
  const downloadSandboxFile = useCallback3(
3683
3783
  async (path) => {
3684
- if (privateClient == null) {
3784
+ if (server.downloadSandboxFile == null) {
3685
3785
  const error = new Error(
3686
- "Downloading a sandbox file requires a `privateClient` PrivateAgentSessionClient."
3786
+ "Downloading a sandbox file requires AgentChatServer.downloadSandboxFile."
3687
3787
  );
3688
3788
  onError?.(error);
3689
3789
  throw error;
@@ -3693,10 +3793,9 @@ function useTrueFoundryAgentRuntimeImpl(options, pendingAgentSpecRef) {
3693
3793
  onError?.(error);
3694
3794
  throw error;
3695
3795
  }
3696
- const response = await privateClient.downloadSandboxFile(sandboxId, { path });
3697
- return await response.blob();
3796
+ return await server.downloadSandboxFile(sandboxId, { path });
3698
3797
  },
3699
- [privateClient, sandboxId, onError]
3798
+ [server, sandboxId, onError]
3700
3799
  );
3701
3800
  const draftExtras = useMemo3(() => {
3702
3801
  if (agent.mode !== "draft") {
@@ -3781,7 +3880,7 @@ function useTrueFoundryAgentRuntimeImpl(options, pendingAgentSpecRef) {
3781
3880
  }
3782
3881
  function useTrueFoundryAgentRuntime(options) {
3783
3882
  const resolved = resolveTrueFoundryAgentRuntimeOptions(options);
3784
- const { client, agent, privateClient } = resolved;
3883
+ const { server, agent } = resolved;
3785
3884
  const pendingAgentSpecRef = useRef3(
3786
3885
  agent.mode === "draft" ? agent.defaultAgentSpec : void 0
3787
3886
  );
@@ -3789,23 +3888,18 @@ function useTrueFoundryAgentRuntime(options) {
3789
3888
  const namedAgentName = agent.mode === "named" ? agent.agentName : void 0;
3790
3889
  const threadListAdapter = useMemo3(() => {
3791
3890
  if (agentMode === "draft") {
3792
- if (privateClient == null) {
3793
- throw new Error(
3794
- "Draft agent mode requires a `privateClient` PrivateAgentSessionClient."
3795
- );
3796
- }
3797
3891
  const draftAgent = agent;
3798
3892
  return createTrueFoundryDraftThreadListAdapter({
3799
- privateClient,
3893
+ server,
3800
3894
  defaultAgentSpec: draftAgent.defaultAgentSpec,
3801
3895
  getAgentSpec: () => pendingAgentSpecRef.current ?? draftAgent.defaultAgentSpec
3802
3896
  });
3803
3897
  }
3804
3898
  return createTrueFoundryThreadListAdapter({
3805
- client,
3899
+ server,
3806
3900
  agentName: namedAgentName
3807
3901
  });
3808
- }, [agentMode, namedAgentName, client, privateClient]);
3902
+ }, [agentMode, namedAgentName, server]);
3809
3903
  return useRemoteThreadListRuntime({
3810
3904
  allowNesting: true,
3811
3905
  adapter: threadListAdapter,
@@ -3819,16 +3913,19 @@ function useTrueFoundryAgentRuntime(options) {
3819
3913
  // src/truefoundryOwnedSessionsThreadListAdapter.ts
3820
3914
  var THREAD_LIST_PAGE_SIZE3 = 20;
3821
3915
  function ownedSessionTitle(session) {
3822
- if (session.type === "session/draft") {
3823
- return draftSessionTitle(session);
3916
+ if (session.isMutable && session.agentSpec != null) {
3917
+ return draftSessionTitle({
3918
+ title: session.title,
3919
+ agentSpec: session.agentSpec
3920
+ });
3824
3921
  }
3825
- return session.title ?? session.agentName;
3922
+ return session.title ?? session.agentName ?? session.id;
3826
3923
  }
3827
3924
  function createTrueFoundryOwnedSessionsThreadListAdapter(options) {
3828
- const { privateClient } = options;
3925
+ const { server } = options;
3829
3926
  return {
3830
3927
  async list({ after } = {}) {
3831
- const page = await privateClient.listOwnedSessions({
3928
+ const page = await server.listSessions({
3832
3929
  limit: THREAD_LIST_PAGE_SIZE3,
3833
3930
  pageToken: after,
3834
3931
  startTimestamp: sessionListStartTimestamp()
@@ -3841,7 +3938,7 @@ function createTrueFoundryOwnedSessionsThreadListAdapter(options) {
3841
3938
  }));
3842
3939
  return {
3843
3940
  threads,
3844
- nextCursor: page.response.pagination.nextPageToken ?? void 0
3941
+ nextCursor: page.nextPageToken ?? void 0
3845
3942
  };
3846
3943
  },
3847
3944
  async initialize() {
@@ -3850,14 +3947,12 @@ function createTrueFoundryOwnedSessionsThreadListAdapter(options) {
3850
3947
  );
3851
3948
  },
3852
3949
  async fetch(remoteId) {
3853
- const draft = await privateClient.getDraftSession({
3854
- draftSessionId: remoteId
3855
- });
3950
+ const session = await server.getSession({ sessionId: remoteId });
3856
3951
  return {
3857
3952
  status: "regular",
3858
- remoteId: draft.id,
3859
- title: draftSessionTitle(draft),
3860
- lastMessageAt: new Date(draft.updatedAt)
3953
+ remoteId: session.id,
3954
+ title: ownedSessionTitle(session),
3955
+ lastMessageAt: new Date(session.updatedAt)
3861
3956
  };
3862
3957
  },
3863
3958
  async rename() {
@@ -3874,9 +3969,6 @@ function createTrueFoundryOwnedSessionsThreadListAdapter(options) {
3874
3969
  };
3875
3970
  }
3876
3971
 
3877
- // src/index.ts
3878
- import { PrivateAgentSessionClient } from "truefoundry-gateway-sdk/agents/private";
3879
-
3880
3972
  // src/hooks.ts
3881
3973
  import { useMemo as useMemo4 } from "react";
3882
3974
  import { useAui as useAui2 } from "@assistant-ui/store";
@@ -4021,7 +4113,6 @@ var trueFoundryAttachmentAdapter = {
4021
4113
  }
4022
4114
  };
4023
4115
  export {
4024
- PrivateAgentSessionClient,
4025
4116
  ROOT_THREAD_ID,
4026
4117
  TOOL_RESPONSE_THREAD_ID_CUSTOM_KEY,
4027
4118
  buildEditedUserMessageContent,
@@ -4039,7 +4130,9 @@ export {
4039
4130
  findPausedAssistantMessage,
4040
4131
  getSession,
4041
4132
  getTurnMessageContent,
4133
+ isEventDelta,
4042
4134
  mergeAgentSpec,
4135
+ mergeEventDelta,
4043
4136
  messageHasPendingApprovals,
4044
4137
  messageHasPendingRequiredActions,
4045
4138
  messageHasPendingResponses,