@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
@@ -1,4 +1,4 @@
1
- import type { AgentSessionClient } from "truefoundry-gateway-sdk/agents";
1
+ import type { AgentChatServer } from "./server/index.js";
2
2
  import { beforeEach, describe, expect, it, vi } from "vitest";
3
3
 
4
4
  import { createEmptySessionSnapshot } from "./sessionSnapshot.js";
@@ -19,7 +19,7 @@ import { buildSnapshotFromSessionEvents } from "./convertTurnMessages.js";
19
19
  import { loadSessionSnapshot } from "./loadSessionSnapshot.js";
20
20
  import { getSession } from "./sessions.js";
21
21
 
22
- const mockClient = {} as AgentSessionClient;
22
+ const mockServer = {} as AgentChatServer;
23
23
 
24
24
  describe("loadSessionSnapshot", () => {
25
25
  beforeEach(() => {
@@ -33,8 +33,8 @@ describe("loadSessionSnapshot", () => {
33
33
  );
34
34
 
35
35
  const [first, second] = await Promise.all([
36
- loadSessionSnapshot(mockClient, "session-1"),
37
- loadSessionSnapshot(mockClient, "session-1"),
36
+ loadSessionSnapshot(mockServer, "session-1"),
37
+ loadSessionSnapshot(mockServer, "session-1"),
38
38
  ]);
39
39
 
40
40
  expect(first).toBe(second);
@@ -48,8 +48,8 @@ describe("loadSessionSnapshot", () => {
48
48
  createEmptySessionSnapshot(),
49
49
  );
50
50
 
51
- await loadSessionSnapshot(mockClient, "session-1");
52
- await loadSessionSnapshot(mockClient, "session-1");
51
+ await loadSessionSnapshot(mockServer, "session-1");
52
+ await loadSessionSnapshot(mockServer, "session-1");
53
53
 
54
54
  expect(getSession).toHaveBeenCalledTimes(2);
55
55
  expect(buildSnapshotFromSessionEvents).toHaveBeenCalledTimes(2);
@@ -62,10 +62,11 @@ describe("loadSessionSnapshot", () => {
62
62
  );
63
63
 
64
64
  const onProgress = vi.fn();
65
- await loadSessionSnapshot(mockClient, "session-1", undefined, onProgress);
65
+ await loadSessionSnapshot(mockServer, "session-1", onProgress);
66
66
 
67
67
  expect(buildSnapshotFromSessionEvents).toHaveBeenCalledWith(
68
- {},
68
+ mockServer,
69
+ "session-1",
69
70
  onProgress,
70
71
  );
71
72
  });
@@ -1,7 +1,7 @@
1
- import type { AgentSessionClient } from "truefoundry-gateway-sdk/agents";
1
+ import type { AgentChatServer } from "./server/types.js";
2
2
 
3
3
  import { buildSnapshotFromSessionEvents } from "./convertTurnMessages.js";
4
- import { getSession, type GetSessionOptions } from "./sessions.js";
4
+ import { getSession } from "./sessions.js";
5
5
  import type { SessionSnapshot } from "./sessionSnapshot.js";
6
6
 
7
7
  const inflightBySessionId = new Map<string, Promise<SessionSnapshot>>();
@@ -15,25 +15,20 @@ const inflightBySessionId = new Map<string, Promise<SessionSnapshot>>();
15
15
  * can update the UI progressively while history is being processed.
16
16
  */
17
17
  export function loadSessionSnapshot(
18
- client: AgentSessionClient,
18
+ server: AgentChatServer,
19
19
  sessionId: string,
20
- sessionOptions?: GetSessionOptions,
21
20
  onProgress?: (snap: SessionSnapshot) => void,
22
21
  ): Promise<SessionSnapshot> {
23
- const cacheKey =
24
- sessionOptions?.privateClient != null ? `draft:${sessionId}` : sessionId;
25
- let inflight = inflightBySessionId.get(cacheKey);
22
+ let inflight = inflightBySessionId.get(sessionId);
26
23
  if (inflight == null) {
27
- inflight = getSession(client, sessionId, sessionOptions)
28
- .then((session) =>
29
- buildSnapshotFromSessionEvents(session, onProgress),
30
- )
24
+ inflight = getSession(server, sessionId)
25
+ .then(() => buildSnapshotFromSessionEvents(server, sessionId, onProgress))
31
26
  .finally(() => {
32
- if (inflightBySessionId.get(cacheKey) === inflight) {
33
- inflightBySessionId.delete(cacheKey);
27
+ if (inflightBySessionId.get(sessionId) === inflight) {
28
+ inflightBySessionId.delete(sessionId);
34
29
  }
35
30
  });
36
- inflightBySessionId.set(cacheKey, inflight);
31
+ inflightBySessionId.set(sessionId, inflight);
37
32
  }
38
33
  return inflight;
39
34
  }
package/src/mcpAuth.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { MessageStatus } from "@assistant-ui/core";
2
- import type { McpAuthRequiredEvent, TurnStateDone } from "truefoundry-gateway-sdk/agents";
2
+ import type { McpAuthRequiredEvent, TurnStateDone } from "./server/index.js";
3
3
 
4
4
  import type { AssistantContentPart } from "./modelMessageContent.js";
5
5
  import type { McpAuthMessageCustomMetadata } from "./messageCustomMetadata.js";
@@ -28,9 +28,12 @@ export function buildMcpAuthTextParts(
28
28
  export function findMcpAuthRequired(
29
29
  requiredActions: TurnStateDone["requiredActions"] | undefined,
30
30
  ): McpAuthRequiredEvent | undefined {
31
- return requiredActions?.find(
32
- (action): action is McpAuthRequiredEvent => action.type === "mcp.auth_required",
31
+ const found = requiredActions?.find(
32
+ (action) => action.type === "mcp.auth_required",
33
33
  );
34
+ return found?.type === "mcp.auth_required"
35
+ ? (found as McpAuthRequiredEvent)
36
+ : undefined;
34
37
  }
35
38
 
36
39
  export function mcpAuthAssistantStatus(): MessageStatus {
@@ -1,4 +1,4 @@
1
- import type { McpAuthRequiredEvent } from "truefoundry-gateway-sdk/agents";
1
+ import type { McpAuthRequiredEvent } from "./server/index.js";
2
2
 
3
3
  import type { SubAgentCustomMetadata } from "./foldPeerThreads.js";
4
4
  import { TOOL_APPROVAL_THREAD_ID_CUSTOM_KEY } from "./toolApproval.js";
@@ -1,5 +1,5 @@
1
1
  import type { ThreadAssistantMessagePart } from "@assistant-ui/core";
2
- import type { ModelMessageEvent } from "truefoundry-gateway-sdk/agents";
2
+ import type { ModelMessageEvent } from "./server/index.js";
3
3
  import type { PendingResponseRef } from "./foldPeerThreads.js";
4
4
  import { extractImagePartsFromModelMessage } from "./modelMessageImageContent.js";
5
5
 
@@ -1,5 +1,5 @@
1
1
  import { describe, expect, it } from "vitest";
2
- import type { ModelMessageEvent } from "truefoundry-gateway-sdk/agents";
2
+ import type { ModelMessageEvent } from "./server/index.js";
3
3
 
4
4
  import { buildAssistantContent } from "./modelMessageContent.js";
5
5
  import { mergeStreamEventDelta } from "./modelMessageImageContent.js";
@@ -1,10 +1,11 @@
1
1
  import type { CompleteAttachment } from "@assistant-ui/core";
2
- import type {
3
- ModelMessageEvent,
4
- TurnEvent,
5
- TurnStreamingEvent,
6
- } from "truefoundry-gateway-sdk/agents";
7
- import { isEventDelta, mergeEventDelta } from "truefoundry-gateway-sdk/agents";
2
+ import {
3
+ isEventDelta,
4
+ mergeEventDelta,
5
+ type ModelMessageEvent,
6
+ type TurnEvent,
7
+ type TurnStreamingEvent,
8
+ } from "./server/index.js";
8
9
 
9
10
  import type { AssistantContentPart } from "./modelMessageContent.js";
10
11
 
@@ -0,0 +1,285 @@
1
+ import { AgentSessionClient } from "truefoundry-gateway-sdk/agents";
2
+ import type { AgentSession } from "truefoundry-gateway-sdk/agents";
3
+ import { PrivateAgentSessionClient } from "truefoundry-gateway-sdk/agents/private";
4
+ import type { AgentDraftSession } from "truefoundry-gateway-sdk/agents/private";
5
+ import type {
6
+ AgentChatServer,
7
+ AgentSpec,
8
+ ListResult,
9
+ Session,
10
+ Turn,
11
+ TurnInputItem,
12
+ PreviousTurnIdInput,
13
+ } from "../../server/types.js";
14
+ import type {
15
+ TurnEvent,
16
+ TurnStreamData,
17
+ SessionEventItem,
18
+ } from "../../server/events.js";
19
+
20
+ type GwSession = AgentSession | AgentDraftSession;
21
+
22
+ export type CreateTrueFoundryChatServerOptions = {
23
+ apiKey: string;
24
+ baseUrl: string;
25
+ /** Optional override — otherwise constructed from apiKey/baseUrl. */
26
+ client?: AgentSessionClient;
27
+ privateClient?: PrivateAgentSessionClient;
28
+ deleteSession?: (req: { sessionId: string }) => Promise<void>;
29
+ };
30
+
31
+ export type TrueFoundryChatServer = AgentChatServer & {
32
+ /** Escape hatch for hosts that still need raw gateway clients. */
33
+ getGatewayClients(): {
34
+ client: AgentSessionClient;
35
+ privateClient: PrivateAgentSessionClient;
36
+ };
37
+ };
38
+
39
+ function isDraft(session: GwSession): session is AgentDraftSession {
40
+ return (session as AgentDraftSession).type === "session/draft";
41
+ }
42
+
43
+ function toSession(raw: GwSession): Session {
44
+ const mutable = isDraft(raw);
45
+ return {
46
+ id: raw.id,
47
+ title: raw.title,
48
+ agentName: raw.agentName,
49
+ ...(mutable ? { agentSpec: raw.agentSpec as AgentSpec } : {}),
50
+ isMutable: mutable,
51
+ createdAt: raw.createdAt,
52
+ updatedAt: raw.updatedAt,
53
+ };
54
+ }
55
+
56
+ function toTurn(raw: {
57
+ id: string;
58
+ sessionId: string;
59
+ previousTurnId?: string | null;
60
+ input?: TurnInputItem[];
61
+ state: Turn["state"];
62
+ createdAt: string;
63
+ }): Turn {
64
+ return {
65
+ id: raw.id,
66
+ sessionId: raw.sessionId,
67
+ previousTurnId: raw.previousTurnId,
68
+ input: raw.input as TurnInputItem[] | undefined,
69
+ state: raw.state as Turn["state"],
70
+ createdAt: raw.createdAt,
71
+ };
72
+ }
73
+
74
+ async function toListResult<TIn, TOut>(
75
+ page: {
76
+ data: TIn[];
77
+ response?: { pagination?: { nextPageToken?: string } };
78
+ hasNextPage?: () => boolean;
79
+ },
80
+ map: (item: TIn) => TOut,
81
+ ): Promise<ListResult<TOut>> {
82
+ const nextPageToken = page.response?.pagination?.nextPageToken;
83
+ return {
84
+ data: page.data.map(map),
85
+ ...(nextPageToken != null && nextPageToken !== ""
86
+ ? { nextPageToken }
87
+ : {}),
88
+ };
89
+ }
90
+
91
+ /**
92
+ * Wraps TrueFoundry gateway clients into a flat `AgentChatServer`.
93
+ * Named vs draft routing is fully internal — an in-memory session-type cache
94
+ * (populated by createSession/listSessions) determines which gateway client
95
+ * to call. No try/catch fallback, no double network calls.
96
+ */
97
+ export function createTrueFoundryChatServer(
98
+ opts: CreateTrueFoundryChatServerOptions,
99
+ ): TrueFoundryChatServer {
100
+ const gatewayOpts = { apiKey: opts.apiKey, baseUrl: opts.baseUrl };
101
+ const client = opts.client ?? new AgentSessionClient(gatewayOpts);
102
+ const privateClient =
103
+ opts.privateClient ?? new PrivateAgentSessionClient(gatewayOpts);
104
+
105
+ const sessionTypeCache = new Map<string, boolean>();
106
+
107
+ function cacheSessionType(session: Session): void {
108
+ sessionTypeCache.set(session.id, session.isMutable);
109
+ }
110
+
111
+ function getSessionObj(sessionId: string): Promise<GwSession> {
112
+ const isMutable = sessionTypeCache.get(sessionId);
113
+ if (isMutable === true) {
114
+ return privateClient.getDraftSession({ draftSessionId: sessionId });
115
+ }
116
+ if (isMutable === false) {
117
+ return client.getSession({ sessionId });
118
+ }
119
+ throw new Error(
120
+ `Cannot resolve session "${sessionId}": session type not cached. ` +
121
+ `Ensure createSession or listSessions was called first.`,
122
+ );
123
+ }
124
+
125
+ const server: TrueFoundryChatServer = {
126
+ async createSession(req) {
127
+ if (req.agentSpec != null) {
128
+ const draft = await privateClient.createDraftSession({
129
+ agentSpec: req.agentSpec as never,
130
+ ...(req.agentName != null ? { agentName: req.agentName } : {}),
131
+ });
132
+ const session = toSession(draft);
133
+ cacheSessionType(session);
134
+ return session;
135
+ }
136
+ if (req.agentName != null) {
137
+ const named = await client.createSession({
138
+ agentName: req.agentName,
139
+ });
140
+ const session = toSession(named);
141
+ cacheSessionType(session);
142
+ return session;
143
+ }
144
+ throw new Error("createSession requires agentName and/or agentSpec");
145
+ },
146
+
147
+ async listSessions(req) {
148
+ const page = await privateClient.listOwnedSessions({
149
+ limit: req?.limit,
150
+ order: req?.order,
151
+ pageToken: req?.pageToken,
152
+ startTimestamp: req?.startTimestamp,
153
+ ...(req?.agentName != null ? { agentName: req.agentName } : {}),
154
+ });
155
+ const result = await toListResult(page, toSession);
156
+ for (const session of result.data) {
157
+ cacheSessionType(session);
158
+ }
159
+ return result;
160
+ },
161
+
162
+ async getSession({ sessionId }) {
163
+ const raw = await getSessionObj(sessionId);
164
+ const session = toSession(raw);
165
+ cacheSessionType(session);
166
+ return session;
167
+ },
168
+
169
+ async updateSession(req) {
170
+ const raw = await getSessionObj(req.sessionId);
171
+ if (!isDraft(raw)) {
172
+ throw new Error(
173
+ "updateSession: session is not mutable (isMutable=false)",
174
+ );
175
+ }
176
+ if (req.agentSpec != null) {
177
+ await raw.update({ agentSpec: req.agentSpec as never });
178
+ }
179
+ return toSession(raw);
180
+ },
181
+
182
+ prepareAndExecuteTurn(req: {
183
+ sessionId: string;
184
+ input?: TurnInputItem[];
185
+ previousTurnId?: PreviousTurnIdInput;
186
+ abortSignal?: AbortSignal;
187
+ headers?: Record<string, string>;
188
+ }): AsyncIterable<TurnStreamData> {
189
+ return (async function* () {
190
+ const session = await getSessionObj(req.sessionId);
191
+ const prepared = session.prepareTurn({
192
+ input: req.input,
193
+ previousTurnId: req.previousTurnId ?? "auto",
194
+ });
195
+ yield* prepared.execute(
196
+ { stream: true },
197
+ {
198
+ ...(req.abortSignal != null
199
+ ? { abortSignal: req.abortSignal }
200
+ : {}),
201
+ ...(req.headers != null ? { headers: req.headers } : {}),
202
+ },
203
+ ) as AsyncIterable<TurnStreamData>;
204
+ })();
205
+ },
206
+
207
+ async cancelSession({ sessionId }) {
208
+ await (await getSessionObj(sessionId)).cancel();
209
+ },
210
+
211
+ async deleteSession({ sessionId }) {
212
+ if (opts.deleteSession == null) {
213
+ throw new Error(
214
+ "deleteSession is not on the gateway SDK. Pass deleteSession to createTrueFoundryChatServer.",
215
+ );
216
+ }
217
+ await opts.deleteSession({ sessionId });
218
+ },
219
+
220
+ async listTurns({ sessionId, limit, pageToken, order }) {
221
+ const raw = await getSessionObj(sessionId);
222
+ const page = await raw.listTurns({
223
+ ...(limit != null ? { limit } : {}),
224
+ ...(pageToken != null ? { pageToken } : {}),
225
+ ...(order != null ? { order } : {}),
226
+ });
227
+ return toListResult(page, (turn) => toTurn(turn));
228
+ },
229
+
230
+ async getTurn({ sessionId, turnId }) {
231
+ const raw = await getSessionObj(sessionId);
232
+ return toTurn(await raw.getTurn({ turnId }));
233
+ },
234
+
235
+ async listEvents({ sessionId, pageToken, lastTurnId, limit }) {
236
+ const raw = await getSessionObj(sessionId);
237
+ const page = await raw.listEvents({
238
+ ...(limit != null ? { limit } : {}),
239
+ ...(pageToken != null ? { pageToken } : {}),
240
+ ...(lastTurnId != null ? { lastTurnId } : {}),
241
+ });
242
+ return toListResult(
243
+ page,
244
+ (item) => item as SessionEventItem,
245
+ );
246
+ },
247
+
248
+ async listTurnEvents({ sessionId, turnId, limit, pageToken, order }) {
249
+ const raw = await getSessionObj(sessionId);
250
+ const turn = await raw.getTurn({ turnId });
251
+ const page = await turn.listEvents({
252
+ ...(limit != null ? { limit } : {}),
253
+ ...(pageToken != null ? { pageToken } : {}),
254
+ ...(order != null ? { order } : {}),
255
+ });
256
+ return toListResult(page, (event) => event as TurnEvent);
257
+ },
258
+
259
+ async *subscribeToTurn({
260
+ sessionId,
261
+ turnId,
262
+ afterSequenceNumber,
263
+ abortSignal,
264
+ }) {
265
+ const raw = await getSessionObj(sessionId);
266
+ const turn = await raw.getTurn({ turnId });
267
+ yield* turn.stream(
268
+ afterSequenceNumber != null ? { afterSequenceNumber } : {},
269
+ abortSignal != null ? { abortSignal } : {},
270
+ ) as AsyncIterable<TurnStreamData>;
271
+ },
272
+
273
+ async downloadSandboxFile(sandboxId, req) {
274
+ const response = await privateClient.downloadSandboxFile(
275
+ sandboxId,
276
+ req,
277
+ );
278
+ return await response.blob();
279
+ },
280
+
281
+ getGatewayClients: () => ({ client, privateClient }),
282
+ };
283
+
284
+ return server;
285
+ }
@@ -1,7 +1,12 @@
1
- import type { TruefoundryGatewayApi } from "truefoundry-gateway-sdk";
1
+ import type { AgentSpec } from "../server/types.js";
2
2
 
3
- export type AgentSpec = TruefoundryGatewayApi.AgentSpec;
4
- export type DraftSession = TruefoundryGatewayApi.DraftSession;
3
+ export type { AgentSpec } from "../server/types.js";
4
+
5
+ /** @deprecated Use Session with isMutable: true instead. Kept for title helper. */
6
+ export type DraftSession = {
7
+ title?: string | null;
8
+ agentSpec: AgentSpec;
9
+ };
5
10
 
6
11
  export type AgentSpecUpdate = {
7
12
  instructions?: string;
@@ -1,7 +1,5 @@
1
- import type { PrivateAgentSessionClient } from "truefoundry-gateway-sdk/agents/private";
2
-
1
+ import type { AgentChatServer } from "../server/types.js";
3
2
  import type { AgentSpec } from "./agentSpec.js";
4
- import { getGatewayFromPrivateClient } from "./getGatewayFromPrivateClient.js";
5
3
 
6
4
  export const DRAFT_SESSION_LAST_UPDATED_AT_HEADER = "x-tfy-session-last-updated-at";
7
5
 
@@ -11,22 +9,25 @@ export type DraftSessionBridge = {
11
9
  };
12
10
 
13
11
  export function createDraftSessionBridge(
14
- privateClient: PrivateAgentSessionClient,
12
+ server: AgentChatServer,
15
13
  ): DraftSessionBridge {
16
14
  return {
17
15
  async getDraftAgentSpec(draftSessionId) {
18
- const draft = await privateClient.getDraftSession({ draftSessionId });
19
- return draft.agentSpec;
16
+ const session = await server.getSession({ sessionId: draftSessionId });
17
+ if (session.agentSpec == null) {
18
+ throw new Error(
19
+ `Session ${draftSessionId} has no agentSpec (isMutable=${session.isMutable}).`,
20
+ );
21
+ }
22
+ return session.agentSpec;
20
23
  },
21
24
 
22
25
  async syncAgentSpec(draftSessionId, agentSpec) {
23
- // PrivateAgentSessionClient does not wrap update yet — use the low-level client.
24
- const gateway = getGatewayFromPrivateClient(privateClient);
25
- const response = await gateway.agents.private.draftSessions.update(
26
- draftSessionId,
27
- { agentSpec },
28
- );
29
- return response.data.updatedAt;
26
+ const updated = await server.updateSession({
27
+ sessionId: draftSessionId,
28
+ agentSpec,
29
+ });
30
+ return updated.updatedAt;
30
31
  },
31
32
  };
32
33
  }