@opengeni/db 0.2.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -26,6 +26,7 @@ import {
26
26
  sessionEvents,
27
27
  sessionGoals,
28
28
  sessionHistoryItems,
29
+ sessionMcpServers,
29
30
  sessionRecordings,
30
31
  sessionTurns,
31
32
  sessions,
@@ -38,7 +39,7 @@ import {
38
39
  workspaceMemberships,
39
40
  workspacePacks,
40
41
  workspaces
41
- } from "./chunk-PSX56ZTL.js";
42
+ } from "./chunk-T2U4H4Z2.js";
42
43
  import {
43
44
  migrate,
44
45
  runMigrations
@@ -144,12 +145,64 @@ function sanitizeEventPayload(payload) {
144
145
  }
145
146
  if (payload && typeof payload === "object") {
146
147
  const entries = Object.entries(payload).map(
147
- ([key, value]) => [sanitizeEventString(key), sanitizeEventPayload(value)]
148
+ ([key, value]) => [sanitizeEventString(key), sanitizeSensitiveEventField(key, value)]
148
149
  );
149
150
  return Object.fromEntries(entries);
150
151
  }
151
152
  return payload;
152
153
  }
154
+ function sanitizeSensitiveEventField(key, value) {
155
+ if (key === "mcpServers") {
156
+ return sanitizeSessionMcpServerList(value);
157
+ }
158
+ if (key === "mcpCredentialUpdates") {
159
+ return sanitizeMcpCredentialUpdateList(value);
160
+ }
161
+ return sanitizeEventPayload(value);
162
+ }
163
+ function sanitizeSessionMcpServerList(value) {
164
+ if (!Array.isArray(value)) {
165
+ return sanitizeEventPayload(value);
166
+ }
167
+ return value.map((item) => {
168
+ if (!isPlainObject(item)) {
169
+ return sanitizeEventPayload(item);
170
+ }
171
+ const { headers, headersEncrypted, ...rest } = item;
172
+ const cleaned = sanitizeEventPayload(rest);
173
+ const headerNames = safeHeaderNames(headers) ?? safeHeaderNames(headersEncrypted);
174
+ if (headerNames) {
175
+ cleaned.headerNames = headerNames;
176
+ }
177
+ return cleaned;
178
+ });
179
+ }
180
+ function sanitizeMcpCredentialUpdateList(value) {
181
+ if (!Array.isArray(value)) {
182
+ return sanitizeEventPayload(value);
183
+ }
184
+ return value.map((item) => {
185
+ if (!isPlainObject(item)) {
186
+ return sanitizeEventPayload(item);
187
+ }
188
+ const { headers, headersEncrypted, ...rest } = item;
189
+ const cleaned = sanitizeEventPayload(rest);
190
+ const headerNames = safeHeaderNames(headers) ?? safeHeaderNames(headersEncrypted);
191
+ if (headerNames) {
192
+ cleaned.headerNames = headerNames;
193
+ }
194
+ return cleaned;
195
+ });
196
+ }
197
+ function safeHeaderNames(value) {
198
+ if (!isPlainObject(value)) {
199
+ return null;
200
+ }
201
+ return Object.keys(value).map(sanitizeEventString).sort();
202
+ }
203
+ function isPlainObject(value) {
204
+ return Boolean(value && typeof value === "object" && !Array.isArray(value));
205
+ }
153
206
 
154
207
  // src/index.ts
155
208
  import { sql as sql2 } from "drizzle-orm";
@@ -388,6 +441,7 @@ var allWorkspacePermissions = [
388
441
  "api_keys:manage",
389
442
  "environments:manage",
390
443
  "environments:use",
444
+ "mcp_servers:attach",
391
445
  "goals:manage",
392
446
  "enrollments:read",
393
447
  "enrollments:manage"
@@ -2093,6 +2147,111 @@ function mapWorkspaceEnvironmentVariableMetadata(row) {
2093
2147
  updatedAt: row.updatedAt.toISOString()
2094
2148
  };
2095
2149
  }
2150
+ function mapSessionMcpServerMetadata(row) {
2151
+ return {
2152
+ id: row.serverId,
2153
+ name: row.name ?? null,
2154
+ url: row.url,
2155
+ headerNames: Object.keys(row.headersEncrypted ?? {}).sort(),
2156
+ credentialVersion: Number(row.credentialVersion)
2157
+ };
2158
+ }
2159
+ async function sessionMcpServerMetadataForSessions(db, workspaceId, sessionIds) {
2160
+ const grouped = /* @__PURE__ */ new Map();
2161
+ if (sessionIds.length === 0) {
2162
+ return grouped;
2163
+ }
2164
+ const rows = await db.select().from(sessionMcpServers).where(and(
2165
+ eq(sessionMcpServers.workspaceId, workspaceId),
2166
+ inArray(sessionMcpServers.sessionId, sessionIds)
2167
+ )).orderBy(asc(sessionMcpServers.createdAt), asc(sessionMcpServers.serverId));
2168
+ for (const row of rows) {
2169
+ const list = grouped.get(row.sessionId) ?? [];
2170
+ list.push(mapSessionMcpServerMetadata(row));
2171
+ grouped.set(row.sessionId, list);
2172
+ }
2173
+ return grouped;
2174
+ }
2175
+ async function insertSessionMcpServers(db, input) {
2176
+ if (input.servers.length === 0) {
2177
+ return [];
2178
+ }
2179
+ const rows = await db.insert(sessionMcpServers).values(input.servers.map((server) => ({
2180
+ accountId: input.accountId,
2181
+ workspaceId: input.workspaceId,
2182
+ sessionId: input.sessionId,
2183
+ serverId: server.id,
2184
+ name: server.name ?? null,
2185
+ url: server.url,
2186
+ allowedTools: server.allowedTools ?? null,
2187
+ timeoutMs: server.timeoutMs ?? null,
2188
+ cacheToolsList: server.cacheToolsList ?? false,
2189
+ headersEncrypted: server.headersEncrypted ?? {}
2190
+ }))).returning();
2191
+ return rows.map(mapSessionMcpServerMetadata);
2192
+ }
2193
+ async function createSessionMcpServers(db, input) {
2194
+ return await withRlsContext(
2195
+ db,
2196
+ { accountId: input.accountId, workspaceId: input.workspaceId },
2197
+ async (scopedDb) => await insertSessionMcpServers(scopedDb, input)
2198
+ );
2199
+ }
2200
+ async function listSessionMcpServerMetadata(db, workspaceId, sessionId) {
2201
+ return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
2202
+ const grouped = await sessionMcpServerMetadataForSessions(scopedDb, workspaceId, [sessionId]);
2203
+ return grouped.get(sessionId) ?? [];
2204
+ });
2205
+ }
2206
+ async function updateSessionMcpServerCredentials(db, input) {
2207
+ return await withWorkspaceRls(db, input.workspaceId, async (scopedDb) => await scopedDb.transaction(
2208
+ async (tx) => await updateSessionMcpServerCredentialsInTransaction(tx, input)
2209
+ ));
2210
+ }
2211
+ async function updateSessionMcpServerCredentialsInTransaction(tx, input) {
2212
+ const servers = [];
2213
+ const missingIds = [];
2214
+ for (const update of input.updates) {
2215
+ const [row] = await tx.update(sessionMcpServers).set({
2216
+ headersEncrypted: update.headersEncrypted,
2217
+ credentialVersion: sql`${sessionMcpServers.credentialVersion} + 1`,
2218
+ updatedAt: /* @__PURE__ */ new Date()
2219
+ }).where(and(
2220
+ eq(sessionMcpServers.workspaceId, input.workspaceId),
2221
+ eq(sessionMcpServers.sessionId, input.sessionId),
2222
+ eq(sessionMcpServers.serverId, update.id)
2223
+ )).returning();
2224
+ if (!row) {
2225
+ missingIds.push(update.id);
2226
+ } else {
2227
+ servers.push(mapSessionMcpServerMetadata(row));
2228
+ }
2229
+ }
2230
+ return { servers, missingIds };
2231
+ }
2232
+ async function listSessionMcpServersForRun(db, workspaceId, sessionId, encryptionKey) {
2233
+ return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
2234
+ const rows = await scopedDb.select().from(sessionMcpServers).where(and(
2235
+ eq(sessionMcpServers.workspaceId, workspaceId),
2236
+ eq(sessionMcpServers.sessionId, sessionId)
2237
+ )).orderBy(asc(sessionMcpServers.createdAt), asc(sessionMcpServers.serverId));
2238
+ return rows.map((row) => {
2239
+ let headers;
2240
+ try {
2241
+ headers = Object.fromEntries(Object.entries(row.headersEncrypted ?? {}).map(([name, stored]) => [name, decryptEnvironmentValue(encryptionKey, stored)]));
2242
+ } catch {
2243
+ throw new Error("session MCP server credential decryption failed");
2244
+ }
2245
+ return {
2246
+ ...mapSessionMcpServerMetadata(row),
2247
+ ...row.allowedTools ? { allowedTools: row.allowedTools } : {},
2248
+ ...row.timeoutMs ? { timeoutMs: row.timeoutMs } : {},
2249
+ ...row.cacheToolsList ? { cacheToolsList: row.cacheToolsList } : {},
2250
+ headers
2251
+ };
2252
+ });
2253
+ });
2254
+ }
2096
2255
  async function createSession(db, input) {
2097
2256
  const id = crypto.randomUUID();
2098
2257
  return await withRlsContext(db, { accountId: input.accountId, workspaceId: input.workspaceId }, async (scopedDb) => {
@@ -2110,6 +2269,7 @@ async function createSession(db, input) {
2110
2269
  sandboxGroupId: input.sandboxGroupId ?? id,
2111
2270
  environmentId: input.environmentId ?? null,
2112
2271
  firstPartyMcpPermissions: input.firstPartyMcpPermissions ?? null,
2272
+ instructions: input.instructions ?? null,
2113
2273
  parentSessionId: input.parentSessionId ?? null,
2114
2274
  createIdempotencyKey: input.createIdempotencyKey ?? null,
2115
2275
  status: "queued"
@@ -2117,7 +2277,13 @@ async function createSession(db, input) {
2117
2277
  if (!row) {
2118
2278
  throw new Error("Failed to create session");
2119
2279
  }
2120
- return mapSession(row);
2280
+ const mcpServers = await insertSessionMcpServers(scopedDb, {
2281
+ accountId: input.accountId,
2282
+ workspaceId: input.workspaceId,
2283
+ sessionId: row.id,
2284
+ servers: input.mcpServers ?? []
2285
+ });
2286
+ return mapSession(row, mcpServers);
2121
2287
  });
2122
2288
  }
2123
2289
  async function createSessionWithIdempotencyKey(db, input) {
@@ -2137,6 +2303,7 @@ async function createSessionWithIdempotencyKey(db, input) {
2137
2303
  sandboxGroupId: input.sandboxGroupId ?? id,
2138
2304
  environmentId: input.environmentId ?? null,
2139
2305
  firstPartyMcpPermissions: input.firstPartyMcpPermissions ?? null,
2306
+ instructions: input.instructions ?? null,
2140
2307
  parentSessionId: input.parentSessionId ?? null,
2141
2308
  createIdempotencyKey: input.createIdempotencyKey,
2142
2309
  status: "queued"
@@ -2145,7 +2312,13 @@ async function createSessionWithIdempotencyKey(db, input) {
2145
2312
  where: sql`${sessions.createIdempotencyKey} is not null`
2146
2313
  }).returning();
2147
2314
  if (inserted) {
2148
- return { session: mapSession(inserted), created: true };
2315
+ const mcpServers = await insertSessionMcpServers(scopedDb, {
2316
+ accountId: input.accountId,
2317
+ workspaceId: input.workspaceId,
2318
+ sessionId: inserted.id,
2319
+ servers: input.mcpServers ?? []
2320
+ });
2321
+ return { session: mapSession(inserted, mcpServers), created: true };
2149
2322
  }
2150
2323
  const [existing] = await scopedDb.select().from(sessions).where(and(
2151
2324
  eq(sessions.workspaceId, input.workspaceId),
@@ -2154,7 +2327,8 @@ async function createSessionWithIdempotencyKey(db, input) {
2154
2327
  if (!existing) {
2155
2328
  throw new Error("Failed to create session under idempotency key");
2156
2329
  }
2157
- return { session: mapSession(existing), created: false };
2330
+ const grouped = await sessionMcpServerMetadataForSessions(scopedDb, input.workspaceId, [existing.id]);
2331
+ return { session: mapSession(existing, grouped.get(existing.id) ?? []), created: false };
2158
2332
  });
2159
2333
  }
2160
2334
  async function getSessionByCreateIdempotencyKey(db, workspaceId, createIdempotencyKey) {
@@ -2163,13 +2337,17 @@ async function getSessionByCreateIdempotencyKey(db, workspaceId, createIdempoten
2163
2337
  eq(sessions.workspaceId, workspaceId),
2164
2338
  eq(sessions.createIdempotencyKey, createIdempotencyKey)
2165
2339
  )).limit(1);
2166
- return row ? mapSession(row) : null;
2340
+ if (!row) return null;
2341
+ const grouped = await sessionMcpServerMetadataForSessions(scopedDb, workspaceId, [row.id]);
2342
+ return mapSession(row, grouped.get(row.id) ?? []);
2167
2343
  });
2168
2344
  }
2169
2345
  async function getSession(db, workspaceId, sessionId) {
2170
2346
  return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
2171
2347
  const [row] = await scopedDb.select().from(sessions).where(and(eq(sessions.workspaceId, workspaceId), eq(sessions.id, sessionId))).limit(1);
2172
- return row ? mapSession(row) : null;
2348
+ if (!row) return null;
2349
+ const grouped = await sessionMcpServerMetadataForSessions(scopedDb, workspaceId, [row.id]);
2350
+ return mapSession(row, grouped.get(row.id) ?? []);
2173
2351
  });
2174
2352
  }
2175
2353
  async function getAnySessionInGroup(db, workspaceId, sandboxGroupId) {
@@ -2187,7 +2365,8 @@ async function listDistinctEnvironmentIdsInGroup(db, workspaceId, sandboxGroupId
2187
2365
  async function listSessions(db, workspaceId, limit = 50) {
2188
2366
  return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
2189
2367
  const rows = await scopedDb.select().from(sessions).where(eq(sessions.workspaceId, workspaceId)).orderBy(desc(sessions.createdAt), desc(sessions.id)).limit(limit);
2190
- return rows.map(mapSession);
2368
+ const grouped = await sessionMcpServerMetadataForSessions(scopedDb, workspaceId, rows.map((row) => row.id));
2369
+ return rows.map((row) => mapSession(row, grouped.get(row.id) ?? []));
2191
2370
  });
2192
2371
  }
2193
2372
  async function countActiveSessionsForWorkspace(db, workspaceId) {
@@ -2208,12 +2387,38 @@ async function requireSession(db, workspaceId, sessionId) {
2208
2387
  }
2209
2388
  return session;
2210
2389
  }
2211
- async function listSessionEvents(db, workspaceId, sessionId, after = 0, limit = 500) {
2390
+ var POSTGRES_INT_MAX = 2147483647;
2391
+ async function listSessionEvents(db, workspaceId, sessionId, afterOrOptions = 0, legacyLimit = 500) {
2392
+ const options = typeof afterOrOptions === "number" ? { after: afterOrOptions, limit: legacyLimit } : afterOrOptions;
2393
+ const after = normalizeEventSequence(options.after, 0);
2394
+ const limit = normalizeEventLimit(options.limit, 500);
2395
+ const hasBefore = options.before !== void 0 && Number.isFinite(options.before);
2396
+ const before = hasBefore ? Math.floor(options.before) : void 0;
2212
2397
  return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
2213
- const rows = await scopedDb.select().from(sessionEvents).where(and(eq(sessionEvents.workspaceId, workspaceId), eq(sessionEvents.sessionId, sessionId), gt(sessionEvents.sequence, after))).orderBy(asc(sessionEvents.sequence)).limit(limit);
2214
- return rows.map(mapEvent);
2398
+ const filters = [
2399
+ eq(sessionEvents.workspaceId, workspaceId),
2400
+ eq(sessionEvents.sessionId, sessionId),
2401
+ gt(sessionEvents.sequence, after)
2402
+ ];
2403
+ if (before !== void 0 && before <= POSTGRES_INT_MAX) {
2404
+ filters.push(lt(sessionEvents.sequence, before));
2405
+ }
2406
+ const rows = await scopedDb.select().from(sessionEvents).where(and(...filters)).orderBy(hasBefore ? desc(sessionEvents.sequence) : asc(sessionEvents.sequence)).limit(limit);
2407
+ return (hasBefore ? rows.reverse() : rows).map(mapEvent);
2215
2408
  });
2216
2409
  }
2410
+ function normalizeEventSequence(value, fallback) {
2411
+ if (value === void 0 || !Number.isFinite(value)) {
2412
+ return fallback;
2413
+ }
2414
+ return Math.floor(value);
2415
+ }
2416
+ function normalizeEventLimit(value, fallback) {
2417
+ if (value === void 0 || !Number.isFinite(value)) {
2418
+ return fallback;
2419
+ }
2420
+ return Math.max(0, Math.floor(value));
2421
+ }
2217
2422
  async function getSessionEvent(db, workspaceId, eventId) {
2218
2423
  return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
2219
2424
  const [row] = await scopedDb.select().from(sessionEvents).where(and(eq(sessionEvents.workspaceId, workspaceId), eq(sessionEvents.id, eventId))).limit(1);
@@ -2348,6 +2553,20 @@ async function applyContextCompaction(db, input) {
2348
2553
  eq(sessionHistoryItems.active, true),
2349
2554
  lt(sessionHistoryItems.position, input.boundaryPosition)
2350
2555
  ));
2556
+ if (input.replacementItems && input.replacementItems.length > 0) {
2557
+ await tx.insert(sessionHistoryItems).values(input.replacementItems.map((entry) => ({
2558
+ accountId: input.accountId,
2559
+ workspaceId: input.workspaceId,
2560
+ sessionId: input.sessionId,
2561
+ turnId: null,
2562
+ position: entry.position,
2563
+ item: sanitizeEventPayload(entry.item),
2564
+ active: true
2565
+ }))).onConflictDoUpdate({
2566
+ target: [sessionHistoryItems.workspaceId, sessionHistoryItems.sessionId, sessionHistoryItems.position],
2567
+ set: { active: true }
2568
+ });
2569
+ }
2351
2570
  await tx.insert(sessionHistoryItems).values({
2352
2571
  accountId: input.accountId,
2353
2572
  workspaceId: input.workspaceId,
@@ -2816,6 +3035,28 @@ async function commitWarmingToWarm(db, input) {
2816
3035
  }
2817
3036
  );
2818
3037
  }
3038
+ async function recordWarmingSandboxCreated(db, input) {
3039
+ return await withRlsContext(
3040
+ db,
3041
+ { accountId: input.accountId, workspaceId: input.workspaceId },
3042
+ async (scopedDb) => {
3043
+ const resumeStateJson = input.resumeState == null ? null : JSON.stringify(input.resumeState);
3044
+ const rows = await scopedDb.execute(sql`
3045
+ update sandbox_leases set
3046
+ instance_id = ${input.instanceId},
3047
+ resume_backend_id = ${input.resumeBackendId ?? null},
3048
+ resume_state = ${resumeStateJson}::jsonb,
3049
+ expires_at = now() + (${String(input.leaseTtlMs)} || ' milliseconds')::interval,
3050
+ updated_at = now()
3051
+ where workspace_id = ${input.workspaceId} and sandbox_group_id = ${input.sandboxGroupId}
3052
+ and liveness = 'warming' and lease_epoch = ${input.expectedEpoch}
3053
+ returning *
3054
+ `);
3055
+ if (rows.length === 0) return { recorded: false, lease: null };
3056
+ return { recorded: true, lease: mapLeaseRow(rows[0]) };
3057
+ }
3058
+ );
3059
+ }
2819
3060
  async function failWarmingToCold(db, input) {
2820
3061
  await withRlsContext(
2821
3062
  db,
@@ -2943,7 +3184,21 @@ async function reapStaleLeaseHolders(db, input) {
2943
3184
  resume_backend_id = null, resume_state = null,
2944
3185
  data_plane_url = null, terminal_data_plane_url = null, updated_at = now()
2945
3186
  where workspace_id = ${input.workspaceId}
2946
- and liveness = 'warming' and expires_at < now()
3187
+ and liveness = 'warming' and expires_at < now() and instance_id is null
3188
+ returning id
3189
+ `);
3190
+ const warmingDrain = await tx.execute(sql`
3191
+ update sandbox_leases set
3192
+ liveness = 'draining',
3193
+ refcount = 0,
3194
+ turn_holders = 0,
3195
+ viewer_holders = 0,
3196
+ data_plane_url = null,
3197
+ terminal_data_plane_url = null,
3198
+ expires_at = now() - interval '1 millisecond',
3199
+ updated_at = now()
3200
+ where workspace_id = ${input.workspaceId}
3201
+ and liveness = 'warming' and expires_at < now() and instance_id is not null
2947
3202
  returning id
2948
3203
  `);
2949
3204
  const drainable = await rawRows(tx, sql`
@@ -2953,7 +3208,7 @@ async function reapStaleLeaseHolders(db, input) {
2953
3208
  `);
2954
3209
  return {
2955
3210
  reapedViewers: reaped.length,
2956
- warmingReset: warmingReset.length,
3211
+ warmingReset: warmingReset.length + warmingDrain.length,
2957
3212
  drained: drainable.map((r) => ({
2958
3213
  workspaceId: input.workspaceId,
2959
3214
  sandboxGroupId: r.sandbox_group_id,
@@ -2988,6 +3243,19 @@ async function listMeterableWarmLeases(db) {
2988
3243
  backend: r.backend
2989
3244
  }));
2990
3245
  }
3246
+ async function listLiveModalSandboxLeaseAttributions(db) {
3247
+ const rows = await rawRows(db, sql`
3248
+ select lease_id, workspace_id, sandbox_group_id, instance_id, liveness
3249
+ from opengeni_private.list_live_modal_sandbox_leases()
3250
+ `);
3251
+ return rows.map((r) => ({
3252
+ leaseId: r.lease_id,
3253
+ workspaceId: r.workspace_id,
3254
+ sandboxGroupId: r.sandbox_group_id,
3255
+ instanceId: r.instance_id,
3256
+ liveness: r.liveness
3257
+ }));
3258
+ }
2991
3259
  async function reArmDrainingLease(db, input) {
2992
3260
  return await withRlsContext(
2993
3261
  db,
@@ -4482,7 +4750,9 @@ async function appendSessionEventsWithLockedSessionUpdate(db, workspaceId, sessi
4482
4750
  if (!sessionRow) {
4483
4751
  throw new Error(`Session not found: ${sessionId}`);
4484
4752
  }
4485
- const built = build(mapSession(sessionRow));
4753
+ const built = await build(mapSession(sessionRow), {
4754
+ updateSessionMcpServerCredentials: async (updates) => await updateSessionMcpServerCredentialsInTransaction(tx, { workspaceId, sessionId, updates })
4755
+ });
4486
4756
  if (built.events.length === 0) {
4487
4757
  return [];
4488
4758
  }
@@ -4519,7 +4789,7 @@ async function appendSessionEventsWithLockedSessionUpdate(db, workspaceId, sessi
4519
4789
  function sessionSubject(workspaceId, sessionId) {
4520
4790
  return `workspaces.${workspaceId}.sessions.${sessionId}.events`;
4521
4791
  }
4522
- function mapSession(row) {
4792
+ function mapSession(row, mcpServers = []) {
4523
4793
  return {
4524
4794
  id: row.id,
4525
4795
  accountId: row.accountId,
@@ -4528,6 +4798,7 @@ function mapSession(row) {
4528
4798
  initialMessage: row.initialMessage,
4529
4799
  title: row.title ?? null,
4530
4800
  titleSource: row.titleSource ?? null,
4801
+ instructions: row.instructions ?? null,
4531
4802
  resources: row.resources,
4532
4803
  tools: row.tools,
4533
4804
  metadata: row.metadata,
@@ -4542,6 +4813,7 @@ function mapSession(row) {
4542
4813
  activeEpoch: Number(row.activeEpoch),
4543
4814
  environmentId: row.environmentId,
4544
4815
  firstPartyMcpPermissions: row.firstPartyMcpPermissions ?? null,
4816
+ mcpServers,
4545
4817
  parentSessionId: row.parentSessionId ?? null,
4546
4818
  createIdempotencyKey: row.createIdempotencyKey ?? null,
4547
4819
  temporalWorkflowId: row.temporalWorkflowId,
@@ -4962,6 +5234,7 @@ export {
4962
5234
  createScheduledTaskRun,
4963
5235
  createSession,
4964
5236
  createSessionGoal,
5237
+ createSessionMcpServers,
4965
5238
  createSessionWithIdempotencyKey,
4966
5239
  createSocialConnection,
4967
5240
  createSocialPost,
@@ -5053,6 +5326,7 @@ export {
5053
5326
  listEnrollments,
5054
5327
  listGitHubInstallationIdsForWorkspace,
5055
5328
  listGitHubInstallationsForWorkspace,
5329
+ listLiveModalSandboxLeaseAttributions,
5056
5330
  listMeterableWarmLeases,
5057
5331
  listOpenPtySessions,
5058
5332
  listPackInstallations,
@@ -5062,6 +5336,8 @@ export {
5062
5336
  listScheduledTasks,
5063
5337
  listSessionEvents,
5064
5338
  listSessionIdsInGroup,
5339
+ listSessionMcpServerMetadata,
5340
+ listSessionMcpServersForRun,
5065
5341
  listSessionTurns,
5066
5342
  listSessions,
5067
5343
  listSocialConnections,
@@ -5099,6 +5375,7 @@ export {
5099
5375
  recordStreamAcknowledgment,
5100
5376
  recordStripeWebhookEvent,
5101
5377
  recordUsageEvent,
5378
+ recordWarmingSandboxCreated,
5102
5379
  registerDbBinding,
5103
5380
  registerWorkspacePack,
5104
5381
  releaseLeaseHolder,
@@ -5145,6 +5422,7 @@ export {
5145
5422
  updateScheduledTask,
5146
5423
  updateScheduledTaskRun,
5147
5424
  updateSessionGoal,
5425
+ updateSessionMcpServerCredentials,
5148
5426
  updateSessionTitle,
5149
5427
  updateWorkspace,
5150
5428
  updateWorkspaceEnvironment,