@opengeni/db 0.23.0 → 0.27.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 (35) hide show
  1. package/dist/{chunk-3UCHDMKG.js → chunk-EX7CDSGH.js} +196 -2
  2. package/dist/chunk-EX7CDSGH.js.map +1 -0
  3. package/dist/{chunk-L6ADMZHE.js → chunk-IHPCI4GV.js} +5 -1
  4. package/dist/chunk-IHPCI4GV.js.map +1 -0
  5. package/dist/connection-token-resolver.d.ts +24 -2
  6. package/dist/index.d.ts +68 -2
  7. package/dist/index.js +1457 -338
  8. package/dist/index.js.map +1 -1
  9. package/dist/preference-registry.d.ts +14 -0
  10. package/dist/provision-roles.js +1 -1
  11. package/dist/runtime-posture.d.ts +3 -3
  12. package/dist/schema.d.ts +262 -4
  13. package/dist/schema.js +5 -1
  14. package/dist/session-realtime-mirror.d.ts +22 -1
  15. package/dist/workspace-instruction-policies-schema.d.ts +449 -0
  16. package/dist/workspace-instruction-policies.d.ts +88 -8
  17. package/drizzle/0165_document_authority_foundation.sql +259 -0
  18. package/drizzle/0166_connection_disconnect_idempotency.sql +49 -0
  19. package/drizzle/0167_document_index_replay_authority.sql +61 -0
  20. package/drizzle/0168_workspace_instruction_policy_operation_receipts.sql +44 -0
  21. package/drizzle/0169_workspace_instruction_policy_onboarding_proposals.sql +202 -0
  22. package/package.json +3 -3
  23. package/src/connection-token-resolver.ts +79 -16
  24. package/src/index.ts +419 -23
  25. package/src/preference-registry.ts +103 -0
  26. package/src/runtime-posture.ts +4 -0
  27. package/src/schema.ts +86 -0
  28. package/src/session-control.ts +48 -1
  29. package/src/session-queue-commands.ts +45 -11
  30. package/src/session-realtime-mirror.ts +117 -1
  31. package/src/session-realtime.ts +49 -1
  32. package/src/workspace-instruction-policies-schema.ts +116 -0
  33. package/src/workspace-instruction-policies.ts +819 -25
  34. package/dist/chunk-3UCHDMKG.js.map +0 -1
  35. package/dist/chunk-L6ADMZHE.js.map +0 -1
package/dist/index.js CHANGED
@@ -11,6 +11,7 @@ import {
11
11
  codexRotationSettings,
12
12
  codexSubscriptionCredentials,
13
13
  composerDrafts,
14
+ connectionDisconnectOperations,
14
15
  connections,
15
16
  connectorActionPolicies,
16
17
  connectorActionRequests,
@@ -103,7 +104,9 @@ import {
103
104
  workspaceInferenceControls,
104
105
  workspaceInstructionPolicyActivationEvents,
105
106
  workspaceInstructionPolicyHeads,
107
+ workspaceInstructionPolicyOnboardingProposals,
106
108
  workspaceInstructionPolicyRevisions,
109
+ workspaceInstructionPolicySnapshots,
107
110
  workspaceMemberships,
108
111
  workspaceModelPolicies,
109
112
  workspacePacks,
@@ -111,7 +114,7 @@ import {
111
114
  workspaceVariableSetVariables,
112
115
  workspaceVariableSets,
113
116
  workspaces
114
- } from "./chunk-3UCHDMKG.js";
117
+ } from "./chunk-EX7CDSGH.js";
115
118
  import {
116
119
  migrate,
117
120
  runMigrations
@@ -131,7 +134,7 @@ import {
131
134
  inspectRuntimeDatabasePosture,
132
135
  provisionRoles,
133
136
  runtimeDatabaseReadyCheck
134
- } from "./chunk-L6ADMZHE.js";
137
+ } from "./chunk-IHPCI4GV.js";
135
138
  import "./chunk-PZ5AY32C.js";
136
139
 
137
140
  // src/index.ts
@@ -144,7 +147,8 @@ import {
144
147
  canonicalModalCheckpointProviderBinding,
145
148
  decodeNativeSnapshotRef,
146
149
  parseWorkspaceArchiveDescriptor,
147
- stableJson as stableJson3
150
+ stableJson as stableJson3,
151
+ MODEL_ATTACHMENT_REFS_FIELD
148
152
  } from "@opengeni/contracts";
149
153
  import {
150
154
  approvalIdentifier,
@@ -191,17 +195,17 @@ import {
191
195
  desc as desc8,
192
196
  eq as eq17,
193
197
  getTableColumns,
194
- gt as gt4,
198
+ gt as gt5,
195
199
  gte as gte2,
196
200
  inArray as inArray11,
197
201
  isNotNull,
198
202
  ilike,
199
- isNull as isNull5,
203
+ isNull as isNull6,
200
204
  lt as lt4,
201
205
  lte as lte2,
202
206
  ne,
203
207
  notInArray,
204
- or as or4,
208
+ or as or6,
205
209
  sql as sql14
206
210
  } from "drizzle-orm";
207
211
 
@@ -1162,13 +1166,199 @@ async function closePendingSessionToolCallsInTransaction(tx, input) {
1162
1166
  }
1163
1167
 
1164
1168
  // src/session-control.ts
1165
- import { createHash } from "crypto";
1169
+ import { createHash as createHash2 } from "crypto";
1166
1170
  import {
1167
1171
  boundWorkspaceControlEvent,
1168
1172
  McpPersonalConnectionDelegations,
1169
1173
  workspaceControlUtf8Bytes
1170
1174
  } from "@opengeni/contracts";
1171
- import { and as and4, eq as eq4, inArray, sql as sql2 } from "drizzle-orm";
1175
+ import { and as and5, eq as eq5, inArray, sql as sql3 } from "drizzle-orm";
1176
+
1177
+ // src/session-realtime-mirror.ts
1178
+ import { createHash } from "crypto";
1179
+ import { and as and4, desc, eq as eq4, gt, sql as sql2 } from "drizzle-orm";
1180
+ var SESSION_REALTIME_MIRROR_MAX_TEXT_BYTES = 131072;
1181
+ var SESSION_REALTIME_MIRROR_MAX_PAYLOAD_BYTES = 131072;
1182
+ var TRUNCATION_MARKER = "\n\u2026realtime context truncated\u2026";
1183
+ function deterministicUuid(seed) {
1184
+ const bytes = createHash("sha256").update(seed, "utf8").digest().subarray(0, 16);
1185
+ bytes[6] = (bytes[6] ?? 0) & 15 | 80;
1186
+ bytes[8] = (bytes[8] ?? 0) & 63 | 128;
1187
+ const hex = bytes.toString("hex");
1188
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
1189
+ }
1190
+ function takeUtf8Head(value, maximumBytes) {
1191
+ const bytes = Buffer.from(value, "utf8");
1192
+ if (bytes.length <= maximumBytes) return value;
1193
+ let end = maximumBytes;
1194
+ while (end > 0 && (bytes[end] & 192) === 128) end -= 1;
1195
+ return bytes.subarray(0, end).toString("utf8");
1196
+ }
1197
+ function boundedText(value) {
1198
+ if (Buffer.byteLength(value, "utf8") <= SESSION_REALTIME_MIRROR_MAX_TEXT_BYTES) return value;
1199
+ const markerBytes = Buffer.byteLength(TRUNCATION_MARKER, "utf8");
1200
+ return `${takeUtf8Head(value, SESSION_REALTIME_MIRROR_MAX_TEXT_BYTES - markerBytes)}${TRUNCATION_MARKER}`;
1201
+ }
1202
+ function boundedPayload(value) {
1203
+ const payload = sanitizeEventPayload(value);
1204
+ if (Buffer.byteLength(JSON.stringify(payload), "utf8") > SESSION_REALTIME_MIRROR_MAX_PAYLOAD_BYTES) {
1205
+ throw new Error("Realtime mirror payload exceeds the durable ledger limit");
1206
+ }
1207
+ return payload;
1208
+ }
1209
+ async function mirrorSessionRealtimeContextInTransaction(db, input) {
1210
+ const now = input.now ?? /* @__PURE__ */ new Date();
1211
+ const modes = await db.select().from(sessionRealtimeModes).where(
1212
+ and4(
1213
+ eq4(sessionRealtimeModes.accountId, input.accountId),
1214
+ eq4(sessionRealtimeModes.workspaceId, input.workspaceId),
1215
+ eq4(sessionRealtimeModes.sessionId, input.sessionId),
1216
+ eq4(sessionRealtimeModes.state, "active"),
1217
+ gt(sessionRealtimeModes.leaseExpiresAt, now)
1218
+ )
1219
+ ).orderBy(desc(sessionRealtimeModes.startedAt)).for("update").limit(2);
1220
+ if (modes.length === 0) return null;
1221
+ if (modes.length !== 1) {
1222
+ throw new Error(`Session ${input.sessionId} has multiple active realtime modes`);
1223
+ }
1224
+ const mode = modes[0];
1225
+ const operationId = deterministicUuid(
1226
+ `opengeni:session-realtime-mirror:${mode.id}:${input.sourceKind}:${input.sourceId}`
1227
+ );
1228
+ const [existing] = await db.select().from(sessionRealtimeEntries).where(
1229
+ and4(
1230
+ eq4(sessionRealtimeEntries.realtimeId, mode.id),
1231
+ eq4(sessionRealtimeEntries.operationId, operationId)
1232
+ )
1233
+ ).limit(1);
1234
+ if (existing) return { entry: existing, replay: true };
1235
+ const [sequenceRow] = await db.select({ next: sql2`coalesce(max(${sessionRealtimeEntries.sequence}), 0) + 1` }).from(sessionRealtimeEntries).where(eq4(sessionRealtimeEntries.realtimeId, mode.id));
1236
+ const payload = boundedPayload({
1237
+ ...input.payload ?? {},
1238
+ source: input.sourceKind,
1239
+ sourceId: input.sourceId,
1240
+ channel: input.channel,
1241
+ ...input.turnId ? { sourceTurnId: input.turnId } : {}
1242
+ });
1243
+ const [entry] = await db.insert(sessionRealtimeEntries).values({
1244
+ accountId: input.accountId,
1245
+ workspaceId: input.workspaceId,
1246
+ sessionId: input.sessionId,
1247
+ realtimeId: mode.id,
1248
+ operationId,
1249
+ connectionEpoch: mode.connectionEpoch,
1250
+ sequence: Number(sequenceRow?.next ?? 1),
1251
+ direction: "provider_out",
1252
+ kind: "session_update",
1253
+ text: boundedText(input.text),
1254
+ payload,
1255
+ createdAt: now,
1256
+ updatedAt: now
1257
+ }).returning();
1258
+ if (!entry) throw new Error("Failed to append realtime session context");
1259
+ return { entry, replay: false };
1260
+ }
1261
+ function renderRealtimeHumanInputContext(input) {
1262
+ return [
1263
+ "<session_user_message>",
1264
+ ` <status>${input.routing}</status>`,
1265
+ ` <delivery>${input.delivery}</delivery>`,
1266
+ ` <text>${escapeXmlText(input.text)}</text>`,
1267
+ " <instruction>Already routed by OpenGeni; do not delegate this message again.</instruction>",
1268
+ "</session_user_message>"
1269
+ ].join("\n");
1270
+ }
1271
+ function renderRealtimeHumanInputRequestContext(input) {
1272
+ const lines = ["<session_human_input_request>", " <status>waiting_for_user</status>"];
1273
+ for (const request of input.requests) {
1274
+ lines.push(
1275
+ " <request>",
1276
+ ` <id>${escapeXmlText(request.id)}</id>`,
1277
+ ` <allow_skip>${String(request.allowSkip)}</allow_skip>`,
1278
+ ` <expires_at>${escapeXmlText(renderExpiry(request.expiresAt))}</expires_at>`
1279
+ );
1280
+ for (const question of request.questions) {
1281
+ lines.push(
1282
+ " <question>",
1283
+ ` <id>${escapeXmlText(question.id)}</id>`,
1284
+ ` <kind>${escapeXmlText(question.kind)}</kind>`,
1285
+ ` <required>${String(question.required)}</required>`
1286
+ );
1287
+ if (question.label) lines.push(` <label>${escapeXmlText(question.label)}</label>`);
1288
+ lines.push(` <prompt>${escapeXmlText(question.prompt)}</prompt>`);
1289
+ if (question.helpText) {
1290
+ lines.push(` <help_text>${escapeXmlText(question.helpText)}</help_text>`);
1291
+ }
1292
+ if (question.options.length > 0) {
1293
+ lines.push(" <options>");
1294
+ for (const option of question.options) {
1295
+ lines.push(
1296
+ " <option>",
1297
+ ` <id>${escapeXmlText(option.id)}</id>`,
1298
+ ` <label>${escapeXmlText(option.label)}</label>`
1299
+ );
1300
+ if (option.description) {
1301
+ lines.push(` <description>${escapeXmlText(option.description)}</description>`);
1302
+ }
1303
+ lines.push(" </option>");
1304
+ }
1305
+ lines.push(" </options>");
1306
+ }
1307
+ lines.push(
1308
+ ` <allow_other>${String(question.allowOther)}</allow_other>`,
1309
+ " </question>"
1310
+ );
1311
+ }
1312
+ lines.push(" </request>");
1313
+ }
1314
+ lines.push(
1315
+ " <instruction>The current work is waiting for the user's input. Ask the questions naturally, one at a time when useful, without changing their meaning or answering for the user. The user may answer in the visible form or answer conversationally here. If the user answers here, delegate exactly once with a complete message containing the relevant question and the user's answer. If the user changes direction instead, delegate that new direction normally. Do not claim the work resumed until a later session update confirms it.</instruction>",
1316
+ "</session_human_input_request>"
1317
+ );
1318
+ return lines.join("\n");
1319
+ }
1320
+ function renderRealtimeHumanInputResponseContext(input) {
1321
+ const lines = [
1322
+ "<session_human_input_response>",
1323
+ ` <request_id>${escapeXmlText(input.requestId)}</request_id>`,
1324
+ ` <outcome>${escapeXmlText(input.response.outcome)}</outcome>`
1325
+ ];
1326
+ if (input.response.outcome === "answered") {
1327
+ const questions = new Map(input.questions.map((question) => [question.id, question]));
1328
+ lines.push(" <answers>");
1329
+ for (const answer of input.response.answers) {
1330
+ const question = questions.get(answer.questionId);
1331
+ const optionLabels = new Map(
1332
+ question?.options.map((option) => [option.id, option.label]) ?? []
1333
+ );
1334
+ lines.push(
1335
+ " <answer>",
1336
+ ` <question_id>${escapeXmlText(answer.questionId)}</question_id>`
1337
+ );
1338
+ if (question) lines.push(` <question>${escapeXmlText(question.prompt)}</question>`);
1339
+ for (const value of answer.values) {
1340
+ lines.push(` <value>${escapeXmlText(optionLabels.get(value) ?? value)}</value>`);
1341
+ }
1342
+ if (answer.other) lines.push(` <other>${escapeXmlText(answer.other)}</other>`);
1343
+ lines.push(" </answer>");
1344
+ }
1345
+ lines.push(" </answers>");
1346
+ }
1347
+ lines.push(
1348
+ input.response.outcome === "answered" || input.response.outcome === "skipped" ? " <instruction>This structured response was accepted through the session UI and the same work can resume. Treat it as authoritative user context, do not delegate it again, and acknowledge briefly only if useful.</instruction>" : " <instruction>This pending question is no longer active. Do not ask it again unless the user raises it.</instruction>",
1349
+ "</session_human_input_response>"
1350
+ );
1351
+ return lines.join("\n");
1352
+ }
1353
+ function renderExpiry(value) {
1354
+ if (value === null || value === void 0) return "none";
1355
+ return value instanceof Date ? value.toISOString() : value;
1356
+ }
1357
+ function escapeXmlText(value) {
1358
+ return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
1359
+ }
1360
+
1361
+ // src/session-control.ts
1172
1362
  var SESSION_ANCESTRY_LIMIT = 1e4;
1173
1363
  var NO_SETTLEMENT_ATTEMPTS = {
1174
1364
  attemptCount: 0,
@@ -1239,7 +1429,7 @@ async function assertAgentCommandAuthorityInTransaction(db, input) {
1239
1429
  if (!lockedSessions.some((row) => row.id === input.targetSessionId)) {
1240
1430
  throw new SessionControlInvariantError(`Target session not found: ${input.targetSessionId}`);
1241
1431
  }
1242
- const rows = await db.execute(sql2`
1432
+ const rows = await db.execute(sql3`
1243
1433
  select
1244
1434
  attempt.id as "attemptId",
1245
1435
  attempt.state as "attemptState",
@@ -1281,7 +1471,7 @@ async function assertAgentCommandAuthorityInTransaction(db, input) {
1281
1471
  throw new AgentCommandAuthorityError("SELF_STEER", "An agent cannot steer its own session");
1282
1472
  }
1283
1473
  if (input.action !== "pause") return;
1284
- const ancestry = await db.execute(sql2`
1474
+ const ancestry = await db.execute(sql3`
1285
1475
  with recursive caller_ancestry(id, parent_id, depth, path, cycle) as (
1286
1476
  select session.id, session.parent_session_id, 0, array[session.id], false
1287
1477
  from ${sessions} session
@@ -1333,17 +1523,17 @@ function canonicalize(value) {
1333
1523
  return value;
1334
1524
  }
1335
1525
  function canonicalSessionCommandHash(value) {
1336
- return createHash("sha256").update(JSON.stringify(canonicalize(value))).digest("hex");
1526
+ return createHash2("sha256").update(JSON.stringify(canonicalize(value))).digest("hex");
1337
1527
  }
1338
1528
  function controlEtag(value) {
1339
1529
  return `sc1:${canonicalSessionCommandHash(value)}`;
1340
1530
  }
1341
1531
  function lockClause(mode) {
1342
- if (mode === "none") return sql2.empty();
1343
- return mode === "update" ? sql2.raw("for update") : sql2.raw("for share");
1532
+ if (mode === "none") return sql3.empty();
1533
+ return mode === "update" ? sql3.raw("for update") : sql3.raw("for share");
1344
1534
  }
1345
1535
  async function lockWorkspaceInferenceControl(db, workspaceId, mode) {
1346
- const rows = await db.execute(sql2`
1536
+ const rows = await db.execute(sql3`
1347
1537
  select
1348
1538
  workspace_id as "workspaceId",
1349
1539
  account_id as "accountId",
@@ -1370,27 +1560,27 @@ async function lockSessionEventWriteRows(db, input) {
1370
1560
  const control = controlLock === "share" || controlLock === "update" ? await lockWorkspaceInferenceControl(db, input.workspaceId, controlLock) : null;
1371
1561
  let workspace = null;
1372
1562
  if ((input.workspaceLock ?? "key_share") === "key_share") {
1373
- const [lockedWorkspace] = await db.select().from(workspaces).where(eq4(workspaces.id, input.workspaceId)).for("key share").limit(1);
1563
+ const [lockedWorkspace] = await db.select().from(workspaces).where(eq5(workspaces.id, input.workspaceId)).for("key share").limit(1);
1374
1564
  workspace = lockedWorkspace ?? null;
1375
1565
  }
1376
1566
  const sessionIds = [...new Set(input.sessionIds ?? [])].sort();
1377
1567
  const sessions2 = sessionIds.length > 0 ? await db.select().from(sessions).where(
1378
- and4(
1379
- eq4(sessions.workspaceId, input.workspaceId),
1568
+ and5(
1569
+ eq5(sessions.workspaceId, input.workspaceId),
1380
1570
  inArray(sessions.id, sessionIds)
1381
1571
  )
1382
1572
  ).orderBy(sessions.id).for("update") : [];
1383
1573
  const turnIds = [...new Set(input.turnIds ?? [])].sort();
1384
1574
  const turns = turnIds.length > 0 ? await db.select().from(sessionTurns).where(
1385
- and4(
1386
- eq4(sessionTurns.workspaceId, input.workspaceId),
1575
+ and5(
1576
+ eq5(sessionTurns.workspaceId, input.workspaceId),
1387
1577
  inArray(sessionTurns.id, turnIds)
1388
1578
  )
1389
1579
  ).orderBy(sessionTurns.id).for("update") : [];
1390
1580
  const attemptIds = [...new Set(input.attemptIds ?? [])].sort();
1391
1581
  const attempts = attemptIds.length > 0 ? await db.select().from(sessionTurnAttempts).where(
1392
- and4(
1393
- eq4(sessionTurnAttempts.workspaceId, input.workspaceId),
1582
+ and5(
1583
+ eq5(sessionTurnAttempts.workspaceId, input.workspaceId),
1394
1584
  inArray(sessionTurnAttempts.id, attemptIds)
1395
1585
  )
1396
1586
  ).orderBy(sessionTurnAttempts.id).for("update") : [];
@@ -1403,9 +1593,9 @@ async function registerSessionTurnAttemptClaim(db, input) {
1403
1593
  }).onConflictDoNothing({ target: sessionTurnAttempts.id }).returning();
1404
1594
  if (inserted) return inserted;
1405
1595
  const [existing] = await db.select().from(sessionTurnAttempts).where(
1406
- and4(
1407
- eq4(sessionTurnAttempts.workspaceId, input.workspaceId),
1408
- eq4(sessionTurnAttempts.id, input.id)
1596
+ and5(
1597
+ eq5(sessionTurnAttempts.workspaceId, input.workspaceId),
1598
+ eq5(sessionTurnAttempts.id, input.id)
1409
1599
  )
1410
1600
  ).for("update").limit(1);
1411
1601
  if (!existing || existing.accountId !== input.accountId || existing.sessionId !== input.sessionId || existing.turnId !== input.turnId || existing.executionGeneration !== input.executionGeneration || existing.temporalWorkflowId !== input.temporalWorkflowId || existing.temporalWorkflowRunId !== input.temporalWorkflowRunId || existing.temporalActivityId !== input.temporalActivityId || JSON.stringify(existing.connectorActionPolicies) !== JSON.stringify(input.connectorActionPolicies) || existing.state === "closed") {
@@ -1417,9 +1607,9 @@ async function registerSessionTurnAttemptClaim(db, input) {
1417
1607
  }
1418
1608
  async function closeSessionTurnAttemptInTransaction(db, input) {
1419
1609
  const [attempt] = await db.select().from(sessionTurnAttempts).where(
1420
- and4(
1421
- eq4(sessionTurnAttempts.workspaceId, input.workspaceId),
1422
- eq4(sessionTurnAttempts.id, input.id)
1610
+ and5(
1611
+ eq5(sessionTurnAttempts.workspaceId, input.workspaceId),
1612
+ eq5(sessionTurnAttempts.id, input.id)
1423
1613
  )
1424
1614
  ).for("update").limit(1);
1425
1615
  if (!attempt || attempt.accountId !== input.accountId || attempt.sessionId !== input.sessionId || attempt.turnId !== input.turnId || attempt.executionGeneration !== input.executionGeneration) {
@@ -1450,10 +1640,10 @@ async function closeSessionTurnAttemptInTransaction(db, input) {
1450
1640
  closedAt: now,
1451
1641
  updatedAt: now
1452
1642
  }).where(
1453
- and4(
1454
- eq4(sessionTurnAttempts.workspaceId, input.workspaceId),
1455
- eq4(sessionTurnAttempts.id, input.id),
1456
- sql2`${sessionTurnAttempts.state} in ('claimed', 'running')`
1643
+ and5(
1644
+ eq5(sessionTurnAttempts.workspaceId, input.workspaceId),
1645
+ eq5(sessionTurnAttempts.id, input.id),
1646
+ sql3`${sessionTurnAttempts.state} in ('claimed', 'running')`
1457
1647
  )
1458
1648
  ).returning({ id: sessionTurnAttempts.id });
1459
1649
  if (!closed) {
@@ -1465,14 +1655,14 @@ function targetValues(sessionIds) {
1465
1655
  if (sessionIds.length === 0) {
1466
1656
  throw new SessionControlInvariantError("At least one target session is required");
1467
1657
  }
1468
- return sql2.join(
1469
- sessionIds.map((id) => sql2`(${id}::uuid)`),
1470
- sql2`, `
1658
+ return sql3.join(
1659
+ sessionIds.map((id) => sql3`(${id}::uuid)`),
1660
+ sql3`, `
1471
1661
  );
1472
1662
  }
1473
1663
  var TARGET_PATH_PROJECTION_LIMIT = 128;
1474
1664
  async function loadTargetAncestryRows(db, workspaceId, sessionIds) {
1475
- return await db.execute(sql2`
1665
+ return await db.execute(sql3`
1476
1666
  with recursive targets(id) as (values ${targetValues(sessionIds)}),
1477
1667
  ancestry as (
1478
1668
  select
@@ -1535,7 +1725,7 @@ async function loadTargetAncestryRows(db, workspaceId, sessionIds) {
1535
1725
  `);
1536
1726
  }
1537
1727
  async function loadAncestryNodes(db, workspaceId, sessionIds) {
1538
- const rows = await db.execute(sql2`
1728
+ const rows = await db.execute(sql3`
1539
1729
  with recursive targets(id) as (values ${targetValues(sessionIds)}),
1540
1730
  ancestry_ids(id) as (
1541
1731
  select session.id
@@ -1728,7 +1918,7 @@ function projectEffectiveControl(workspace, targetId, rows, settlementAttempts)
1728
1918
  };
1729
1919
  }
1730
1920
  async function settlementAttemptCounts(db, workspaceId, sessionIds) {
1731
- const rows = await db.execute(sql2`
1921
+ const rows = await db.execute(sql3`
1732
1922
  with recursive targets(id) as (values ${targetValues(sessionIds)}),
1733
1923
  interruptions as (
1734
1924
  select
@@ -1875,7 +2065,7 @@ async function evaluateSessionDiscoveryControls(db, workspaceId, sessionIds) {
1875
2065
  if (workspace.workspaceState === "paused" && workspacePauseRevision === null) {
1876
2066
  throw new SessionControlInvariantError("Paused workspace is missing its pause revision");
1877
2067
  }
1878
- const rows = await db.execute(sql2`
2068
+ const rows = await db.execute(sql3`
1879
2069
  with recursive targets(id) as (values ${targetValues(uniqueIds)}),
1880
2070
  ancestry as (
1881
2071
  select
@@ -2042,22 +2232,22 @@ async function evaluateSessionControl(db, workspaceId, sessionId, options = {})
2042
2232
  async function findCommandReceipt(db, input) {
2043
2233
  const actorSubjectId = input.actor.type === "agent_attempt" ? null : input.actor.subjectId;
2044
2234
  const actorAttemptId = input.actor.type === "agent_attempt" ? input.actor.attemptId : null;
2045
- const identity = input.identityScope === "goal_operation" ? and4(
2046
- eq4(sessionCommandReceipts.workspaceId, input.workspaceId),
2047
- eq4(sessionCommandReceipts.actorType, "agent_attempt"),
2048
- eq4(sessionCommandReceipts.action, input.action),
2049
- eq4(sessionCommandReceipts.targetSessionId, input.targetSessionId),
2050
- sql2`${sessionCommandReceipts.targetTurnId} is null`,
2051
- eq4(sessionCommandReceipts.operationKey, input.operationKey)
2052
- ) : and4(
2053
- eq4(sessionCommandReceipts.workspaceId, input.workspaceId),
2054
- eq4(sessionCommandReceipts.actorType, input.actor.type),
2055
- sql2`${sessionCommandReceipts.actorSubjectId} is not distinct from ${actorSubjectId}`,
2056
- sql2`${sessionCommandReceipts.actorAttemptId} is not distinct from ${actorAttemptId}::uuid`,
2057
- eq4(sessionCommandReceipts.action, input.action),
2058
- sql2`${sessionCommandReceipts.targetSessionId} is not distinct from ${input.targetSessionId}::uuid`,
2059
- sql2`${sessionCommandReceipts.targetTurnId} is not distinct from ${input.targetTurnId}::uuid`,
2060
- eq4(sessionCommandReceipts.operationKey, input.operationKey)
2235
+ const identity = input.identityScope === "goal_operation" ? and5(
2236
+ eq5(sessionCommandReceipts.workspaceId, input.workspaceId),
2237
+ eq5(sessionCommandReceipts.actorType, "agent_attempt"),
2238
+ eq5(sessionCommandReceipts.action, input.action),
2239
+ eq5(sessionCommandReceipts.targetSessionId, input.targetSessionId),
2240
+ sql3`${sessionCommandReceipts.targetTurnId} is null`,
2241
+ eq5(sessionCommandReceipts.operationKey, input.operationKey)
2242
+ ) : and5(
2243
+ eq5(sessionCommandReceipts.workspaceId, input.workspaceId),
2244
+ eq5(sessionCommandReceipts.actorType, input.actor.type),
2245
+ sql3`${sessionCommandReceipts.actorSubjectId} is not distinct from ${actorSubjectId}`,
2246
+ sql3`${sessionCommandReceipts.actorAttemptId} is not distinct from ${actorAttemptId}::uuid`,
2247
+ eq5(sessionCommandReceipts.action, input.action),
2248
+ sql3`${sessionCommandReceipts.targetSessionId} is not distinct from ${input.targetSessionId}::uuid`,
2249
+ sql3`${sessionCommandReceipts.targetTurnId} is not distinct from ${input.targetTurnId}::uuid`,
2250
+ eq5(sessionCommandReceipts.operationKey, input.operationKey)
2061
2251
  );
2062
2252
  const rows = await db.select().from(sessionCommandReceipts).where(identity).for("update");
2063
2253
  return rows[0] ?? null;
@@ -2108,9 +2298,9 @@ function nextRevision(workspace) {
2108
2298
  }
2109
2299
  async function advanceWorkspaceRevision(db, workspaceId, revision) {
2110
2300
  const rows = await db.update(workspaceInferenceControls).set({ revision, updatedAt: /* @__PURE__ */ new Date() }).where(
2111
- and4(
2112
- eq4(workspaceInferenceControls.workspaceId, workspaceId),
2113
- eq4(workspaceInferenceControls.revision, revision - 1)
2301
+ and5(
2302
+ eq5(workspaceInferenceControls.workspaceId, workspaceId),
2303
+ eq5(workspaceInferenceControls.revision, revision - 1)
2114
2304
  )
2115
2305
  ).returning({ workspaceId: workspaceInferenceControls.workspaceId });
2116
2306
  if (rows.length !== 1) {
@@ -2120,7 +2310,7 @@ async function advanceWorkspaceRevision(db, workspaceId, revision) {
2120
2310
  }
2121
2311
  }
2122
2312
  async function registerContinuableWakes(db, input) {
2123
- const rows = await db.execute(sql2`
2313
+ const rows = await db.execute(sql3`
2124
2314
  with eligible as (
2125
2315
  select *
2126
2316
  from opengeni_private.list_continuable_sessions(
@@ -2162,7 +2352,7 @@ async function registerWorkspaceWakes(db, input) {
2162
2352
  });
2163
2353
  }
2164
2354
  async function registerInterruptionWakes(db, input) {
2165
- const rows = await db.execute(sql2`
2355
+ const rows = await db.execute(sql3`
2166
2356
  with eligible as (
2167
2357
  select distinct
2168
2358
  session.id as session_id,
@@ -2198,11 +2388,11 @@ async function registerInterruptionWakes(db, input) {
2198
2388
  }
2199
2389
  async function registerCancellationWakes(db, input) {
2200
2390
  if (input.sessionIds.length === 0) return 0;
2201
- const sessionIds = sql2.join(
2202
- input.sessionIds.map((id) => sql2`${id}::uuid`),
2203
- sql2`, `
2391
+ const sessionIds = sql3.join(
2392
+ input.sessionIds.map((id) => sql3`${id}::uuid`),
2393
+ sql3`, `
2204
2394
  );
2205
- const rows = await db.execute(sql2`
2395
+ const rows = await db.execute(sql3`
2206
2396
  with eligible as (
2207
2397
  select
2208
2398
  session.id as session_id,
@@ -2244,7 +2434,7 @@ async function registerSessionWorkflowWakeInTransaction(db, input) {
2244
2434
  target: sessionWorkflowWakeOutbox.sessionId,
2245
2435
  set: {
2246
2436
  temporalWorkflowId: input.temporalWorkflowId,
2247
- wakeRevision: sql2`${sessionWorkflowWakeOutbox.wakeRevision} + 1`,
2437
+ wakeRevision: sql3`${sessionWorkflowWakeOutbox.wakeRevision} + 1`,
2248
2438
  reason: input.reason,
2249
2439
  attempts: 0,
2250
2440
  nextAttemptAt: /* @__PURE__ */ new Date(),
@@ -2259,9 +2449,9 @@ async function registerSessionWorkflowWakeInTransaction(db, input) {
2259
2449
  }
2260
2450
  async function registerInternalUpdateWakeInTransaction(db, input) {
2261
2451
  const [existing] = await db.select().from(sessionWorkflowWakeOutbox).where(
2262
- and4(
2263
- eq4(sessionWorkflowWakeOutbox.workspaceId, input.workspaceId),
2264
- eq4(sessionWorkflowWakeOutbox.sessionId, input.sessionId)
2452
+ and5(
2453
+ eq5(sessionWorkflowWakeOutbox.workspaceId, input.workspaceId),
2454
+ eq5(sessionWorkflowWakeOutbox.sessionId, input.sessionId)
2265
2455
  )
2266
2456
  ).for("update").limit(1);
2267
2457
  if (existing && existing.wakeRevision > existing.deliveredRevision) {
@@ -2271,7 +2461,7 @@ async function registerInternalUpdateWakeInTransaction(db, input) {
2271
2461
  nextAttemptAt: /* @__PURE__ */ new Date(),
2272
2462
  lastError: null,
2273
2463
  updatedAt: /* @__PURE__ */ new Date()
2274
- }).where(eq4(sessionWorkflowWakeOutbox.sessionId, input.sessionId));
2464
+ }).where(eq5(sessionWorkflowWakeOutbox.sessionId, input.sessionId));
2275
2465
  return { wakeRevision: existing.wakeRevision, shouldSignal: false };
2276
2466
  }
2277
2467
  return {
@@ -2283,7 +2473,7 @@ async function registerInternalUpdateWakeInTransaction(db, input) {
2283
2473
  };
2284
2474
  }
2285
2475
  async function interruptDescendantAttempts(db, input) {
2286
- const rows = await db.execute(sql2`
2476
+ const rows = await db.execute(sql3`
2287
2477
  with recursive live_attempts as (
2288
2478
  select attempt.id, attempt.account_id, attempt.workspace_id, attempt.session_id
2289
2479
  from ${sessionTurnAttempts} attempt
@@ -2331,7 +2521,7 @@ async function interruptDescendantAttempts(db, input) {
2331
2521
  return Number(rows[0]?.count ?? 0);
2332
2522
  }
2333
2523
  async function interruptWorkspaceAttempts(db, input) {
2334
- const rows = await db.execute(sql2`
2524
+ const rows = await db.execute(sql3`
2335
2525
  with inserted as (
2336
2526
  insert into ${sessionAttemptInterruptions} (
2337
2527
  account_id, workspace_id, session_id, operation_id, attempt_id,
@@ -2358,12 +2548,12 @@ async function updateSessionCommandReceiptResult(db, receiptId, input) {
2358
2548
  ...input.draftRevision !== void 0 ? { appliedDraftRevision: input.draftRevision } : {},
2359
2549
  result: input.result,
2360
2550
  updatedAt: /* @__PURE__ */ new Date()
2361
- }).where(eq4(sessionCommandReceipts.id, receiptId)).returning();
2551
+ }).where(eq5(sessionCommandReceipts.id, receiptId)).returning();
2362
2552
  if (!receipt) throw new SessionControlInvariantError("Command receipt disappeared");
2363
2553
  return receipt;
2364
2554
  }
2365
2555
  async function loadSessionSubtreeIds(db, workspaceId, rootSessionId) {
2366
- const rows = await db.execute(sql2`
2556
+ const rows = await db.execute(sql3`
2367
2557
  with recursive subtree(id, root_parent_session_id, depth, path, cycle) as (
2368
2558
  select session.id, session.parent_session_id, 0::integer, array[session.id]::uuid[], false
2369
2559
  from ${sessions} session
@@ -2400,8 +2590,8 @@ var TERMINAL_CANCELLATION_LIVE_TURN_STATUSES = [
2400
2590
  ];
2401
2591
  async function loadCancellationTurnIds(db, workspaceId, sessionIds) {
2402
2592
  const rows = await db.select({ id: sessionTurns.id }).from(sessionTurns).where(
2403
- and4(
2404
- eq4(sessionTurns.workspaceId, workspaceId),
2593
+ and5(
2594
+ eq5(sessionTurns.workspaceId, workspaceId),
2405
2595
  inArray(sessionTurns.sessionId, sessionIds),
2406
2596
  inArray(sessionTurns.status, TERMINAL_CANCELLATION_LIVE_TURN_STATUSES)
2407
2597
  )
@@ -2420,10 +2610,10 @@ async function enqueueCancelledChildOutboxInTransaction(db, input) {
2420
2610
  let personalConnectionDelegations = [];
2421
2611
  if (input.rootSession.parentTurnId) {
2422
2612
  const [parentTurn] = await db.select({ delegations: sessionTurns.personalConnectionDelegations }).from(sessionTurns).where(
2423
- and4(
2424
- eq4(sessionTurns.workspaceId, input.workspaceId),
2425
- eq4(sessionTurns.sessionId, parentSessionId),
2426
- eq4(sessionTurns.id, input.rootSession.parentTurnId)
2613
+ and5(
2614
+ eq5(sessionTurns.workspaceId, input.workspaceId),
2615
+ eq5(sessionTurns.sessionId, parentSessionId),
2616
+ eq5(sessionTurns.id, input.rootSession.parentTurnId)
2427
2617
  )
2428
2618
  ).limit(1);
2429
2619
  if (parentTurn) {
@@ -2465,7 +2655,7 @@ async function enqueueCancelledChildOutboxInTransaction(db, input) {
2465
2655
  });
2466
2656
  }
2467
2657
  async function assertSessionBranchIsNotCancelled(db, workspaceId, sessionId) {
2468
- const rows = await db.execute(sql2`
2658
+ const rows = await db.execute(sql3`
2469
2659
  with recursive ancestry(id, parent_id, status, depth, path, cycle) as (
2470
2660
  select session.id, session.parent_session_id, session.status, 0::integer,
2471
2661
  array[session.id]::uuid[], false
@@ -2540,7 +2730,7 @@ async function cancelSessionSubtreeInTransaction(db, input) {
2540
2730
  activeAttemptId: null,
2541
2731
  cancelledBy: input.actor,
2542
2732
  cancelReason: input.reason ?? "session_cancelled",
2543
- version: sql2`${sessionTurns.version} + 1`,
2733
+ version: sql3`${sessionTurns.version} + 1`,
2544
2734
  finishedAt: now,
2545
2735
  updatedAt: now
2546
2736
  }).where(inArray(sessionTurns.id, immediatelyCancelledTurnIds));
@@ -2551,29 +2741,30 @@ async function cancelSessionSubtreeInTransaction(db, input) {
2551
2741
  respondedAt: now,
2552
2742
  updatedAt: now
2553
2743
  }).where(
2554
- and4(
2555
- eq4(sessionHumanInputRequests.workspaceId, input.workspaceId),
2744
+ and5(
2745
+ eq5(sessionHumanInputRequests.workspaceId, input.workspaceId),
2556
2746
  inArray(sessionHumanInputRequests.turnId, immediatelyCancelledTurnIds),
2557
- eq4(sessionHumanInputRequests.status, "pending")
2747
+ eq5(sessionHumanInputRequests.status, "pending")
2558
2748
  )
2559
2749
  ).returning({
2560
2750
  id: sessionHumanInputRequests.id,
2561
2751
  sessionId: sessionHumanInputRequests.sessionId,
2562
- turnId: sessionHumanInputRequests.turnId
2752
+ turnId: sessionHumanInputRequests.turnId,
2753
+ questions: sessionHumanInputRequests.questions
2563
2754
  });
2564
2755
  await db.update(codexCapacityWaiters).set({ status: "superseded", lastWakeReason: "session_cancelled", updatedAt: now }).where(
2565
- and4(
2566
- eq4(codexCapacityWaiters.workspaceId, input.workspaceId),
2756
+ and5(
2757
+ eq5(codexCapacityWaiters.workspaceId, input.workspaceId),
2567
2758
  inArray(codexCapacityWaiters.blockedTurnId, immediatelyCancelledTurnIds),
2568
- eq4(codexCapacityWaiters.status, "waiting")
2759
+ eq5(codexCapacityWaiters.status, "waiting")
2569
2760
  )
2570
2761
  );
2571
2762
  }
2572
2763
  const cancelledSystemUpdates = await db.update(sessionSystemUpdates).set({ state: "cancelled" }).where(
2573
- and4(
2574
- eq4(sessionSystemUpdates.workspaceId, input.workspaceId),
2764
+ and5(
2765
+ eq5(sessionSystemUpdates.workspaceId, input.workspaceId),
2575
2766
  inArray(sessionSystemUpdates.sessionId, input.sessionIds),
2576
- eq4(sessionSystemUpdates.state, "pending")
2767
+ eq5(sessionSystemUpdates.state, "pending")
2577
2768
  )
2578
2769
  ).returning({
2579
2770
  id: sessionSystemUpdates.id,
@@ -2674,19 +2865,51 @@ async function cancelSessionSubtreeInTransaction(db, input) {
2674
2865
  }
2675
2866
  const inserted = eventValues.length > 0 ? await db.insert(sessionEvents).values(eventValues).returning({
2676
2867
  id: sessionEvents.id,
2677
- sequence: sessionEvents.sequence
2868
+ sequence: sessionEvents.sequence,
2869
+ type: sessionEvents.type,
2870
+ turnId: sessionEvents.turnId,
2871
+ payload: sessionEvents.payload
2678
2872
  }) : [];
2873
+ const cancelledHumanInputsById = new Map(
2874
+ cancelledHumanInputs.filter((request) => request.sessionId === session.id).map((request) => [request.id, request])
2875
+ );
2876
+ for (const event of inserted) {
2877
+ if (event.type !== "user.humanInputResponse") continue;
2878
+ const payload = event.payload;
2879
+ const request = typeof payload.requestId === "string" ? cancelledHumanInputsById.get(payload.requestId) : null;
2880
+ if (!request) continue;
2881
+ await mirrorSessionRealtimeContextInTransaction(db, {
2882
+ accountId: input.accountId,
2883
+ workspaceId: input.workspaceId,
2884
+ sessionId: session.id,
2885
+ sourceKind: "human_input_response",
2886
+ sourceId: event.id,
2887
+ turnId: event.turnId,
2888
+ channel: null,
2889
+ text: renderRealtimeHumanInputResponseContext({
2890
+ requestId: request.id,
2891
+ questions: request.questions,
2892
+ response: { outcome: "cancelled" }
2893
+ }),
2894
+ payload: {
2895
+ requestId: request.id,
2896
+ outcome: "cancelled",
2897
+ sourceEventId: event.id
2898
+ },
2899
+ now
2900
+ });
2901
+ }
2679
2902
  const liveTurnId = session.activeTurnId && liveTurnIds.has(session.activeTurnId) ? session.activeTurnId : null;
2680
2903
  await db.update(sessions).set({
2681
2904
  status: "cancelled",
2682
2905
  activeTurnId: liveTurnId,
2683
- queueVersion: sql2`${sessions.queueVersion} + 1`,
2906
+ queueVersion: sql3`${sessions.queueVersion} + 1`,
2684
2907
  queueHeadPosition: 0,
2685
2908
  queueTailPosition: 0,
2686
2909
  lastSequence: sequence,
2687
2910
  updatedAt: now
2688
2911
  }).where(
2689
- and4(eq4(sessions.workspaceId, input.workspaceId), eq4(sessions.id, session.id))
2912
+ and5(eq5(sessions.workspaceId, input.workspaceId), eq5(sessions.id, session.id))
2690
2913
  );
2691
2914
  const eventIds = [...preinsertedEvents, ...inserted].sort((left, right) => left.sequence - right.sequence).map((event) => event.id);
2692
2915
  if (session.id === input.rootSessionId) eventIds.unshift(input.rootControlEventId);
@@ -2810,9 +3033,9 @@ async function mutateSessionControlInTransaction(db, input) {
2810
3033
  updatedAt: /* @__PURE__ */ new Date()
2811
3034
  }
2812
3035
  ).where(
2813
- and4(
2814
- eq4(sessions.workspaceId, input.workspaceId),
2815
- input.action === "cancel" ? inArray(sessions.id, cancellationSessionIds) : eq4(sessions.id, input.sessionId)
3036
+ and5(
3037
+ eq5(sessions.workspaceId, input.workspaceId),
3038
+ input.action === "cancel" ? inArray(sessions.id, cancellationSessionIds) : eq5(sessions.id, input.sessionId)
2816
3039
  )
2817
3040
  ).returning({
2818
3041
  id: sessions.id,
@@ -2869,7 +3092,7 @@ async function mutateSessionControlInTransaction(db, input) {
2869
3092
  }).returning({ id: sessionEvents.id });
2870
3093
  if (!controlEvent)
2871
3094
  throw new SessionControlInvariantError("Session control event was not inserted");
2872
- await db.update(sessions).set({ lastSequence: updated.lastSequence + 1, updatedAt: /* @__PURE__ */ new Date() }).where(eq4(sessions.id, input.sessionId));
3095
+ await db.update(sessions).set({ lastSequence: updated.lastSequence + 1, updatedAt: /* @__PURE__ */ new Date() }).where(eq5(sessions.id, input.sessionId));
2873
3096
  await db.insert(auditEvents).values({
2874
3097
  accountId: input.accountId,
2875
3098
  workspaceId: input.workspaceId,
@@ -2963,9 +3186,9 @@ async function autoResumeSessionBranchInTransaction(db, input) {
2963
3186
  directControlChangedAt: /* @__PURE__ */ new Date(),
2964
3187
  updatedAt: /* @__PURE__ */ new Date()
2965
3188
  }).where(
2966
- and4(
2967
- eq4(sessions.workspaceId, input.workspaceId),
2968
- eq4(sessions.id, input.sessionId)
3189
+ and5(
3190
+ eq5(sessions.workspaceId, input.workspaceId),
3191
+ eq5(sessions.id, input.sessionId)
2969
3192
  )
2970
3193
  );
2971
3194
  const workspaceControlEventId = await insertWorkspaceControlEventInTransaction(db, {
@@ -3035,9 +3258,9 @@ async function mutateWorkspaceControlInTransaction(db, input) {
3035
3258
  changedAt: /* @__PURE__ */ new Date(),
3036
3259
  updatedAt: /* @__PURE__ */ new Date()
3037
3260
  }).where(
3038
- and4(
3039
- eq4(workspaceInferenceControls.workspaceId, input.workspaceId),
3040
- eq4(workspaceInferenceControls.revision, currentRevision)
3261
+ and5(
3262
+ eq5(workspaceInferenceControls.workspaceId, input.workspaceId),
3263
+ eq5(workspaceInferenceControls.revision, currentRevision)
3041
3264
  )
3042
3265
  ).returning({ workspaceId: workspaceInferenceControls.workspaceId });
3043
3266
  if (!updated) {
@@ -3114,7 +3337,7 @@ async function insertWorkspaceControlEventInTransaction(db, input) {
3114
3337
 
3115
3338
  // src/session-realtime.ts
3116
3339
  import { createHash as createHash4, timingSafeEqual } from "crypto";
3117
- import { and as and9, asc as asc4, eq as eq9, inArray as inArray4 } from "drizzle-orm";
3340
+ import { and as and9, asc as asc4, eq as eq9, gt as gt3, inArray as inArray4, isNull as isNull2, or } from "drizzle-orm";
3118
3341
 
3119
3342
  // src/session-realtime-context.ts
3120
3343
  import { createHash as createHash3 } from "crypto";
@@ -3134,115 +3357,17 @@ import {
3134
3357
  import { and as and7, asc as asc2, eq as eq7, inArray as inArray2, sql as sql4 } from "drizzle-orm";
3135
3358
 
3136
3359
  // src/session-realtime-state.ts
3137
- import { and as and5, eq as eq5, gt } from "drizzle-orm";
3360
+ import { and as and6, eq as eq6, gt as gt2 } from "drizzle-orm";
3138
3361
  async function sessionRealtimeIsActiveInTransaction(db, workspaceId, sessionId, now = /* @__PURE__ */ new Date()) {
3139
3362
  const [row] = await db.select({ id: sessionRealtimeModes.id }).from(sessionRealtimeModes).where(
3140
- and5(
3141
- eq5(sessionRealtimeModes.workspaceId, workspaceId),
3142
- eq5(sessionRealtimeModes.sessionId, sessionId),
3143
- eq5(sessionRealtimeModes.state, "active"),
3144
- gt(sessionRealtimeModes.leaseExpiresAt, now)
3145
- )
3146
- ).limit(1);
3147
- return Boolean(row);
3148
- }
3149
-
3150
- // src/session-realtime-mirror.ts
3151
- import { createHash as createHash2 } from "crypto";
3152
- import { and as and6, desc, eq as eq6, gt as gt2, sql as sql3 } from "drizzle-orm";
3153
- var SESSION_REALTIME_MIRROR_MAX_TEXT_BYTES = 131072;
3154
- var SESSION_REALTIME_MIRROR_MAX_PAYLOAD_BYTES = 131072;
3155
- var TRUNCATION_MARKER = "\n\u2026realtime context truncated\u2026";
3156
- function deterministicUuid(seed) {
3157
- const bytes = createHash2("sha256").update(seed, "utf8").digest().subarray(0, 16);
3158
- bytes[6] = (bytes[6] ?? 0) & 15 | 80;
3159
- bytes[8] = (bytes[8] ?? 0) & 63 | 128;
3160
- const hex = bytes.toString("hex");
3161
- return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
3162
- }
3163
- function takeUtf8Head(value, maximumBytes) {
3164
- const bytes = Buffer.from(value, "utf8");
3165
- if (bytes.length <= maximumBytes) return value;
3166
- let end = maximumBytes;
3167
- while (end > 0 && (bytes[end] & 192) === 128) end -= 1;
3168
- return bytes.subarray(0, end).toString("utf8");
3169
- }
3170
- function boundedText(value) {
3171
- if (Buffer.byteLength(value, "utf8") <= SESSION_REALTIME_MIRROR_MAX_TEXT_BYTES) return value;
3172
- const markerBytes = Buffer.byteLength(TRUNCATION_MARKER, "utf8");
3173
- return `${takeUtf8Head(value, SESSION_REALTIME_MIRROR_MAX_TEXT_BYTES - markerBytes)}${TRUNCATION_MARKER}`;
3174
- }
3175
- function boundedPayload(value) {
3176
- const payload = sanitizeEventPayload(value);
3177
- if (Buffer.byteLength(JSON.stringify(payload), "utf8") > SESSION_REALTIME_MIRROR_MAX_PAYLOAD_BYTES) {
3178
- throw new Error("Realtime mirror payload exceeds the durable ledger limit");
3179
- }
3180
- return payload;
3181
- }
3182
- async function mirrorSessionRealtimeContextInTransaction(db, input) {
3183
- const now = input.now ?? /* @__PURE__ */ new Date();
3184
- const modes = await db.select().from(sessionRealtimeModes).where(
3185
3363
  and6(
3186
- eq6(sessionRealtimeModes.accountId, input.accountId),
3187
- eq6(sessionRealtimeModes.workspaceId, input.workspaceId),
3188
- eq6(sessionRealtimeModes.sessionId, input.sessionId),
3364
+ eq6(sessionRealtimeModes.workspaceId, workspaceId),
3365
+ eq6(sessionRealtimeModes.sessionId, sessionId),
3189
3366
  eq6(sessionRealtimeModes.state, "active"),
3190
3367
  gt2(sessionRealtimeModes.leaseExpiresAt, now)
3191
3368
  )
3192
- ).orderBy(desc(sessionRealtimeModes.startedAt)).for("update").limit(2);
3193
- if (modes.length === 0) return null;
3194
- if (modes.length !== 1) {
3195
- throw new Error(`Session ${input.sessionId} has multiple active realtime modes`);
3196
- }
3197
- const mode = modes[0];
3198
- const operationId = deterministicUuid(
3199
- `opengeni:session-realtime-mirror:${mode.id}:${input.sourceKind}:${input.sourceId}`
3200
- );
3201
- const [existing] = await db.select().from(sessionRealtimeEntries).where(
3202
- and6(
3203
- eq6(sessionRealtimeEntries.realtimeId, mode.id),
3204
- eq6(sessionRealtimeEntries.operationId, operationId)
3205
- )
3206
3369
  ).limit(1);
3207
- if (existing) return { entry: existing, replay: true };
3208
- const [sequenceRow] = await db.select({ next: sql3`coalesce(max(${sessionRealtimeEntries.sequence}), 0) + 1` }).from(sessionRealtimeEntries).where(eq6(sessionRealtimeEntries.realtimeId, mode.id));
3209
- const payload = boundedPayload({
3210
- ...input.payload ?? {},
3211
- source: input.sourceKind,
3212
- sourceId: input.sourceId,
3213
- channel: input.channel,
3214
- ...input.turnId ? { sourceTurnId: input.turnId } : {}
3215
- });
3216
- const [entry] = await db.insert(sessionRealtimeEntries).values({
3217
- accountId: input.accountId,
3218
- workspaceId: input.workspaceId,
3219
- sessionId: input.sessionId,
3220
- realtimeId: mode.id,
3221
- operationId,
3222
- connectionEpoch: mode.connectionEpoch,
3223
- sequence: Number(sequenceRow?.next ?? 1),
3224
- direction: "provider_out",
3225
- kind: "session_update",
3226
- text: boundedText(input.text),
3227
- payload,
3228
- createdAt: now,
3229
- updatedAt: now
3230
- }).returning();
3231
- if (!entry) throw new Error("Failed to append realtime session context");
3232
- return { entry, replay: false };
3233
- }
3234
- function renderRealtimeHumanInputContext(input) {
3235
- return [
3236
- "<session_user_message>",
3237
- ` <status>${input.routing}</status>`,
3238
- ` <delivery>${input.delivery}</delivery>`,
3239
- ` <text>${escapeXmlText(input.text)}</text>`,
3240
- " <instruction>Already routed by OpenGeni; do not delegate this message again.</instruction>",
3241
- "</session_user_message>"
3242
- ].join("\n");
3243
- }
3244
- function escapeXmlText(value) {
3245
- return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
3370
+ return Boolean(row);
3246
3371
  }
3247
3372
 
3248
3373
  // src/session-queue-commands.ts
@@ -3370,10 +3495,13 @@ async function supersedeSessionCurrentDirectionInTransaction(db, input) {
3370
3495
  eq7(sessionHumanInputRequests.turnId, current.id),
3371
3496
  eq7(sessionHumanInputRequests.status, "pending")
3372
3497
  )
3373
- ).returning({ id: sessionHumanInputRequests.id });
3498
+ ).returning({
3499
+ id: sessionHumanInputRequests.id,
3500
+ questions: sessionHumanInputRequests.questions
3501
+ });
3374
3502
  let lastSequence = closedTools.sequence;
3375
3503
  if (cancelledHumanInputs.length > 0) {
3376
- await db.insert(sessionEvents).values(
3504
+ const cancelledHumanInputEvents = await db.insert(sessionEvents).values(
3377
3505
  cancelledHumanInputs.map((request) => ({
3378
3506
  accountId: input.accountId,
3379
3507
  workspaceId: input.workspaceId,
@@ -3386,7 +3514,33 @@ async function supersedeSessionCurrentDirectionInTransaction(db, input) {
3386
3514
  payload: { requestId: request.id, response: { outcome: "cancelled" } },
3387
3515
  occurredAt: now
3388
3516
  }))
3389
- );
3517
+ ).returning();
3518
+ const requestsById = new Map(cancelledHumanInputs.map((request) => [request.id, request]));
3519
+ for (const event of cancelledHumanInputEvents) {
3520
+ const payload = event.payload;
3521
+ const request = typeof payload.requestId === "string" ? requestsById.get(payload.requestId) : null;
3522
+ if (!request) continue;
3523
+ await mirrorSessionRealtimeContextInTransaction(db, {
3524
+ accountId: input.accountId,
3525
+ workspaceId: input.workspaceId,
3526
+ sessionId: input.sessionId,
3527
+ sourceKind: "human_input_response",
3528
+ sourceId: event.id,
3529
+ turnId: current.id,
3530
+ channel: null,
3531
+ text: renderRealtimeHumanInputResponseContext({
3532
+ requestId: request.id,
3533
+ questions: request.questions,
3534
+ response: { outcome: "cancelled" }
3535
+ }),
3536
+ payload: {
3537
+ requestId: request.id,
3538
+ outcome: "cancelled",
3539
+ sourceEventId: event.id
3540
+ },
3541
+ now
3542
+ });
3543
+ }
3390
3544
  }
3391
3545
  await db.update(sessionTurns).set({
3392
3546
  status: "superseded",
@@ -5435,6 +5589,46 @@ async function beginSessionRealtimeInTransaction(db, input) {
5435
5589
  now
5436
5590
  );
5437
5591
  eventIds.push(event.id);
5592
+ const pendingHumanInputs = await db.select({
5593
+ id: sessionHumanInputRequests.id,
5594
+ turnId: sessionHumanInputRequests.turnId,
5595
+ questions: sessionHumanInputRequests.questions,
5596
+ allowSkip: sessionHumanInputRequests.allowSkip,
5597
+ expiresAt: sessionHumanInputRequests.expiresAt
5598
+ }).from(sessionHumanInputRequests).where(
5599
+ and9(
5600
+ eq9(sessionHumanInputRequests.accountId, input.accountId),
5601
+ eq9(sessionHumanInputRequests.workspaceId, input.workspaceId),
5602
+ eq9(sessionHumanInputRequests.sessionId, input.sessionId),
5603
+ eq9(sessionHumanInputRequests.status, "pending"),
5604
+ or(
5605
+ isNull2(sessionHumanInputRequests.expiresAt),
5606
+ gt3(sessionHumanInputRequests.expiresAt, now)
5607
+ )
5608
+ )
5609
+ ).orderBy(
5610
+ asc4(sessionHumanInputRequests.createdAt),
5611
+ asc4(sessionHumanInputRequests.id)
5612
+ );
5613
+ if (pendingHumanInputs.length > 0) {
5614
+ const sourceTurnIds = new Set(pendingHumanInputs.map((request) => request.turnId));
5615
+ await mirrorSessionRealtimeContextInTransaction(db, {
5616
+ accountId: input.accountId,
5617
+ workspaceId: input.workspaceId,
5618
+ sessionId: input.sessionId,
5619
+ sourceKind: "human_input_request",
5620
+ sourceId: `startup:${pendingHumanInputs.map((request) => request.id).join(":")}`,
5621
+ turnId: sourceTurnIds.size === 1 ? pendingHumanInputs[0].turnId : null,
5622
+ channel: "speakable",
5623
+ text: renderRealtimeHumanInputRequestContext({ requests: pendingHumanInputs }),
5624
+ payload: {
5625
+ status: "waiting_for_user",
5626
+ requestIds: pendingHumanInputs.map((request) => request.id),
5627
+ trigger: "realtime_start"
5628
+ },
5629
+ now
5630
+ });
5631
+ }
5438
5632
  return {
5439
5633
  mode: mapRealtimeMode(row),
5440
5634
  replay: false,
@@ -5566,7 +5760,7 @@ async function settleExpiredSessionRealtimeInTransaction(db, session, now = /* @
5566
5760
  // src/session-realtime-ledger.ts
5567
5761
  import { createHash as createHash6 } from "crypto";
5568
5762
  import { LatencyMode, ReasoningEffort as ReasoningEffort2 } from "@opengeni/contracts";
5569
- import { and as and11, asc as asc5, desc as desc3, eq as eq11, inArray as inArray6, isNull as isNull2, or, sql as sql7 } from "drizzle-orm";
5763
+ import { and as and11, asc as asc5, desc as desc3, eq as eq11, inArray as inArray6, isNull as isNull3, or as or2, sql as sql7 } from "drizzle-orm";
5570
5764
 
5571
5765
  // src/session-realtime-terminal.ts
5572
5766
  import { createHash as createHash5 } from "crypto";
@@ -6016,7 +6210,7 @@ async function claimSessionRealtimeConnectionInTransaction(db, input) {
6016
6210
  and11(
6017
6211
  eq11(sessionRealtimeEntries.realtimeId, input.realtimeId),
6018
6212
  eq11(sessionRealtimeEntries.direction, "provider_out"),
6019
- isNull2(sessionRealtimeEntries.providerAckedAt)
6213
+ isNull3(sessionRealtimeEntries.providerAckedAt)
6020
6214
  )
6021
6215
  ).orderBy(asc5(sessionRealtimeEntries.sequence)).limit(SESSION_REALTIME_STARTUP_MAX_ENTRIES);
6022
6216
  const startupFenceSequence = startupEntries.at(-1)?.sequence ?? 0;
@@ -6048,7 +6242,7 @@ async function startupEntriesForConnection(db, connection) {
6048
6242
  and11(
6049
6243
  eq11(sessionRealtimeEntries.realtimeId, connection.realtimeId),
6050
6244
  eq11(sessionRealtimeEntries.direction, "provider_out"),
6051
- isNull2(sessionRealtimeEntries.providerAckedAt),
6245
+ isNull3(sessionRealtimeEntries.providerAckedAt),
6052
6246
  sql7`${sessionRealtimeEntries.sequence} <= ${connection.startupFenceSequence}`
6053
6247
  )
6054
6248
  ).orderBy(asc5(sessionRealtimeEntries.sequence)).limit(SESSION_REALTIME_STARTUP_MAX_ENTRIES);
@@ -6470,7 +6664,7 @@ async function materializeRealtimeUpdates(db, input, accountId, allocateSequence
6470
6664
  eq11(sessionSystemUpdates.sessionId, input.sessionId),
6471
6665
  inArray6(sessionSystemUpdates.state, ["pending", "deferred"]),
6472
6666
  inArray6(sessionSystemUpdates.kind, ["agent_message", "child_terminal_result"]),
6473
- isNull2(sessionRealtimeEntries.id)
6667
+ isNull3(sessionRealtimeEntries.id)
6474
6668
  )
6475
6669
  ).orderBy(asc5(sessionSystemUpdates.createdAt), asc5(sessionSystemUpdates.id)).limit(SESSION_REALTIME_LEDGER_MAX_OUTBOUND);
6476
6670
  const updates = rows.map(({ update }) => update);
@@ -6579,7 +6773,7 @@ async function syncSessionRealtimeLedgerInTransaction(db, input, hooks = {}) {
6579
6773
  }).where(
6580
6774
  and11(
6581
6775
  eq11(sessionRealtimeConnections.id, connection.id),
6582
- isNull2(sessionRealtimeConnections.startupAcknowledgedAt)
6776
+ isNull3(sessionRealtimeConnections.startupAcknowledgedAt)
6583
6777
  )
6584
6778
  ).returning({ id: sessionRealtimeConnections.id });
6585
6779
  if (!acknowledged) {
@@ -6616,7 +6810,7 @@ async function syncSessionRealtimeLedgerInTransaction(db, input, hooks = {}) {
6616
6810
  const [existing] = await db.select().from(sessionRealtimeEntries).where(
6617
6811
  and11(
6618
6812
  eq11(sessionRealtimeEntries.realtimeId, input.realtimeId),
6619
- incoming.kind === "delegation_call" && incoming.delegationItemId ? or(
6813
+ incoming.kind === "delegation_call" && incoming.delegationItemId ? or2(
6620
6814
  eq11(sessionRealtimeEntries.operationId, incoming.operationId),
6621
6815
  and11(
6622
6816
  eq11(sessionRealtimeEntries.kind, "delegation_call"),
@@ -6695,7 +6889,7 @@ async function syncSessionRealtimeLedgerInTransaction(db, input, hooks = {}) {
6695
6889
  eq11(sessionRealtimeEntries.sessionId, input.sessionId),
6696
6890
  eq11(sessionRealtimeEntries.realtimeId, input.realtimeId),
6697
6891
  eq11(sessionRealtimeEntries.direction, "provider_out"),
6698
- isNull2(sessionRealtimeEntries.clientAckedAt),
6892
+ isNull3(sessionRealtimeEntries.clientAckedAt),
6699
6893
  sql7`${sessionRealtimeEntries.sequence} <= ${clientAck}`
6700
6894
  )
6701
6895
  );
@@ -6730,7 +6924,7 @@ async function syncSessionRealtimeLedgerInTransaction(db, input, hooks = {}) {
6730
6924
  sessionRealtimeEntries.id,
6731
6925
  ackable.map((entry) => entry.id)
6732
6926
  ),
6733
- isNull2(sessionRealtimeEntries.providerAckedAt)
6927
+ isNull3(sessionRealtimeEntries.providerAckedAt)
6734
6928
  )
6735
6929
  );
6736
6930
  }
@@ -6740,7 +6934,7 @@ async function syncSessionRealtimeLedgerInTransaction(db, input, hooks = {}) {
6740
6934
  eq11(sessionRealtimeEntries.sessionId, input.sessionId),
6741
6935
  eq11(sessionRealtimeEntries.realtimeId, input.realtimeId),
6742
6936
  eq11(sessionRealtimeEntries.direction, "provider_out"),
6743
- isNull2(sessionRealtimeEntries.providerAckedAt)
6937
+ isNull3(sessionRealtimeEntries.providerAckedAt)
6744
6938
  )
6745
6939
  ).orderBy(
6746
6940
  sql7`case when ${sessionRealtimeEntries.clientAckedAt} is null then 0 else 1 end`,
@@ -7300,13 +7494,14 @@ function renderMemoryEntry(record) {
7300
7494
  import { sql as sql15 } from "drizzle-orm";
7301
7495
 
7302
7496
  // src/workspace-instruction-policies.ts
7303
- import { createHash as createHash8 } from "crypto";
7497
+ import { createHash as createHash8, randomUUID } from "crypto";
7304
7498
  import {
7499
+ PreferenceRegistrySnapshot,
7305
7500
  ResolvedWorkspaceInstructionPolicySnapshot,
7306
7501
  WORKSPACE_INSTRUCTION_POLICY_CONTENT_MAX_CHARS,
7307
7502
  WorkspaceInstructionPolicySnapshot
7308
7503
  } from "@opengeni/contracts";
7309
- import { and as and12, asc as asc6, desc as desc4, eq as eq12, inArray as inArray7, isNull as isNull3, lt, sql as sql8 } from "drizzle-orm";
7504
+ import { and as and12, asc as asc6, desc as desc4, eq as eq12, inArray as inArray7, isNull as isNull4, lt, or as or3, sql as sql8 } from "drizzle-orm";
7310
7505
  var WorkspaceInstructionPolicyConflictError = class extends Error {
7311
7506
  constructor(currentHead) {
7312
7507
  super("The active workspace instruction policy changed in another request");
@@ -7315,6 +7510,13 @@ var WorkspaceInstructionPolicyConflictError = class extends Error {
7315
7510
  name = "WorkspaceInstructionPolicyConflictError";
7316
7511
  code = "WORKSPACE_INSTRUCTION_POLICY_CONFLICT";
7317
7512
  };
7513
+ var WorkspaceInstructionPolicyOperationReuseError = class extends Error {
7514
+ name = "WorkspaceInstructionPolicyOperationReuseError";
7515
+ code = "WORKSPACE_INSTRUCTION_POLICY_OPERATION_REUSED";
7516
+ constructor() {
7517
+ super("The workspace instruction-policy operation id was already used for another request");
7518
+ }
7519
+ };
7318
7520
  var WorkspaceInstructionPolicyNotFoundError = class extends Error {
7319
7521
  name = "WorkspaceInstructionPolicyNotFoundError";
7320
7522
  constructor(message = "Workspace instruction-policy revision was not found") {
@@ -7330,18 +7532,217 @@ var WorkspaceInstructionPolicyLegacyUnavailableError = class extends Error {
7330
7532
  super("This workspace has no legacy agent instructions to import");
7331
7533
  }
7332
7534
  };
7535
+ var WorkspaceInstructionPolicyOnboardingProposalContentError = class extends Error {
7536
+ constructor(code) {
7537
+ super(
7538
+ code === "WORKSPACE_INSTRUCTION_POLICY_ONBOARDING_PROPOSAL_EMPTY" ? "An onboarding proposal must contain non-blank instruction-policy content" : `An onboarding proposal must not exceed ${WORKSPACE_INSTRUCTION_POLICY_CONTENT_MAX_CHARS} characters`
7539
+ );
7540
+ this.code = code;
7541
+ }
7542
+ name = "WorkspaceInstructionPolicyOnboardingProposalContentError";
7543
+ };
7544
+ var WorkspaceInstructionPolicyOnboardingProposalStaleError = class extends Error {
7545
+ constructor(currentHead) {
7546
+ super("The onboarding proposal was prepared against a stale active policy baseline");
7547
+ this.currentHead = currentHead;
7548
+ }
7549
+ name = "WorkspaceInstructionPolicyOnboardingProposalStaleError";
7550
+ code = "WORKSPACE_INSTRUCTION_POLICY_ONBOARDING_PROPOSAL_STALE";
7551
+ };
7552
+ var WorkspaceInstructionPolicyOnboardingProposalConflictError = class extends Error {
7553
+ constructor(existingProposalId, existingDraftRevisionId) {
7554
+ super("This onboarding source version already proposed a draft for the policy target");
7555
+ this.existingProposalId = existingProposalId;
7556
+ this.existingDraftRevisionId = existingDraftRevisionId;
7557
+ }
7558
+ name = "WorkspaceInstructionPolicyOnboardingProposalConflictError";
7559
+ code = "WORKSPACE_INSTRUCTION_POLICY_ONBOARDING_PROPOSAL_CONFLICT";
7560
+ };
7333
7561
  var WorkspaceInstructionPolicySnapshotAuthorityError = class extends Error {
7334
7562
  name = "WorkspaceInstructionPolicySnapshotAuthorityError";
7335
7563
  };
7336
7564
  function contentHash(content) {
7337
7565
  return createHash8("sha256").update(content, "utf8").digest("hex");
7338
7566
  }
7567
+ function hasOwnField(value, field) {
7568
+ return Object.prototype.hasOwnProperty.call(value, field);
7569
+ }
7570
+ function operationRequestFingerprint(operation, fields) {
7571
+ const canonicalRequest = JSON.stringify([
7572
+ "workspace_instruction_policy_operation",
7573
+ 1,
7574
+ operation,
7575
+ fields
7576
+ ]);
7577
+ return createHash8("sha256").update(canonicalRequest, "utf8").digest("hex");
7578
+ }
7579
+ function draftRequestFingerprint(input) {
7580
+ return operationRequestFingerprint("create_draft", [
7581
+ ["accountId", true, input.accountId],
7582
+ ["workspaceId", true, input.workspaceId],
7583
+ ["kind", true, input.kind],
7584
+ ["scope", true, input.scope],
7585
+ ["roleKey", true, input.roleKey],
7586
+ ["content", true, input.content],
7587
+ ["provenanceSource", true, input.provenanceSource],
7588
+ ["provenanceSourceId", true, input.provenanceSourceId],
7589
+ ["supersedesRevisionId", true, input.supersedesRevisionId],
7590
+ ["createdBySubjectId", true, input.createdBySubjectId]
7591
+ ]);
7592
+ }
7593
+ function importLegacyRequestFingerprint(input) {
7594
+ return operationRequestFingerprint("import_legacy", [
7595
+ ["accountId", true, input.accountId],
7596
+ ["workspaceId", true, input.workspaceId],
7597
+ ["createdBySubjectId", true, input.createdBySubjectId],
7598
+ ["supersedesRevisionId", true, input.supersedesRevisionId]
7599
+ ]);
7600
+ }
7601
+ function activeRevisionRequestFingerprint(input) {
7602
+ const expectedCurrentRevisionIdPresent = hasOwnField(input, "expectedCurrentRevisionId");
7603
+ const expectedActivationVersionPresent = hasOwnField(input, "expectedActivationVersion");
7604
+ return operationRequestFingerprint(`change_active_revision:${input.type}`, [
7605
+ ["accountId", true, input.accountId],
7606
+ ["workspaceId", true, input.workspaceId],
7607
+ ["targetRevisionId", true, input.targetRevisionId],
7608
+ [
7609
+ "expectedCurrentRevisionId",
7610
+ expectedCurrentRevisionIdPresent,
7611
+ input.expectedCurrentRevisionId ?? null
7612
+ ],
7613
+ [
7614
+ "expectedActivationVersion",
7615
+ expectedActivationVersionPresent,
7616
+ input.expectedActivationVersion ?? null
7617
+ ],
7618
+ ["actorSubjectId", true, input.actorSubjectId],
7619
+ ["reason", true, input.reason]
7620
+ ]);
7621
+ }
7622
+ function onboardingProposalRequestFingerprint(input) {
7623
+ return operationRequestFingerprint("create_onboarding_proposal", [
7624
+ ["accountId", true, input.accountId],
7625
+ ["workspaceId", true, input.workspaceId],
7626
+ ["kind", true, input.kind],
7627
+ ["scope", true, input.scope],
7628
+ ["roleKey", true, input.roleKey],
7629
+ ["content", true, input.content],
7630
+ ["sourceId", true, input.sourceId],
7631
+ ["sourceVersion", true, input.sourceVersion],
7632
+ ["confidenceBps", true, input.confidenceBps],
7633
+ ["expectedCurrentRevisionId", true, input.expectedCurrentRevisionId],
7634
+ ["expectedActivationVersion", true, input.expectedActivationVersion],
7635
+ ["createdBySubjectId", true, input.createdBySubjectId]
7636
+ ]);
7637
+ }
7339
7638
  function iso(value) {
7340
7639
  return (value instanceof Date ? value : new Date(value)).toISOString();
7341
7640
  }
7641
+ async function getWorkspaceStateAcceptedAttemptGovernance(db, input) {
7642
+ return await withWorkspaceSubjectRls(db, input.workspaceId, input.subjectId, async (scopedDb) => {
7643
+ const initiatingSubject = sql8`coalesce(
7644
+ ${sessionTurns.initiatingHumanSubjectId},
7645
+ case when ${sessionTurns.initiatorKind} = 'subject'
7646
+ then ${sessionTurns.initiatorSubjectId}
7647
+ end
7648
+ )`;
7649
+ const [attempt] = await scopedDb.select({
7650
+ attemptId: sessionTurnAttempts.id,
7651
+ executionGeneration: sessionTurnAttempts.executionGeneration,
7652
+ acceptedAt: sessionTurns.createdAt
7653
+ }).from(sessionTurnAttempts).innerJoin(
7654
+ sessionTurns,
7655
+ and12(
7656
+ eq12(sessionTurns.accountId, sessionTurnAttempts.accountId),
7657
+ eq12(sessionTurns.workspaceId, sessionTurnAttempts.workspaceId),
7658
+ eq12(sessionTurns.sessionId, sessionTurnAttempts.sessionId),
7659
+ eq12(sessionTurns.id, sessionTurnAttempts.turnId)
7660
+ )
7661
+ ).where(
7662
+ and12(
7663
+ eq12(sessionTurnAttempts.accountId, input.accountId),
7664
+ eq12(sessionTurnAttempts.workspaceId, input.workspaceId),
7665
+ eq12(sessionTurnAttempts.id, input.attemptId),
7666
+ eq12(initiatingSubject, input.subjectId)
7667
+ )
7668
+ ).limit(1);
7669
+ if (!attempt) return null;
7670
+ const [policyRows, preferenceRows] = await Promise.all([
7671
+ scopedDb.select().from(workspaceInstructionPolicySnapshots).where(
7672
+ and12(
7673
+ eq12(workspaceInstructionPolicySnapshots.accountId, input.accountId),
7674
+ eq12(workspaceInstructionPolicySnapshots.workspaceId, input.workspaceId),
7675
+ eq12(workspaceInstructionPolicySnapshots.attemptId, input.attemptId),
7676
+ eq12(
7677
+ workspaceInstructionPolicySnapshots.executionGeneration,
7678
+ attempt.executionGeneration
7679
+ )
7680
+ )
7681
+ ).limit(1),
7682
+ scopedDb.select().from(preferenceRegistrySnapshots).where(
7683
+ and12(
7684
+ eq12(preferenceRegistrySnapshots.accountId, input.accountId),
7685
+ eq12(preferenceRegistrySnapshots.workspaceId, input.workspaceId),
7686
+ eq12(preferenceRegistrySnapshots.attemptId, input.attemptId),
7687
+ eq12(preferenceRegistrySnapshots.executionGeneration, attempt.executionGeneration),
7688
+ eq12(preferenceRegistrySnapshots.initiatingHumanSubjectId, input.subjectId)
7689
+ )
7690
+ ).limit(1)
7691
+ ]);
7692
+ const policyRow = policyRows[0] ?? null;
7693
+ const preferenceRow = preferenceRows[0] ?? null;
7694
+ return {
7695
+ attemptId: attempt.attemptId,
7696
+ executionGeneration: attempt.executionGeneration,
7697
+ acceptedAt: iso(attempt.acceptedAt),
7698
+ policySnapshot: policyRow ? WorkspaceInstructionPolicySnapshot.parse({
7699
+ id: policyRow.id,
7700
+ workspaceId: policyRow.workspaceId,
7701
+ sessionId: policyRow.sessionId,
7702
+ turnId: policyRow.turnId,
7703
+ attemptId: policyRow.attemptId,
7704
+ executionGeneration: policyRow.executionGeneration,
7705
+ policyRole: policyRow.policyRole,
7706
+ roleSource: policyRow.roleSource,
7707
+ entries: policyRow.entries,
7708
+ entryHash: policyRow.entryHash,
7709
+ createdAt: iso(policyRow.createdAt)
7710
+ }) : null,
7711
+ preferenceSnapshot: preferenceRow ? (() => {
7712
+ const snapshot = PreferenceRegistrySnapshot.parse({
7713
+ id: preferenceRow.id,
7714
+ workspaceId: preferenceRow.workspaceId,
7715
+ sessionId: preferenceRow.sessionId,
7716
+ turnId: preferenceRow.turnId,
7717
+ attemptId: preferenceRow.attemptId,
7718
+ executionGeneration: preferenceRow.executionGeneration,
7719
+ initiatingHumanSubjectId: preferenceRow.initiatingHumanSubjectId,
7720
+ descriptorHash: preferenceRow.descriptorHash,
7721
+ descriptors: preferenceRow.descriptors,
7722
+ truncated: preferenceRow.truncated,
7723
+ createdAt: iso(preferenceRow.createdAt)
7724
+ });
7725
+ return {
7726
+ id: snapshot.id,
7727
+ descriptorHash: snapshot.descriptorHash,
7728
+ descriptors: snapshot.descriptors.map((descriptor) => ({
7729
+ id: descriptor.id,
7730
+ revisionId: descriptor.revisionId,
7731
+ contentHash: descriptor.contentHash,
7732
+ activeVersion: descriptor.activeVersion,
7733
+ scope: descriptor.scope
7734
+ })),
7735
+ truncated: snapshot.truncated,
7736
+ createdAt: snapshot.createdAt
7737
+ };
7738
+ })() : null
7739
+ };
7740
+ });
7741
+ }
7342
7742
  function revisionFromRow(row) {
7343
7743
  return {
7344
7744
  id: row.id,
7745
+ operationId: row.operationId ?? row.id,
7345
7746
  accountId: row.accountId,
7346
7747
  workspaceId: row.workspaceId,
7347
7748
  revision: row.revision,
@@ -7375,6 +7776,7 @@ function headFromRow(row) {
7375
7776
  function eventFromRow(row) {
7376
7777
  return {
7377
7778
  id: row.id,
7779
+ operationId: row.operationId ?? row.id,
7378
7780
  accountId: row.accountId,
7379
7781
  workspaceId: row.workspaceId,
7380
7782
  kind: row.kind,
@@ -7397,12 +7799,56 @@ function eventFromRow(row) {
7397
7799
  createdAt: iso(row.createdAt)
7398
7800
  };
7399
7801
  }
7802
+ function onboardingProposalFromRow(row, draftRow) {
7803
+ return {
7804
+ id: row.id,
7805
+ operationId: row.operationId,
7806
+ accountId: row.accountId,
7807
+ workspaceId: row.workspaceId,
7808
+ kind: row.kind,
7809
+ scope: row.scope,
7810
+ roleKey: row.roleKey,
7811
+ source: {
7812
+ id: row.sourceId,
7813
+ version: row.sourceVersion,
7814
+ confidenceBps: row.confidenceBps
7815
+ },
7816
+ baseline: row.baselineRevisionId === null ? null : {
7817
+ workspaceId: row.workspaceId,
7818
+ kind: row.kind,
7819
+ scope: row.scope,
7820
+ roleKey: row.roleKey,
7821
+ revisionId: row.baselineRevisionId,
7822
+ revision: row.baselineRevision,
7823
+ contentHash: row.baselineContentHash,
7824
+ activationVersion: row.baselineActivationVersion,
7825
+ activatedAt: iso(row.baselineActivatedAt)
7826
+ },
7827
+ draft: revisionFromRow(draftRow),
7828
+ status: "proposed",
7829
+ createdBySubjectId: row.createdBySubjectId,
7830
+ createdAt: iso(row.createdAt)
7831
+ };
7832
+ }
7833
+ function headFromEventRow(row) {
7834
+ return {
7835
+ workspaceId: row.workspaceId,
7836
+ kind: row.kind,
7837
+ scope: row.scope,
7838
+ roleKey: row.roleKey,
7839
+ revisionId: row.newRevisionId,
7840
+ revision: row.newRevision,
7841
+ contentHash: row.newContentHash,
7842
+ activationVersion: row.activationVersion,
7843
+ activatedAt: iso(row.createdAt)
7844
+ };
7845
+ }
7400
7846
  function headTargetConditions(workspaceId, target) {
7401
7847
  return [
7402
7848
  eq12(workspaceInstructionPolicyHeads.workspaceId, workspaceId),
7403
7849
  eq12(workspaceInstructionPolicyHeads.kind, target.kind),
7404
7850
  eq12(workspaceInstructionPolicyHeads.scope, target.scope),
7405
- target.roleKey === null ? isNull3(workspaceInstructionPolicyHeads.roleKey) : eq12(workspaceInstructionPolicyHeads.roleKey, target.roleKey)
7851
+ target.roleKey === null ? isNull4(workspaceInstructionPolicyHeads.roleKey) : eq12(workspaceInstructionPolicyHeads.roleKey, target.roleKey)
7406
7852
  ];
7407
7853
  }
7408
7854
  function eventTargetConditions(workspaceId, target) {
@@ -7410,7 +7856,7 @@ function eventTargetConditions(workspaceId, target) {
7410
7856
  eq12(workspaceInstructionPolicyActivationEvents.workspaceId, workspaceId),
7411
7857
  eq12(workspaceInstructionPolicyActivationEvents.kind, target.kind),
7412
7858
  eq12(workspaceInstructionPolicyActivationEvents.scope, target.scope),
7413
- target.roleKey === null ? isNull3(workspaceInstructionPolicyActivationEvents.roleKey) : eq12(workspaceInstructionPolicyActivationEvents.roleKey, target.roleKey)
7859
+ target.roleKey === null ? isNull4(workspaceInstructionPolicyActivationEvents.roleKey) : eq12(workspaceInstructionPolicyActivationEvents.roleKey, target.roleKey)
7414
7860
  ];
7415
7861
  }
7416
7862
  async function lockWorkspace(db, input) {
@@ -7434,6 +7880,65 @@ async function getRevisionInTransaction(db, workspaceId, revisionId) {
7434
7880
  ).limit(1);
7435
7881
  return row ?? null;
7436
7882
  }
7883
+ async function getRevisionByOperationInTransaction(db, workspaceId, operationId) {
7884
+ const [row] = await db.select().from(workspaceInstructionPolicyRevisions).where(
7885
+ and12(
7886
+ eq12(workspaceInstructionPolicyRevisions.workspaceId, workspaceId),
7887
+ or3(
7888
+ eq12(workspaceInstructionPolicyRevisions.operationId, operationId),
7889
+ and12(
7890
+ isNull4(workspaceInstructionPolicyRevisions.operationId),
7891
+ eq12(workspaceInstructionPolicyRevisions.id, operationId)
7892
+ )
7893
+ )
7894
+ )
7895
+ ).limit(1);
7896
+ return row ?? null;
7897
+ }
7898
+ async function getEventByOperationInTransaction(db, workspaceId, operationId) {
7899
+ const [row] = await db.select().from(workspaceInstructionPolicyActivationEvents).where(
7900
+ and12(
7901
+ eq12(workspaceInstructionPolicyActivationEvents.workspaceId, workspaceId),
7902
+ or3(
7903
+ eq12(workspaceInstructionPolicyActivationEvents.operationId, operationId),
7904
+ and12(
7905
+ isNull4(workspaceInstructionPolicyActivationEvents.operationId),
7906
+ eq12(workspaceInstructionPolicyActivationEvents.id, operationId)
7907
+ )
7908
+ )
7909
+ )
7910
+ ).limit(1);
7911
+ return row ?? null;
7912
+ }
7913
+ async function getOnboardingProposalByOperationInTransaction(db, workspaceId, operationId) {
7914
+ const [row] = await db.select().from(workspaceInstructionPolicyOnboardingProposals).where(
7915
+ and12(
7916
+ eq12(workspaceInstructionPolicyOnboardingProposals.workspaceId, workspaceId),
7917
+ eq12(workspaceInstructionPolicyOnboardingProposals.operationId, operationId)
7918
+ )
7919
+ ).limit(1);
7920
+ return row ?? null;
7921
+ }
7922
+ async function getOnboardingProposalBySourceVersionInTransaction(db, input) {
7923
+ const [row] = await db.select().from(workspaceInstructionPolicyOnboardingProposals).where(
7924
+ and12(
7925
+ eq12(workspaceInstructionPolicyOnboardingProposals.workspaceId, input.workspaceId),
7926
+ eq12(workspaceInstructionPolicyOnboardingProposals.kind, input.kind),
7927
+ eq12(workspaceInstructionPolicyOnboardingProposals.scope, input.scope),
7928
+ input.roleKey === null ? isNull4(workspaceInstructionPolicyOnboardingProposals.roleKey) : eq12(workspaceInstructionPolicyOnboardingProposals.roleKey, input.roleKey),
7929
+ eq12(workspaceInstructionPolicyOnboardingProposals.sourceId, input.sourceId),
7930
+ eq12(workspaceInstructionPolicyOnboardingProposals.sourceVersion, input.sourceVersion)
7931
+ )
7932
+ ).limit(1);
7933
+ return row ?? null;
7934
+ }
7935
+ async function resolveOnboardingProposalInTransaction(db, row) {
7936
+ const draftRow = await getRevisionInTransaction(db, row.workspaceId, row.draftRevisionId);
7937
+ if (!draftRow) {
7938
+ throw new Error("Workspace instruction-policy onboarding proposal lost its draft revision");
7939
+ }
7940
+ return onboardingProposalFromRow(row, draftRow);
7941
+ }
7437
7942
  async function getHeadInTransaction(db, workspaceId, target) {
7438
7943
  const [row] = await db.select().from(workspaceInstructionPolicyHeads).where(and12(...headTargetConditions(workspaceId, target))).for("update").limit(1);
7439
7944
  return row ?? null;
@@ -7441,7 +7946,24 @@ async function getHeadInTransaction(db, workspaceId, target) {
7441
7946
  function sameTarget(left, right) {
7442
7947
  return left.kind === right.kind && left.scope === right.scope && left.roleKey === right.roleKey;
7443
7948
  }
7949
+ function draftReceiptMatches(row, input) {
7950
+ return row.createdBySubjectId === input.createdBySubjectId && row.kind === input.kind && row.scope === input.scope && row.roleKey === input.roleKey && row.content === input.content && row.provenanceSource === input.provenanceSource && row.provenanceSourceId === input.provenanceSourceId && row.supersedesRevisionId === input.supersedesRevisionId;
7951
+ }
7444
7952
  async function createDraftInTransaction(db, input) {
7953
+ if (await getEventByOperationInTransaction(db, input.workspaceId, input.operationId)) {
7954
+ throw new WorkspaceInstructionPolicyOperationReuseError();
7955
+ }
7956
+ const existing = await getRevisionByOperationInTransaction(
7957
+ db,
7958
+ input.workspaceId,
7959
+ input.operationId
7960
+ );
7961
+ if (existing) {
7962
+ if (existing.requestFingerprint === null ? !draftReceiptMatches(existing, input) : existing.requestFingerprint !== input.requestFingerprint) {
7963
+ throw new WorkspaceInstructionPolicyOperationReuseError();
7964
+ }
7965
+ return revisionFromRow(existing);
7966
+ }
7445
7967
  if (input.supersedesRevisionId !== null) {
7446
7968
  const superseded = await getRevisionInTransaction(
7447
7969
  db,
@@ -7455,6 +7977,8 @@ async function createDraftInTransaction(db, input) {
7455
7977
  }
7456
7978
  }
7457
7979
  const [created] = await db.insert(workspaceInstructionPolicyRevisions).values({
7980
+ operationId: input.operationId,
7981
+ requestFingerprint: input.requestFingerprint,
7458
7982
  accountId: input.accountId,
7459
7983
  workspaceId: input.workspaceId,
7460
7984
  kind: input.kind,
@@ -7466,26 +7990,57 @@ async function createDraftInTransaction(db, input) {
7466
7990
  provenanceSourceId: input.provenanceSourceId,
7467
7991
  supersedesRevisionId: input.supersedesRevisionId,
7468
7992
  createdBySubjectId: input.createdBySubjectId
7469
- }).returning();
7470
- if (!created) throw new Error("Workspace instruction-policy draft was not created");
7993
+ }).onConflictDoNothing().returning();
7994
+ if (!created) {
7995
+ const concurrent = await getRevisionByOperationInTransaction(
7996
+ db,
7997
+ input.workspaceId,
7998
+ input.operationId
7999
+ );
8000
+ if (!concurrent || concurrent.requestFingerprint !== input.requestFingerprint) {
8001
+ throw new WorkspaceInstructionPolicyOperationReuseError();
8002
+ }
8003
+ return revisionFromRow(concurrent);
8004
+ }
7471
8005
  return revisionFromRow(created);
7472
8006
  }
7473
8007
  async function createWorkspaceInstructionPolicyDraft(db, input) {
8008
+ const request = { ...input, operationId: input.operationId ?? randomUUID() };
8009
+ const normalized = { ...request, requestFingerprint: draftRequestFingerprint(request) };
7474
8010
  return await withRlsContext(
7475
8011
  db,
7476
8012
  { accountId: input.accountId, workspaceId: input.workspaceId },
7477
8013
  async (scopedDb) => {
7478
8014
  await lockWorkspace(scopedDb, input);
7479
- return await createDraftInTransaction(scopedDb, input);
8015
+ return await createDraftInTransaction(scopedDb, normalized);
7480
8016
  }
7481
8017
  );
7482
8018
  }
7483
8019
  async function importLegacyWorkspaceInstructionPolicyDraft(db, input) {
8020
+ const request = { ...input, operationId: input.operationId ?? randomUUID() };
8021
+ const normalized = {
8022
+ ...request,
8023
+ requestFingerprint: importLegacyRequestFingerprint(request)
8024
+ };
7484
8025
  return await withRlsContext(
7485
8026
  db,
7486
8027
  { accountId: input.accountId, workspaceId: input.workspaceId },
7487
8028
  async (scopedDb) => {
7488
8029
  const workspace = await lockWorkspace(scopedDb, input);
8030
+ if (await getEventByOperationInTransaction(scopedDb, input.workspaceId, normalized.operationId)) {
8031
+ throw new WorkspaceInstructionPolicyOperationReuseError();
8032
+ }
8033
+ const existing = await getRevisionByOperationInTransaction(
8034
+ scopedDb,
8035
+ input.workspaceId,
8036
+ normalized.operationId
8037
+ );
8038
+ if (existing) {
8039
+ if (existing.requestFingerprint === null ? existing.createdBySubjectId !== input.createdBySubjectId || existing.kind !== "charter" || existing.scope !== "global" || existing.roleKey !== null || existing.provenanceSource !== "legacy_import" || existing.provenanceSourceId !== "workspaces.agent_instructions" || existing.supersedesRevisionId !== input.supersedesRevisionId : existing.requestFingerprint !== normalized.requestFingerprint) {
8040
+ throw new WorkspaceInstructionPolicyOperationReuseError();
8041
+ }
8042
+ return revisionFromRow(existing);
8043
+ }
7489
8044
  if (workspace.agentInstructions === null) {
7490
8045
  throw new WorkspaceInstructionPolicyLegacyUnavailableError();
7491
8046
  }
@@ -7495,7 +8050,7 @@ async function importLegacyWorkspaceInstructionPolicyDraft(db, input) {
7495
8050
  );
7496
8051
  }
7497
8052
  return await createDraftInTransaction(scopedDb, {
7498
- ...input,
8053
+ ...normalized,
7499
8054
  kind: "charter",
7500
8055
  scope: "global",
7501
8056
  roleKey: null,
@@ -7506,6 +8061,175 @@ async function importLegacyWorkspaceInstructionPolicyDraft(db, input) {
7506
8061
  }
7507
8062
  );
7508
8063
  }
8064
+ async function createWorkspaceInstructionPolicyOnboardingProposal(db, input) {
8065
+ if (input.content.trim().length === 0) {
8066
+ throw new WorkspaceInstructionPolicyOnboardingProposalContentError(
8067
+ "WORKSPACE_INSTRUCTION_POLICY_ONBOARDING_PROPOSAL_EMPTY"
8068
+ );
8069
+ }
8070
+ if (input.content.length > WORKSPACE_INSTRUCTION_POLICY_CONTENT_MAX_CHARS) {
8071
+ throw new WorkspaceInstructionPolicyOnboardingProposalContentError(
8072
+ "WORKSPACE_INSTRUCTION_POLICY_ONBOARDING_PROPOSAL_OVERSIZED"
8073
+ );
8074
+ }
8075
+ const request = {
8076
+ ...input,
8077
+ operationId: input.operationId ?? randomUUID(),
8078
+ sourceId: input.sourceId.trim(),
8079
+ sourceVersion: input.sourceVersion.trim()
8080
+ };
8081
+ const normalized = {
8082
+ ...request,
8083
+ requestFingerprint: onboardingProposalRequestFingerprint(request)
8084
+ };
8085
+ return await withRlsContext(
8086
+ db,
8087
+ { accountId: input.accountId, workspaceId: input.workspaceId },
8088
+ async (scopedDb) => {
8089
+ await lockWorkspace(scopedDb, input);
8090
+ const existing = await getOnboardingProposalByOperationInTransaction(
8091
+ scopedDb,
8092
+ input.workspaceId,
8093
+ normalized.operationId
8094
+ );
8095
+ if (existing) {
8096
+ if (existing.requestFingerprint !== normalized.requestFingerprint) {
8097
+ throw new WorkspaceInstructionPolicyOperationReuseError();
8098
+ }
8099
+ return await resolveOnboardingProposalInTransaction(scopedDb, existing);
8100
+ }
8101
+ if (await getEventByOperationInTransaction(
8102
+ scopedDb,
8103
+ input.workspaceId,
8104
+ normalized.operationId
8105
+ ) || await getRevisionByOperationInTransaction(
8106
+ scopedDb,
8107
+ input.workspaceId,
8108
+ normalized.operationId
8109
+ )) {
8110
+ throw new WorkspaceInstructionPolicyOperationReuseError();
8111
+ }
8112
+ const target = {
8113
+ kind: normalized.kind,
8114
+ scope: normalized.scope,
8115
+ roleKey: normalized.roleKey
8116
+ };
8117
+ const currentRow = await getHeadInTransaction(scopedDb, input.workspaceId, target);
8118
+ const currentHead = currentRow ? headFromRow(currentRow) : null;
8119
+ if ((currentHead?.revisionId ?? null) !== normalized.expectedCurrentRevisionId || (currentHead?.activationVersion ?? 0) !== normalized.expectedActivationVersion) {
8120
+ throw new WorkspaceInstructionPolicyOnboardingProposalStaleError(currentHead);
8121
+ }
8122
+ const sourceConflict = await getOnboardingProposalBySourceVersionInTransaction(
8123
+ scopedDb,
8124
+ normalized
8125
+ );
8126
+ if (sourceConflict) {
8127
+ throw new WorkspaceInstructionPolicyOnboardingProposalConflictError(
8128
+ sourceConflict.id,
8129
+ sourceConflict.draftRevisionId
8130
+ );
8131
+ }
8132
+ const proposalId = randomUUID();
8133
+ const draft = await createDraftInTransaction(scopedDb, {
8134
+ operationId: normalized.operationId,
8135
+ requestFingerprint: normalized.requestFingerprint,
8136
+ accountId: normalized.accountId,
8137
+ workspaceId: normalized.workspaceId,
8138
+ kind: normalized.kind,
8139
+ scope: normalized.scope,
8140
+ roleKey: normalized.roleKey,
8141
+ content: normalized.content,
8142
+ provenanceSource: "onboarding",
8143
+ provenanceSourceId: proposalId,
8144
+ supersedesRevisionId: currentHead?.revisionId ?? null,
8145
+ createdBySubjectId: normalized.createdBySubjectId
8146
+ });
8147
+ const createdAt = /* @__PURE__ */ new Date();
8148
+ const [created] = await scopedDb.insert(workspaceInstructionPolicyOnboardingProposals).values({
8149
+ id: proposalId,
8150
+ operationId: normalized.operationId,
8151
+ requestFingerprint: normalized.requestFingerprint,
8152
+ accountId: normalized.accountId,
8153
+ workspaceId: normalized.workspaceId,
8154
+ kind: normalized.kind,
8155
+ scope: normalized.scope,
8156
+ roleKey: normalized.roleKey,
8157
+ sourceId: normalized.sourceId,
8158
+ sourceVersion: normalized.sourceVersion,
8159
+ confidenceBps: normalized.confidenceBps,
8160
+ baselineRevisionId: currentHead?.revisionId ?? null,
8161
+ baselineRevision: currentHead?.revision ?? null,
8162
+ baselineContentHash: currentHead?.contentHash ?? null,
8163
+ baselineActivationVersion: currentHead?.activationVersion ?? 0,
8164
+ baselineActivatedAt: currentHead ? new Date(currentHead.activatedAt) : null,
8165
+ draftRevisionId: draft.id,
8166
+ draftRevision: draft.revision,
8167
+ draftContentHash: draft.contentHash,
8168
+ status: "proposed",
8169
+ createdBySubjectId: normalized.createdBySubjectId,
8170
+ createdAt
8171
+ }).onConflictDoNothing().returning();
8172
+ if (created) {
8173
+ const draftRow = await getRevisionInTransaction(scopedDb, input.workspaceId, draft.id);
8174
+ if (!draftRow) throw new Error("Onboarding proposal draft was not recorded");
8175
+ return onboardingProposalFromRow(created, draftRow);
8176
+ }
8177
+ const concurrentOperation = await getOnboardingProposalByOperationInTransaction(
8178
+ scopedDb,
8179
+ input.workspaceId,
8180
+ normalized.operationId
8181
+ );
8182
+ if (concurrentOperation) {
8183
+ if (concurrentOperation.requestFingerprint !== normalized.requestFingerprint) {
8184
+ throw new WorkspaceInstructionPolicyOperationReuseError();
8185
+ }
8186
+ return await resolveOnboardingProposalInTransaction(scopedDb, concurrentOperation);
8187
+ }
8188
+ const concurrentSource = await getOnboardingProposalBySourceVersionInTransaction(
8189
+ scopedDb,
8190
+ normalized
8191
+ );
8192
+ if (concurrentSource) {
8193
+ throw new WorkspaceInstructionPolicyOnboardingProposalConflictError(
8194
+ concurrentSource.id,
8195
+ concurrentSource.draftRevisionId
8196
+ );
8197
+ }
8198
+ throw new Error("Workspace instruction-policy onboarding proposal was not created");
8199
+ }
8200
+ );
8201
+ }
8202
+ async function listWorkspaceInstructionPolicyOnboardingProposals(db, workspaceId, query) {
8203
+ return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
8204
+ const rows = await scopedDb.select().from(workspaceInstructionPolicyOnboardingProposals).where(eq12(workspaceInstructionPolicyOnboardingProposals.workspaceId, workspaceId)).orderBy(
8205
+ desc4(workspaceInstructionPolicyOnboardingProposals.createdAt),
8206
+ desc4(workspaceInstructionPolicyOnboardingProposals.id)
8207
+ ).limit(query.limit + 1);
8208
+ const truncated = rows.length > query.limit;
8209
+ const page = rows.slice(0, query.limit);
8210
+ if (page.length === 0) return { proposals: [], truncated };
8211
+ const revisions = await scopedDb.select().from(workspaceInstructionPolicyRevisions).where(
8212
+ and12(
8213
+ eq12(workspaceInstructionPolicyRevisions.workspaceId, workspaceId),
8214
+ inArray7(
8215
+ workspaceInstructionPolicyRevisions.id,
8216
+ page.map((proposal) => proposal.draftRevisionId)
8217
+ )
8218
+ )
8219
+ );
8220
+ const revisionsById = new Map(revisions.map((revision) => [revision.id, revision]));
8221
+ return {
8222
+ proposals: page.map((proposal) => {
8223
+ const draft = revisionsById.get(proposal.draftRevisionId);
8224
+ if (!draft) {
8225
+ throw new Error("Workspace instruction-policy onboarding proposal lost its draft");
8226
+ }
8227
+ return onboardingProposalFromRow(proposal, draft);
8228
+ }),
8229
+ truncated
8230
+ };
8231
+ });
8232
+ }
7509
8233
  function listFilterConditions(workspaceId, query) {
7510
8234
  const conditions = [
7511
8235
  eq12(workspaceInstructionPolicyRevisions.workspaceId, workspaceId)
@@ -7518,7 +8242,7 @@ function listFilterConditions(workspaceId, query) {
7518
8242
  }
7519
8243
  if (query.roleKey !== void 0) {
7520
8244
  conditions.push(
7521
- query.roleKey === null ? isNull3(workspaceInstructionPolicyRevisions.roleKey) : eq12(workspaceInstructionPolicyRevisions.roleKey, query.roleKey)
8245
+ query.roleKey === null ? isNull4(workspaceInstructionPolicyRevisions.roleKey) : eq12(workspaceInstructionPolicyRevisions.roleKey, query.roleKey)
7522
8246
  );
7523
8247
  }
7524
8248
  if (query.afterRevision !== void 0) {
@@ -7619,11 +8343,27 @@ async function diffWorkspaceInstructionPolicyRevisions(db, workspaceId, input) {
7619
8343
  });
7620
8344
  }
7621
8345
  async function changeActiveRevision(db, input) {
8346
+ const requestFingerprint = activeRevisionRequestFingerprint(input);
7622
8347
  return await withRlsContext(
7623
8348
  db,
7624
8349
  { accountId: input.accountId, workspaceId: input.workspaceId },
7625
8350
  async (scopedDb) => {
7626
8351
  await lockWorkspace(scopedDb, input);
8352
+ if (await getRevisionByOperationInTransaction(scopedDb, input.workspaceId, input.operationId)) {
8353
+ throw new WorkspaceInstructionPolicyOperationReuseError();
8354
+ }
8355
+ const existingEvent = await getEventByOperationInTransaction(
8356
+ scopedDb,
8357
+ input.workspaceId,
8358
+ input.operationId
8359
+ );
8360
+ if (existingEvent) {
8361
+ const legacyRequestMatches = hasOwnField(input, "expectedCurrentRevisionId") && !hasOwnField(input, "expectedActivationVersion") && existingEvent.type === input.type && existingEvent.newRevisionId === input.targetRevisionId && existingEvent.oldRevisionId === input.expectedCurrentRevisionId && existingEvent.actorSubjectId === input.actorSubjectId && existingEvent.reason === input.reason;
8362
+ if (existingEvent.requestFingerprint === null ? !legacyRequestMatches : existingEvent.requestFingerprint !== requestFingerprint) {
8363
+ throw new WorkspaceInstructionPolicyOperationReuseError();
8364
+ }
8365
+ return { head: headFromEventRow(existingEvent), event: eventFromRow(existingEvent) };
8366
+ }
7627
8367
  const targetRow = await getRevisionInTransaction(
7628
8368
  scopedDb,
7629
8369
  input.workspaceId,
@@ -7638,7 +8378,7 @@ async function changeActiveRevision(db, input) {
7638
8378
  };
7639
8379
  const currentRow = await getHeadInTransaction(scopedDb, input.workspaceId, targetIdentity);
7640
8380
  const currentHead = currentRow ? headFromRow(currentRow) : null;
7641
- if ((currentHead?.revisionId ?? null) !== input.expectedCurrentRevisionId) {
8381
+ if ((currentHead?.revisionId ?? null) !== input.expectedCurrentRevisionId || input.expectedActivationVersion !== void 0 && (currentHead?.activationVersion ?? 0) !== input.expectedActivationVersion) {
7642
8382
  throw new WorkspaceInstructionPolicyConflictError(currentHead);
7643
8383
  }
7644
8384
  if (currentHead?.revisionId === target.id) {
@@ -7667,6 +8407,8 @@ async function changeActiveRevision(db, input) {
7667
8407
  const activationVersion = (currentHead?.activationVersion ?? 0) + 1;
7668
8408
  const createdAt = /* @__PURE__ */ new Date();
7669
8409
  const [eventRow] = await scopedDb.insert(workspaceInstructionPolicyActivationEvents).values({
8410
+ operationId: input.operationId,
8411
+ requestFingerprint,
7670
8412
  accountId: input.accountId,
7671
8413
  workspaceId: input.workspaceId,
7672
8414
  ...targetIdentity,
@@ -7712,12 +8454,17 @@ async function changeActiveRevision(db, input) {
7712
8454
  async function activateWorkspaceInstructionPolicyRevision(db, input) {
7713
8455
  return await changeActiveRevision(db, {
7714
8456
  ...input,
8457
+ operationId: input.operationId ?? randomUUID(),
7715
8458
  targetRevisionId: input.revisionId,
7716
8459
  type: "activate"
7717
8460
  });
7718
8461
  }
7719
8462
  async function rollbackWorkspaceInstructionPolicyRevision(db, input) {
7720
- return await changeActiveRevision(db, { ...input, type: "rollback" });
8463
+ return await changeActiveRevision(db, {
8464
+ ...input,
8465
+ operationId: input.operationId ?? randomUUID(),
8466
+ type: "rollback"
8467
+ });
7721
8468
  }
7722
8469
  async function getOrCreateWorkspaceInstructionPolicySnapshot(db, claims) {
7723
8470
  try {
@@ -7800,16 +8547,17 @@ import {
7800
8547
  PREFERENCE_REGISTRY_DESCRIPTOR_MAX_COUNT,
7801
8548
  PREFERENCE_REGISTRY_DESCRIPTOR_MAX_UTF8_BYTES,
7802
8549
  PREFERENCE_REGISTRY_TITLE_MAX_CHARS,
8550
+ PreferenceRegistryDescriptor,
7803
8551
  PreferenceRegistryDetailResponse,
7804
8552
  PreferenceRegistryEvent,
7805
8553
  PreferenceRegistryFullContent,
7806
8554
  PreferenceRegistryListResponse,
7807
8555
  PreferenceRegistryRecord,
7808
8556
  PreferenceRegistryRevisionSummary,
7809
- PreferenceRegistrySnapshot,
8557
+ PreferenceRegistrySnapshot as PreferenceRegistrySnapshot2,
7810
8558
  PreferenceRegistryScopeTarget
7811
8559
  } from "@opengeni/contracts";
7812
- import { and as and13, asc as asc7, desc as desc5, eq as eq13, gt as gt3, inArray as inArray8, isNull as isNull4, lte, or as or2, sql as sql9 } from "drizzle-orm";
8560
+ import { and as and13, asc as asc7, desc as desc5, eq as eq13, gt as gt4, inArray as inArray8, isNull as isNull5, lte, or as or4, sql as sql9 } from "drizzle-orm";
7813
8561
  var importedSources = /* @__PURE__ */ new Set([
7814
8562
  "knowledge_proposal",
7815
8563
  "imported_document",
@@ -8120,9 +8868,9 @@ async function listPreferenceRegistryScoped(db, input) {
8120
8868
  if (input.status === "active") {
8121
8869
  conditions.push(
8122
8870
  eq13(preferenceRegistryPreferences.status, "active"),
8123
- or2(
8124
- isNull4(preferenceRegistryRevisions.expiresAt),
8125
- gt3(preferenceRegistryRevisions.expiresAt, now)
8871
+ or4(
8872
+ isNull5(preferenceRegistryRevisions.expiresAt),
8873
+ gt4(preferenceRegistryRevisions.expiresAt, now)
8126
8874
  )
8127
8875
  );
8128
8876
  } else if (input.status === "expired") {
@@ -8162,6 +8910,81 @@ async function listPreferenceRegistry(db, input) {
8162
8910
  return await listPreferenceRegistryScoped(scopedDb, input);
8163
8911
  });
8164
8912
  }
8913
+ async function getCurrentPreferenceRegistryGovernanceMetadata(db, input) {
8914
+ return await withWorkspaceSubjectRls(db, input.workspaceId, input.subjectId, async (scopedDb) => {
8915
+ const rows = await scopedDb.select({
8916
+ preference: preferenceRegistryPreferences,
8917
+ revision: preferenceRegistryRevisions
8918
+ }).from(preferenceRegistryPreferences).innerJoin(
8919
+ preferenceRegistryRevisions,
8920
+ and13(
8921
+ eq13(
8922
+ preferenceRegistryRevisions.id,
8923
+ preferenceRegistryPreferences.activeRevisionId
8924
+ ),
8925
+ eq13(
8926
+ preferenceRegistryRevisions.accountId,
8927
+ preferenceRegistryPreferences.accountId
8928
+ )
8929
+ )
8930
+ ).where(
8931
+ and13(
8932
+ eq13(preferenceRegistryPreferences.status, "active"),
8933
+ or4(
8934
+ isNull5(preferenceRegistryRevisions.expiresAt),
8935
+ gt4(preferenceRegistryRevisions.expiresAt, sql9`transaction_timestamp()`)
8936
+ )
8937
+ )
8938
+ ).orderBy(
8939
+ sql9`case ${preferenceRegistryPreferences.scope}
8940
+ when 'organization' then 0
8941
+ when 'workspace' then 1
8942
+ when 'user' then 2
8943
+ else 3
8944
+ end`,
8945
+ desc5(preferenceRegistryRevisions.precedenceRank),
8946
+ asc7(preferenceRegistryPreferences.stableKey),
8947
+ asc7(preferenceRegistryPreferences.id)
8948
+ ).limit(PREFERENCE_REGISTRY_DESCRIPTOR_MAX_COUNT + 1);
8949
+ const bounded = boundPreferenceRegistryDescriptors(
8950
+ rows.map(
8951
+ ({ preference, revision }) => PreferenceRegistryDescriptor.parse({
8952
+ id: preference.id,
8953
+ stableKey: preference.stableKey,
8954
+ title: revision.title,
8955
+ description: revision.description,
8956
+ scope: preference.scope,
8957
+ activeVersion: preference.activationVersion,
8958
+ revisionId: revision.id,
8959
+ contentHash: revision.contentHash,
8960
+ precedence: {
8961
+ tier: preference.scope,
8962
+ rank: revision.precedenceRank,
8963
+ conflictStrategy: revision.conflictStrategy,
8964
+ conflictsWith: revision.conflictsWith
8965
+ },
8966
+ provenance: {
8967
+ source: revision.provenanceSource,
8968
+ sourceIdHash: revision.provenanceSourceId ? contentHash2(revision.provenanceSourceId) : null,
8969
+ trust: revision.trust
8970
+ },
8971
+ expiresAt: revision.expiresAt ? iso2(revision.expiresAt) : null,
8972
+ retrievalHandle: `preference://${preference.id}/revisions/${revision.id}?sha256=${revision.contentHash}`
8973
+ })
8974
+ )
8975
+ );
8976
+ return {
8977
+ descriptors: bounded.descriptors.map((descriptor) => ({
8978
+ id: descriptor.id,
8979
+ revisionId: descriptor.revisionId,
8980
+ contentHash: descriptor.contentHash,
8981
+ activeVersion: descriptor.activeVersion,
8982
+ scope: descriptor.scope
8983
+ })),
8984
+ truncated: bounded.truncated
8985
+ };
8986
+ });
8987
+ }
8165
8988
  async function listPreferenceRegistryForAttempt(db, input) {
8166
8989
  return await withPreferenceRegistryAttemptAuthority(db, input, async (scopedDb) => {
8167
8990
  return await listPreferenceRegistryScoped(scopedDb, input);
@@ -8382,9 +9205,9 @@ async function supersedePreferenceRegistry(db, input) {
8382
9205
  and13(
8383
9206
  eq13(preferenceRegistryRevisions.id, replacement.activeRevisionId),
8384
9207
  eq13(preferenceRegistryRevisions.preferenceId, replacement.id),
8385
- or2(
8386
- isNull4(preferenceRegistryRevisions.expiresAt),
8387
- gt3(preferenceRegistryRevisions.expiresAt, sql9`transaction_timestamp()`)
9208
+ or4(
9209
+ isNull5(preferenceRegistryRevisions.expiresAt),
9210
+ gt4(preferenceRegistryRevisions.expiresAt, sql9`transaction_timestamp()`)
8388
9211
  )
8389
9212
  )
8390
9213
  ).limit(1);
@@ -8586,7 +9409,7 @@ async function getOrCreatePreferenceRegistrySnapshot(db, claims) {
8586
9409
  "Preference snapshot authority conflicts with the accepted human attempt"
8587
9410
  );
8588
9411
  }
8589
- return PreferenceRegistrySnapshot.parse({
9412
+ return PreferenceRegistrySnapshot2.parse({
8590
9413
  ...snapshot,
8591
9414
  createdAt: iso2(snapshot.createdAt)
8592
9415
  });
@@ -11970,7 +12793,7 @@ var defaultDeps2 = {
11970
12793
  var inflight2 = /* @__PURE__ */ new Map();
11971
12794
  var REFRESH_WINDOW_MS = 6e4;
11972
12795
  var CONNECTION_REFRESH_TIMEOUT_MS = 1e4;
11973
- function buildConnectionTokenResolver(db, settings, deps = defaultDeps2) {
12796
+ function buildConnectionTokenResolver(db, settings, deps = defaultDeps2, options = {}) {
11974
12797
  const load = async (input) => {
11975
12798
  const subjectOwned = input.connectionRef.subjectScope === "subject";
11976
12799
  if (subjectOwned && !input.subjectId) {
@@ -12033,6 +12856,7 @@ function buildConnectionTokenResolver(db, settings, deps = defaultDeps2) {
12033
12856
  status: "ok",
12034
12857
  headers,
12035
12858
  connectionId: cred.id,
12859
+ connectionVersion: cred.version,
12036
12860
  expiresAt: cred.expiresAt
12037
12861
  };
12038
12862
  };
@@ -12041,7 +12865,7 @@ function buildConnectionTokenResolver(db, settings, deps = defaultDeps2) {
12041
12865
  if (!key) {
12042
12866
  throw new Error("OPENGENI_ENVIRONMENTS_ENCRYPTION_KEY is not configured");
12043
12867
  }
12044
- const refreshed = await deps.refresh(cred, ref, settings);
12868
+ const refreshed = await deps.refresh(cred, ref, settings, options.refreshTransport);
12045
12869
  const refreshRecord = {
12046
12870
  id: cred.id,
12047
12871
  version: cred.version,
@@ -12117,17 +12941,29 @@ function buildConnectionTokenResolver(db, settings, deps = defaultDeps2) {
12117
12941
  cred = await refreshSingleFlight(cred, ref);
12118
12942
  } catch (error) {
12119
12943
  if (isPermanentRefreshError(error)) {
12120
- await deps.setStatus(
12121
- db,
12122
- input.workspaceId,
12123
- "needs_reauth",
12124
- error instanceof Error ? error.message : String(error),
12125
- {
12944
+ let handled = false;
12945
+ if (options.transitionPermanentRefreshFailure) {
12946
+ try {
12947
+ handled = await options.transitionPermanentRefreshFailure({
12948
+ workspaceId: cred.workspaceId,
12949
+ connectionId: cred.id,
12950
+ connectionVersion: cred.version,
12951
+ subjectId: cred.subjectId,
12952
+ providerDomain: cred.providerDomain,
12953
+ httpStatus: error.httpStatus,
12954
+ oauthErrorCode: error.oauthErrorCode
12955
+ });
12956
+ } catch {
12957
+ handled = false;
12958
+ }
12959
+ }
12960
+ if (!handled) {
12961
+ await deps.setStatus(db, input.workspaceId, "needs_reauth", error.message, {
12126
12962
  id: cred.id,
12127
12963
  version: cred.version,
12128
12964
  subjectId: cred.subjectId
12129
- }
12130
- ).catch(() => void 0);
12965
+ }).catch(() => void 0);
12966
+ }
12131
12967
  }
12132
12968
  return authNeeded(ref, "refresh_failed", cred.id);
12133
12969
  }
@@ -12182,10 +13018,12 @@ function canonicalResource(value) {
12182
13018
  }
12183
13019
  var ConnectionRefreshHttpError = class extends Error {
12184
13020
  httpStatus;
12185
- constructor(httpStatus) {
13021
+ oauthErrorCode;
13022
+ constructor(httpStatus, oauthErrorCode = null) {
12186
13023
  super(`connection refresh failed with HTTP ${httpStatus}`);
12187
13024
  this.name = "ConnectionRefreshHttpError";
12188
13025
  this.httpStatus = httpStatus;
13026
+ this.oauthErrorCode = oauthErrorCode;
12189
13027
  }
12190
13028
  };
12191
13029
  function isPermanentRefreshError(error) {
@@ -12317,8 +13155,10 @@ async function refreshOAuthConnectionCredential(cred, ref, settings, transportOp
12317
13155
  throw new ConnectionRefreshHttpError(response.status);
12318
13156
  }
12319
13157
  if (!response.ok) {
12320
- await cancelResponseBody(response);
12321
- throw new ConnectionRefreshHttpError(response.status);
13158
+ throw new ConnectionRefreshHttpError(
13159
+ response.status,
13160
+ await readOAuthRefreshErrorCode(response)
13161
+ );
12322
13162
  }
12323
13163
  const payload = await readResponseJsonBounded(
12324
13164
  response,
@@ -12347,6 +13187,20 @@ async function refreshOAuthConnectionCredential(cred, ref, settings, transportOp
12347
13187
  ...scopeText ? { grantedScopes: scopeText.split(/\s+/).filter(Boolean) } : {}
12348
13188
  };
12349
13189
  }
13190
+ async function readOAuthRefreshErrorCode(response) {
13191
+ try {
13192
+ const payload = await readResponseJsonBounded(
13193
+ response,
13194
+ OAUTH_MAX_RESPONSE_BYTES,
13195
+ "OAuth refresh error response"
13196
+ );
13197
+ const code = stringValue(payload.error);
13198
+ return code && /^[a-z0-9_.-]{1,64}$/i.test(code) ? code : null;
13199
+ } catch {
13200
+ await cancelResponseBody(response);
13201
+ return null;
13202
+ }
13203
+ }
12350
13204
  function expiresAtFromTokenResponse(payload, fallback) {
12351
13205
  const expiresAt = stringValue(payload.expires_at);
12352
13206
  if (expiresAt) {
@@ -12380,7 +13234,7 @@ async function cancelResponseBody(response) {
12380
13234
  }
12381
13235
 
12382
13236
  // src/workspace-artifacts.ts
12383
- import { and as and16, desc as desc7, eq as eq16, lt as lt3, or as or3, sql as sql13 } from "drizzle-orm";
13237
+ import { and as and16, desc as desc7, eq as eq16, lt as lt3, or as or5, sql as sql13 } from "drizzle-orm";
12384
13238
  var WorkspaceArtifactNotFoundError = class extends Error {
12385
13239
  name = "WorkspaceArtifactNotFoundError";
12386
13240
  };
@@ -12475,7 +13329,7 @@ async function listWorkspaceArtifacts(db, workspaceId, options = {}) {
12475
13329
  const cursor = options.cursor ? decodeListCursor(options.cursor) : null;
12476
13330
  const visibility = cursor ? and16(
12477
13331
  eq16(workspaceArtifacts.workspaceId, workspaceId),
12478
- or3(
13332
+ or5(
12479
13333
  lt3(workspaceArtifacts.updatedAt, cursor.updatedAt),
12480
13334
  and16(
12481
13335
  eq16(workspaceArtifacts.updatedAt, cursor.updatedAt),
@@ -13345,6 +14199,29 @@ async function withWorkspaceUsageLock(db, workspaceId, fn) {
13345
14199
  return await fn(scopedDb);
13346
14200
  });
13347
14201
  }
14202
+ async function resolveDocumentIndexAuthority(db, input) {
14203
+ const rows = await rawRows(
14204
+ db,
14205
+ sql14`
14206
+ select authority_kind, authority_workspace_id, authority_subject_id
14207
+ from opengeni_private.resolve_document_index_authority(
14208
+ ${input.accountId},
14209
+ ${input.workspaceId},
14210
+ ${input.documentId}
14211
+ )
14212
+ `
14213
+ );
14214
+ const row = rows[0];
14215
+ if (!row) return null;
14216
+ if (row.authority_kind !== "organization" && row.authority_kind !== "workspace" && row.authority_kind !== "personal") {
14217
+ throw new Error(`Stored document authority kind is invalid: ${row.authority_kind}`);
14218
+ }
14219
+ return {
14220
+ authorityKind: row.authority_kind,
14221
+ authorityWorkspaceId: row.authority_workspace_id,
14222
+ authoritySubjectId: row.authority_subject_id
14223
+ };
14224
+ }
13348
14225
  async function withAccountRls(db, accountId, fn) {
13349
14226
  return await withRlsContext(db, { accountId, workspaceId: null }, fn);
13350
14227
  }
@@ -13967,7 +14844,7 @@ async function upsertGitHubInstallation(db, input) {
13967
14844
  },
13968
14845
  // This legacy metadata helper cannot mutate an owner-authorized row.
13969
14846
  // New bindings use bindAuthorizedGitHubInstallationRepositories.
13970
- setWhere: isNull5(githubInstallations.authorityNonce)
14847
+ setWhere: isNull6(githubInstallations.authorityNonce)
13971
14848
  }).returning();
13972
14849
  if (!row) {
13973
14850
  throw new Error("Failed to upsert GitHub installation");
@@ -14010,7 +14887,7 @@ async function bindGitHubInstallationRepositories(db, input) {
14010
14887
  updatedAt: /* @__PURE__ */ new Date()
14011
14888
  },
14012
14889
  // Preserve the immutable authority + allowlist audit boundary.
14013
- setWhere: isNull5(githubInstallations.authorityNonce)
14890
+ setWhere: isNull6(githubInstallations.authorityNonce)
14014
14891
  }).returning();
14015
14892
  if (!row) {
14016
14893
  throw new Error("Failed to bind GitHub installation");
@@ -14463,7 +15340,7 @@ async function sumUsageQuantity(db, input) {
14463
15340
  eq17(usageEvents.eventType, input.eventType),
14464
15341
  ...input.accountId ? [eq17(usageEvents.accountId, input.accountId)] : [],
14465
15342
  ...input.workspaceId ? [eq17(usageEvents.workspaceId, input.workspaceId)] : [],
14466
- ...input.since ? [gt4(usageEvents.occurredAt, input.since)] : []
15343
+ ...input.since ? [gt5(usageEvents.occurredAt, input.since)] : []
14467
15344
  ];
14468
15345
  const [{ total } = { total: 0 }] = await scopedDb.select({
14469
15346
  total: sql14`coalesce(sum(${usageEvents.quantity}), 0)`
@@ -14619,6 +15496,20 @@ async function countScheduledTasksForWorkspace(db, workspaceId) {
14619
15496
  return Number(count);
14620
15497
  });
14621
15498
  }
15499
+ var ConnectionDisconnectIdempotencyError = class extends Error {
15500
+ code = "IDEMPOTENCY_KEY_REUSED";
15501
+ constructor() {
15502
+ super("The disconnect idempotency key was already used with different input");
15503
+ this.name = "ConnectionDisconnectIdempotencyError";
15504
+ }
15505
+ };
15506
+ var ConnectionDisconnectGenerationError = class extends Error {
15507
+ code = "CONNECTION_GENERATION_CHANGED";
15508
+ constructor() {
15509
+ super("The disconnect operation belongs to an older connection generation");
15510
+ this.name = "ConnectionDisconnectGenerationError";
15511
+ }
15512
+ };
14622
15513
  async function createFileUpload(db, input) {
14623
15514
  return await withRlsContext(
14624
15515
  db,
@@ -14674,6 +15565,25 @@ async function requireFile(db, workspaceId, fileId) {
14674
15565
  }
14675
15566
  return file;
14676
15567
  }
15568
+ async function getFiles(db, workspaceId, fileIds) {
15569
+ const ids = [...new Set(fileIds)];
15570
+ if (ids.length === 0) return [];
15571
+ return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
15572
+ const rows = await scopedDb.select().from(files).where(and17(eq17(files.workspaceId, workspaceId), inArray11(files.id, ids)));
15573
+ return rows.map(mapFile);
15574
+ });
15575
+ }
15576
+ function durableUserHistoryItem(prompt, resources) {
15577
+ const attachmentRefs = resources.filter(
15578
+ (resource) => resource.kind === "file"
15579
+ );
15580
+ return sanitizeModelPayload({
15581
+ type: "message",
15582
+ role: "user",
15583
+ content: prompt,
15584
+ ...attachmentRefs.length > 0 ? { [MODEL_ATTACHMENT_REFS_FIELD]: attachmentRefs } : {}
15585
+ });
15586
+ }
14677
15587
  async function getRetainedFileArtifact(db, workspaceId, fileId) {
14678
15588
  return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
14679
15589
  const [row] = await scopedDb.select({
@@ -15251,11 +16161,11 @@ async function upsertCapabilityCatalogItem(db, input) {
15251
16161
  async function listCapabilityCatalogItems(db, workspaceId) {
15252
16162
  return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
15253
16163
  const rows = await scopedDb.select().from(capabilityCatalogItems).where(
15254
- or4(
16164
+ or6(
15255
16165
  eq17(capabilityCatalogItems.workspaceId, workspaceId),
15256
16166
  and17(
15257
- isNull5(capabilityCatalogItems.workspaceId),
15258
- or4(
16167
+ isNull6(capabilityCatalogItems.workspaceId),
16168
+ or6(
15259
16169
  ne(capabilityCatalogItems.source, registryCapabilitySource),
15260
16170
  eq17(capabilityCatalogItems.stale, false)
15261
16171
  )
@@ -15277,9 +16187,9 @@ async function getCapabilityCatalogItem(db, workspaceId, capabilityId) {
15277
16187
  const [row] = await scopedDb.select().from(capabilityCatalogItems).where(
15278
16188
  and17(
15279
16189
  eq17(capabilityCatalogItems.id, capabilityId),
15280
- or4(
16190
+ or6(
15281
16191
  eq17(capabilityCatalogItems.workspaceId, workspaceId),
15282
- isNull5(capabilityCatalogItems.workspaceId)
16192
+ isNull6(capabilityCatalogItems.workspaceId)
15283
16193
  )
15284
16194
  )
15285
16195
  ).orderBy(asc8(sql14`(${capabilityCatalogItems.workspaceId} is null)`)).limit(1);
@@ -15387,12 +16297,12 @@ async function listEnabledMcpCapabilityServers(db, workspaceId) {
15387
16297
  }).from(capabilityInstallations).innerJoin(
15388
16298
  capabilityCatalogItems,
15389
16299
  and17(
15390
- or4(
16300
+ or6(
15391
16301
  eq17(
15392
16302
  capabilityInstallations.workspaceId,
15393
16303
  capabilityCatalogItems.workspaceId
15394
16304
  ),
15395
- isNull5(capabilityCatalogItems.workspaceId)
16305
+ isNull6(capabilityCatalogItems.workspaceId)
15396
16306
  ),
15397
16307
  eq17(capabilityInstallations.capabilityId, capabilityCatalogItems.id)
15398
16308
  )
@@ -15501,10 +16411,10 @@ var connectionMetadataColumns = {
15501
16411
  updatedAt: connections.updatedAt
15502
16412
  };
15503
16413
  function connectionSubjectVisibility(subjectId) {
15504
- return subjectId ? or4(isNull5(connections.subjectId), eq17(connections.subjectId, subjectId)) : isNull5(connections.subjectId);
16414
+ return subjectId ? or6(isNull6(connections.subjectId), eq17(connections.subjectId, subjectId)) : isNull6(connections.subjectId);
15505
16415
  }
15506
16416
  function connectionExactSubject(subjectId) {
15507
- return subjectId ? eq17(connections.subjectId, subjectId) : isNull5(connections.subjectId);
16417
+ return subjectId ? eq17(connections.subjectId, subjectId) : isNull6(connections.subjectId);
15508
16418
  }
15509
16419
  function personalSlackCanonicalConnectionOrder() {
15510
16420
  return [
@@ -15617,6 +16527,124 @@ async function updateConnection(db, input) {
15617
16527
  async (scopedDb) => await updateConnectionInScope(scopedDb, input)
15618
16528
  );
15619
16529
  }
16530
+ async function transitionConnectionStateInScope(db, input) {
16531
+ const [row] = await db.update(connections).set({
16532
+ ...input.status !== void 0 ? { status: input.status } : {},
16533
+ metadata: input.metadata,
16534
+ ...input.lastError !== void 0 ? { lastError: input.lastError } : {},
16535
+ version: sql14`${connections.version} + 1`,
16536
+ ...input.updatedBySubjectId !== void 0 ? { updatedBySubjectId: input.updatedBySubjectId } : {},
16537
+ updatedAt: /* @__PURE__ */ new Date()
16538
+ }).where(
16539
+ and17(
16540
+ eq17(connections.workspaceId, input.workspaceId),
16541
+ eq17(connections.id, input.connectionId),
16542
+ connectionSubjectVisibility(input.visibleToSubjectId),
16543
+ eq17(connections.version, input.expectedVersion)
16544
+ )
16545
+ ).returning(connectionMetadataColumns);
16546
+ return row ? mapConnectionMetadata(row) : null;
16547
+ }
16548
+ async function transitionConnectionState(db, input) {
16549
+ return await withConnectionSubjectRls(
16550
+ db,
16551
+ input.workspaceId,
16552
+ input.visibleToSubjectId,
16553
+ async (scopedDb) => await transitionConnectionStateInScope(scopedDb, input)
16554
+ );
16555
+ }
16556
+ var connectionDisconnectOperationColumns = {
16557
+ accountId: connectionDisconnectOperations.accountId,
16558
+ workspaceId: connectionDisconnectOperations.workspaceId,
16559
+ connectionId: connectionDisconnectOperations.connectionId,
16560
+ subjectId: connectionDisconnectOperations.subjectId,
16561
+ idempotencyKey: connectionDisconnectOperations.idempotencyKey,
16562
+ expectedVersion: connectionDisconnectOperations.expectedVersion,
16563
+ resultVersion: connectionDisconnectOperations.resultVersion
16564
+ };
16565
+ async function disconnectConnectionIdempotently(db, input) {
16566
+ return await withConnectionSubjectRls(
16567
+ db,
16568
+ input.workspaceId,
16569
+ input.subjectId,
16570
+ async (scopedDb) => {
16571
+ const [connectionRow] = await scopedDb.select(connectionMetadataColumns).from(connections).where(
16572
+ and17(
16573
+ eq17(connections.accountId, input.accountId),
16574
+ eq17(connections.workspaceId, input.workspaceId),
16575
+ eq17(connections.id, input.connectionId),
16576
+ eq17(connections.subjectId, input.subjectId)
16577
+ )
16578
+ ).for("update");
16579
+ if (!connectionRow) return null;
16580
+ const connection = mapConnectionMetadata(connectionRow);
16581
+ const [replayed] = await scopedDb.select(connectionDisconnectOperationColumns).from(connectionDisconnectOperations).where(
16582
+ and17(
16583
+ eq17(connectionDisconnectOperations.workspaceId, input.workspaceId),
16584
+ eq17(connectionDisconnectOperations.subjectId, input.subjectId),
16585
+ eq17(connectionDisconnectOperations.idempotencyKey, input.idempotencyKey)
16586
+ )
16587
+ ).limit(1);
16588
+ if (replayed) {
16589
+ if (replayed.accountId !== input.accountId || replayed.connectionId !== input.connectionId || replayed.expectedVersion !== input.expectedVersion) {
16590
+ throw new ConnectionDisconnectIdempotencyError();
16591
+ }
16592
+ if (connection.version !== replayed.resultVersion) {
16593
+ throw new ConnectionDisconnectGenerationError();
16594
+ }
16595
+ return connection;
16596
+ }
16597
+ if (connection.version !== input.expectedVersion) {
16598
+ throw new ConnectionDisconnectGenerationError();
16599
+ }
16600
+ const [inserted] = await scopedDb.insert(connectionDisconnectOperations).values({
16601
+ accountId: input.accountId,
16602
+ workspaceId: input.workspaceId,
16603
+ connectionId: input.connectionId,
16604
+ subjectId: input.subjectId,
16605
+ idempotencyKey: input.idempotencyKey,
16606
+ expectedVersion: input.expectedVersion,
16607
+ resultVersion: input.expectedVersion + 1
16608
+ }).onConflictDoNothing().returning(connectionDisconnectOperationColumns);
16609
+ if (!inserted) {
16610
+ const [conflictingKey] = await scopedDb.select(connectionDisconnectOperationColumns).from(connectionDisconnectOperations).where(
16611
+ and17(
16612
+ eq17(connectionDisconnectOperations.workspaceId, input.workspaceId),
16613
+ eq17(connectionDisconnectOperations.subjectId, input.subjectId),
16614
+ eq17(connectionDisconnectOperations.idempotencyKey, input.idempotencyKey)
16615
+ )
16616
+ ).limit(1);
16617
+ if (!conflictingKey || conflictingKey.accountId !== input.accountId || conflictingKey.connectionId !== input.connectionId || conflictingKey.expectedVersion !== input.expectedVersion) {
16618
+ throw new ConnectionDisconnectIdempotencyError();
16619
+ }
16620
+ if (connection.version !== conflictingKey.resultVersion) {
16621
+ throw new ConnectionDisconnectGenerationError();
16622
+ }
16623
+ return connection;
16624
+ }
16625
+ const [updated] = await scopedDb.update(connections).set({
16626
+ status: "revoked",
16627
+ metadata: input.metadata,
16628
+ ...input.lastError !== void 0 ? { lastError: input.lastError } : {},
16629
+ version: sql14`${connections.version} + 1`,
16630
+ ...input.updatedBySubjectId !== void 0 ? { updatedBySubjectId: input.updatedBySubjectId } : {},
16631
+ updatedAt: /* @__PURE__ */ new Date()
16632
+ }).where(
16633
+ and17(
16634
+ eq17(connections.accountId, input.accountId),
16635
+ eq17(connections.workspaceId, input.workspaceId),
16636
+ eq17(connections.id, input.connectionId),
16637
+ eq17(connections.subjectId, input.subjectId),
16638
+ eq17(connections.version, input.expectedVersion)
16639
+ )
16640
+ ).returning(connectionMetadataColumns);
16641
+ if (!updated) {
16642
+ throw new ConnectionDisconnectGenerationError();
16643
+ }
16644
+ return mapConnectionMetadata(updated);
16645
+ }
16646
+ );
16647
+ }
15620
16648
  async function revokeConnectionInScope(db, workspaceId, connectionId, updatedBySubjectId, expectedVersion) {
15621
16649
  const [row] = await db.update(connections).set({
15622
16650
  status: "revoked",
@@ -15645,12 +16673,18 @@ async function revokeConnectionInScope(db, workspaceId, connectionId, updatedByS
15645
16673
  ).returning(connectionMetadataColumns);
15646
16674
  return row ? mapConnectionMetadata(row) : null;
15647
16675
  }
15648
- async function revokeConnection(db, workspaceId, connectionId, updatedBySubjectId) {
16676
+ async function revokeConnection(db, workspaceId, connectionId, updatedBySubjectId, expectedVersion) {
15649
16677
  return await withConnectionSubjectRls(
15650
16678
  db,
15651
16679
  workspaceId,
15652
16680
  updatedBySubjectId,
15653
- async (scopedDb) => await revokeConnectionInScope(scopedDb, workspaceId, connectionId, updatedBySubjectId)
16681
+ async (scopedDb) => await revokeConnectionInScope(
16682
+ scopedDb,
16683
+ workspaceId,
16684
+ connectionId,
16685
+ updatedBySubjectId,
16686
+ expectedVersion
16687
+ )
15654
16688
  );
15655
16689
  }
15656
16690
  async function resolveSlackInstallationRoute(db, slackTeamId) {
@@ -15715,7 +16749,7 @@ async function enqueueSlackInteractionInbox(db, input) {
15715
16749
  const [existing] = await scopedDb.select().from(slackInteractionInbox).where(
15716
16750
  and17(
15717
16751
  eq17(slackInteractionInbox.connectionId, input.connectionId),
15718
- or4(
16752
+ or6(
15719
16753
  eq17(slackInteractionInbox.providerEventId, input.providerEventId),
15720
16754
  eq17(slackInteractionInbox.providerMessageId, input.providerMessageId)
15721
16755
  )
@@ -15929,7 +16963,7 @@ async function bindSlackInteractionSession(db, input) {
15929
16963
  eq17(slackInteractions.id, input.id),
15930
16964
  eq17(slackInteractions.owningSubjectId, input.owningSubjectId),
15931
16965
  eq17(slackInteractions.sessionReservationId, input.sessionId),
15932
- isNull5(slackInteractions.sessionId)
16966
+ isNull6(slackInteractions.sessionId)
15933
16967
  )
15934
16968
  ).returning();
15935
16969
  if (row) return mapSlackInteraction(row);
@@ -16431,8 +17465,8 @@ async function claimSlackBotPostOperation(db, input) {
16431
17465
  }).where(
16432
17466
  and17(
16433
17467
  eq17(slackBotPostOperations.id, existing.id),
16434
- or4(
16435
- isNull5(slackBotPostOperations.claimHolderId),
17468
+ or6(
17469
+ isNull6(slackBotPostOperations.claimHolderId),
16436
17470
  lte2(slackBotPostOperations.claimExpiresAt, sql14`now()`)
16437
17471
  )
16438
17472
  )
@@ -16628,7 +17662,7 @@ async function markSlackBotDeleteOperationProviderStarted(db, input) {
16628
17662
  eq17(slackBotDeleteOperations.connectionId, input.connectionId),
16629
17663
  eq17(slackBotDeleteOperations.operationId, input.operationId),
16630
17664
  eq17(slackBotDeleteOperations.claimHolderId, input.claimHolderId),
16631
- or4(
17665
+ or6(
16632
17666
  eq17(slackBotDeleteOperations.status, "pending"),
16633
17667
  eq17(slackBotDeleteOperations.status, "outcome_unknown")
16634
17668
  )
@@ -16736,7 +17770,7 @@ async function loadConnectionCredentialForBroker(db, settings, input) {
16736
17770
  "connection credential present but OPENGENI_ENVIRONMENTS_ENCRYPTION_KEY is not configured"
16737
17771
  );
16738
17772
  }
16739
- const subjectPredicate = input.allowSubjectOwned ? connectionExactSubject(input.subjectId) : isNull5(connections.subjectId);
17773
+ const subjectPredicate = input.allowSubjectOwned ? connectionExactSubject(input.subjectId) : isNull6(connections.subjectId);
16740
17774
  const conditions = [
16741
17775
  eq17(connections.workspaceId, input.workspaceId),
16742
17776
  subjectPredicate
@@ -20219,7 +21253,7 @@ async function withCodexCapacityMutation(db, input, mutate) {
20219
21253
  eq17(codexCapacityWaiters.workspaceId, input.workspaceId),
20220
21254
  eq17(codexCapacityWaiters.status, "waiting"),
20221
21255
  ...input.policyHash !== void 0 ? [
20222
- input.policyHash === null ? isNull5(codexCapacityWaiters.policyHash) : eq17(codexCapacityWaiters.policyHash, input.policyHash)
21256
+ input.policyHash === null ? isNull6(codexCapacityWaiters.policyHash) : eq17(codexCapacityWaiters.policyHash, input.policyHash)
20223
21257
  ] : []
20224
21258
  )
20225
21259
  ).returning();
@@ -20312,7 +21346,7 @@ async function supersedeCodexCapacityWaitInTransaction(tx, input) {
20312
21346
  eq17(sessionTurns.workspaceId, input.session.workspaceId),
20313
21347
  eq17(sessionTurns.id, input.blockedTurn.id),
20314
21348
  eq17(sessionTurns.status, "waiting_capacity"),
20315
- isNull5(sessionTurns.activeAttemptId),
21349
+ isNull6(sessionTurns.activeAttemptId),
20316
21350
  eq17(sessionTurns.executionGeneration, input.waiter.blockedTurnGeneration)
20317
21351
  )
20318
21352
  ).returning({ id: sessionTurns.id });
@@ -20590,7 +21624,7 @@ async function reconcileCodexCapacityWait(db, input, decide, policy) {
20590
21624
  eq17(sessionTurns.workspaceId, input.workspaceId),
20591
21625
  eq17(sessionTurns.id, blockedTurn.id),
20592
21626
  eq17(sessionTurns.status, "waiting_capacity"),
20593
- isNull5(sessionTurns.activeAttemptId),
21627
+ isNull6(sessionTurns.activeAttemptId),
20594
21628
  eq17(sessionTurns.executionGeneration, waiter.blockedTurnGeneration)
20595
21629
  )
20596
21630
  ).returning({ id: sessionTurns.id });
@@ -21411,7 +22445,7 @@ async function setInitialActiveCodexCredential(db, workspaceId, credentialId) {
21411
22445
  const rows = await scopedDb.update(codexRotationSettings).set({ activeCredentialId: credentialId, updatedAt: /* @__PURE__ */ new Date() }).where(
21412
22446
  and17(
21413
22447
  eq17(codexRotationSettings.workspaceId, workspaceId),
21414
- isNull5(codexRotationSettings.activeCredentialId)
22448
+ isNull6(codexRotationSettings.activeCredentialId)
21415
22449
  )
21416
22450
  ).returning({ id: codexRotationSettings.id });
21417
22451
  return rows.length > 0;
@@ -21560,8 +22594,8 @@ async function setSessionCodexPin(db, workspaceId, sessionId, pinnedCredentialId
21560
22594
  ];
21561
22595
  if (options.expected) {
21562
22596
  conditions.push(
21563
- options.expected.pinnedCredentialId === null ? isNull5(sessions.codexPinnedCredentialId) : eq17(sessions.codexPinnedCredentialId, options.expected.pinnedCredentialId),
21564
- options.expected.pinSource === null ? isNull5(sessions.codexPinSource) : eq17(sessions.codexPinSource, options.expected.pinSource)
22597
+ options.expected.pinnedCredentialId === null ? isNull6(sessions.codexPinnedCredentialId) : eq17(sessions.codexPinnedCredentialId, options.expected.pinnedCredentialId),
22598
+ options.expected.pinSource === null ? isNull6(sessions.codexPinSource) : eq17(sessions.codexPinSource, options.expected.pinSource)
21565
22599
  );
21566
22600
  }
21567
22601
  const updated = await scopedDb.update(sessions).set({
@@ -22911,7 +23945,7 @@ async function listSessionSpawnDenials(db, workspaceId, options = {}) {
22911
23945
  const rows = await scopedDb.select().from(sessionSpawnDenials).where(
22912
23946
  and17(
22913
23947
  eq17(sessionSpawnDenials.workspaceId, workspaceId),
22914
- options.parentSessionId === void 0 ? void 0 : options.parentSessionId === null ? isNull5(sessionSpawnDenials.parentSessionId) : eq17(sessionSpawnDenials.parentSessionId, options.parentSessionId)
23948
+ options.parentSessionId === void 0 ? void 0 : options.parentSessionId === null ? isNull6(sessionSpawnDenials.parentSessionId) : eq17(sessionSpawnDenials.parentSessionId, options.parentSessionId)
22915
23949
  )
22916
23950
  ).orderBy(desc8(sessionSpawnDenials.createdAt), desc8(sessionSpawnDenials.id)).limit(Math.max(1, Math.min(options.limit ?? 100, 1e3)));
22917
23951
  return rows.map(mapSessionSpawnDenial);
@@ -23229,7 +24263,7 @@ function sessionFilters(options) {
23229
24263
  if (Object.prototype.hasOwnProperty.call(options, "parentSessionId")) {
23230
24264
  const parentSessionId = options.parentSessionId;
23231
24265
  if (parentSessionId === null) {
23232
- filters.push(isNull5(sessions.parentSessionId));
24266
+ filters.push(isNull6(sessions.parentSessionId));
23233
24267
  } else if (parentSessionId !== void 0) {
23234
24268
  filters.push(eq17(sessions.parentSessionId, parentSessionId));
23235
24269
  }
@@ -23238,7 +24272,7 @@ function sessionFilters(options) {
23238
24272
  if (search) {
23239
24273
  const pattern = `%${search.replaceAll("\\", "\\\\").replaceAll("%", "\\%").replaceAll("_", "\\_")}%`;
23240
24274
  filters.push(
23241
- or4(ilike(sessions.title, pattern), ilike(sessions.initialMessage, pattern))
24275
+ or6(ilike(sessions.title, pattern), ilike(sessions.initialMessage, pattern))
23242
24276
  );
23243
24277
  }
23244
24278
  return filters;
@@ -23271,7 +24305,7 @@ function sessionAuthorizationScopeFilter(scope) {
23271
24305
  )
23272
24306
  select id from authorized_sessions
23273
24307
  )` : sql14`false`;
23274
- return or4(exact, descendants);
24308
+ return or6(exact, descendants);
23275
24309
  }
23276
24310
  async function sessionIdsCoveredByAuthorizationRoots(db, workspaceId, sessionIds, scope) {
23277
24311
  if (sessionIds.length === 0) return /* @__PURE__ */ new Set();
@@ -23453,7 +24487,7 @@ async function listSessionsForSubject(db, workspaceId, options) {
23453
24487
  ).where(
23454
24488
  and17(
23455
24489
  ...filters,
23456
- or4(isNull5(sessionPins.id), eq17(sessionPins.pinned, false))
24490
+ or6(isNull6(sessionPins.id), eq17(sessionPins.pinned, false))
23457
24491
  )
23458
24492
  ).orderBy(desc8(sessions.updatedAt), desc8(sessions.id)).limit(limit);
23459
24493
  pageIds = ordinaryIdRows.map((row) => row.id);
@@ -23466,14 +24500,14 @@ async function listSessionsForSubject(db, workspaceId, options) {
23466
24500
  lte2(sessionListSnapshots.expiresAt, now)
23467
24501
  )
23468
24502
  );
23469
- const snapshotSearchFilter = searchFilter ? eq17(sessionListSnapshots.search, searchFilter) : isNull5(sessionListSnapshots.search);
24503
+ const snapshotSearchFilter = searchFilter ? eq17(sessionListSnapshots.search, searchFilter) : isNull6(sessionListSnapshots.search);
23470
24504
  const [reusableSnapshot] = await tx.select().from(sessionListSnapshots).where(
23471
24505
  and17(
23472
24506
  eq17(sessionListSnapshots.workspaceId, workspaceId),
23473
24507
  eq17(sessionListSnapshots.subjectId, options.subjectId),
23474
24508
  eq17(sessionListSnapshots.parentSessionFilter, parentFilter),
23475
24509
  snapshotSearchFilter,
23476
- gt4(
24510
+ gt5(
23477
24511
  sessionListSnapshots.createdAt,
23478
24512
  new Date(now.getTime() - SESSION_LIST_SNAPSHOT_REUSE_MS)
23479
24513
  )
@@ -23494,7 +24528,7 @@ async function listSessionsForSubject(db, workspaceId, options) {
23494
24528
  ).where(
23495
24529
  and17(
23496
24530
  ...filters,
23497
- or4(isNull5(sessionPins.id), eq17(sessionPins.pinned, false))
24531
+ or6(isNull6(sessionPins.id), eq17(sessionPins.pinned, false))
23498
24532
  )
23499
24533
  ).orderBy(desc8(sessions.updatedAt), desc8(sessions.id)).limit(SESSION_LIST_SNAPSHOT_MAX_IDS + 1);
23500
24534
  if (ordinaryIdRows.length > SESSION_LIST_SNAPSHOT_MAX_IDS) {
@@ -23568,7 +24602,7 @@ async function listSessionsForSubject(db, workspaceId, options) {
23568
24602
  eq17(sessions.workspaceId, workspaceId),
23569
24603
  inArray11(sessions.id, pageIds),
23570
24604
  ...options.authorizationScope ? [sessionAuthorizationScopeFilter(options.authorizationScope)] : [],
23571
- or4(isNull5(sessionPins.id), eq17(sessionPins.pinned, false))
24605
+ or6(isNull6(sessionPins.id), eq17(sessionPins.pinned, false))
23572
24606
  )
23573
24607
  );
23574
24608
  const ordinaryById = new Map(ordinaryRows.map((row) => [row.session.id, row]));
@@ -23758,7 +24792,7 @@ async function listSessions(db, workspaceId, limitOrOptions = 50) {
23758
24792
  if (Object.prototype.hasOwnProperty.call(options, "parentSessionId")) {
23759
24793
  const parentSessionId = options.parentSessionId;
23760
24794
  if (parentSessionId === null) {
23761
- filters.push(isNull5(sessions.parentSessionId));
24795
+ filters.push(isNull6(sessions.parentSessionId));
23762
24796
  } else if (parentSessionId !== void 0) {
23763
24797
  filters.push(eq17(sessions.parentSessionId, parentSessionId));
23764
24798
  }
@@ -23899,11 +24933,11 @@ async function listSessionDiscoverySummaries(db, workspaceId, options) {
23899
24933
  if (orderBy === "createdAt" && options.cursor && (cursorSortRevision !== "0" || options.cursor.snapshotRevision !== "0")) {
23900
24934
  throw new Error("sessions_list created-order cursor cannot carry activity revisions");
23901
24935
  }
23902
- const cursorPredicate = options.cursor ? orderBy === "updatedAt" ? or4(
24936
+ const cursorPredicate = options.cursor ? orderBy === "updatedAt" ? or6(
23903
24937
  sql14`${sessions.activityRevision} < ${cursorSortRevision}::text::bigint`,
23904
24938
  and17(
23905
24939
  sql14`${sessions.activityRevision} = ${cursorSortRevision}::text::bigint`,
23906
- or4(
24940
+ or6(
23907
24941
  sql14`${sessions.updatedAt} < ${options.cursor.sortAt}::text::timestamptz`,
23908
24942
  and17(
23909
24943
  sql14`${sessions.updatedAt} = ${options.cursor.sortAt}::text::timestamptz`,
@@ -23911,7 +24945,7 @@ async function listSessionDiscoverySummaries(db, workspaceId, options) {
23911
24945
  )
23912
24946
  )
23913
24947
  )
23914
- ) : or4(
24948
+ ) : or6(
23915
24949
  // Cast through text deliberately. postgres.js otherwise infers a
23916
24950
  // timestamptz parameter and serializes this exact cursor string via
23917
24951
  // JS Date, which discards PostgreSQL's sub-millisecond precision.
@@ -24282,16 +25316,16 @@ async function listSessionEventPage(db, workspaceId, sessionId, options = {}) {
24282
25316
  const filters = [
24283
25317
  eq17(sessionEvents.workspaceId, workspaceId),
24284
25318
  eq17(sessionEvents.sessionId, sessionId),
24285
- gt4(sessionEvents.sequence, after)
25319
+ gt5(sessionEvents.sequence, after)
24286
25320
  ];
24287
25321
  if (options.authoritativeLatest) {
24288
25322
  filters.push(
24289
25323
  and17(
24290
- or4(
24291
- isNull5(sessionEvents.turnAssociation),
25324
+ or6(
25325
+ isNull6(sessionEvents.turnAssociation),
24292
25326
  eq17(sessionEvents.turnAssociation, "current")
24293
25327
  ),
24294
- isNull5(sessionEvents.duplicateOfEventId)
25328
+ isNull6(sessionEvents.duplicateOfEventId)
24295
25329
  )
24296
25330
  );
24297
25331
  }
@@ -24306,7 +25340,7 @@ async function listSessionEventPage(db, workspaceId, sessionId, options = {}) {
24306
25340
  filters.push(lt4(sessionEvents.sequence, cursor));
24307
25341
  }
24308
25342
  } else if (cursor !== void 0) {
24309
- filters.push(gt4(sessionEvents.sequence, cursor));
25343
+ filters.push(gt5(sessionEvents.sequence, cursor));
24310
25344
  }
24311
25345
  if (direction === "after" && before !== void 0 && before <= POSTGRES_INT_MAX) {
24312
25346
  filters.push(lt4(sessionEvents.sequence, before));
@@ -24489,7 +25523,7 @@ async function listSessionEvents(db, workspaceId, sessionId, afterOrOptions = 0,
24489
25523
  const filters = [
24490
25524
  eq17(sessionEvents.workspaceId, workspaceId),
24491
25525
  eq17(sessionEvents.sessionId, sessionId),
24492
- gt4(sessionEvents.sequence, after)
25526
+ gt5(sessionEvents.sequence, after)
24493
25527
  ];
24494
25528
  if (typeFilters.includeTypes.length > 0) {
24495
25529
  filters.push(inArray11(sessionEvents.type, typeFilters.includeTypes));
@@ -24623,7 +25657,7 @@ async function listWorkspaceControlEvents(db, workspaceId, after = 0, limit = 50
24623
25657
  const rows = await scopedDb.select().from(workspaceControlEvents).where(
24624
25658
  and17(
24625
25659
  eq17(workspaceControlEvents.workspaceId, workspaceId),
24626
- gt4(workspaceControlEvents.revision, cursor)
25660
+ gt5(workspaceControlEvents.revision, cursor)
24627
25661
  )
24628
25662
  ).orderBy(asc8(workspaceControlEvents.revision)).limit(boundedLimit);
24629
25663
  return rows.map(mapWorkspaceControlEvent);
@@ -24769,21 +25803,6 @@ function validateAnsweredHumanInput(questions, answers) {
24769
25803
  `Text question ${question.id} accepts one value`
24770
25804
  );
24771
25805
  }
24772
- const value = values[0] ?? "";
24773
- const minLength = question.validation?.minLength;
24774
- const maxLength = question.validation?.maxLength;
24775
- if (minLength != null && value.length < minLength) {
24776
- throw new HumanInputResponseValidationError(
24777
- "INVALID_RESPONSE",
24778
- `Question ${question.id} is shorter than its minimum length`
24779
- );
24780
- }
24781
- if (maxLength != null && value.length > maxLength) {
24782
- throw new HumanInputResponseValidationError(
24783
- "INVALID_RESPONSE",
24784
- `Question ${question.id} exceeds its maximum length`
24785
- );
24786
- }
24787
25806
  continue;
24788
25807
  }
24789
25808
  if (other && !question.allowOther) {
@@ -24856,7 +25875,7 @@ async function hasAcceptedRequiresActionAdvance(tx, input) {
24856
25875
  eq17(sessionEvents.turnId, input.turnId),
24857
25876
  eq17(sessionEvents.turnGeneration, input.turnGeneration),
24858
25877
  inArray11(sessionEvents.type, ["user.approvalDecision", "user.humanInputResponse"]),
24859
- gt4(sessionEvents.sequence, trigger.sequence)
25878
+ gt5(sessionEvents.sequence, trigger.sequence)
24860
25879
  )
24861
25880
  ).limit(1);
24862
25881
  return accepted !== void 0;
@@ -24994,6 +26013,26 @@ async function acceptSessionHumanInputResponse(db, input) {
24994
26013
  occurredAt: now
24995
26014
  }).returning();
24996
26015
  if (!event) throw new Error("Failed to append human-input response");
26016
+ await mirrorSessionRealtimeContextInTransaction(tx, {
26017
+ accountId: session.accountId,
26018
+ workspaceId: input.workspaceId,
26019
+ sessionId: input.sessionId,
26020
+ sourceKind: "human_input_response",
26021
+ sourceId: event.id,
26022
+ turnId: turn.id,
26023
+ channel: response.outcome === "answered" || response.outcome === "skipped" ? "speakable" : null,
26024
+ text: renderRealtimeHumanInputResponseContext({
26025
+ requestId: request.id,
26026
+ questions: request.questions,
26027
+ response
26028
+ }),
26029
+ payload: {
26030
+ requestId: request.id,
26031
+ outcome: response.outcome,
26032
+ sourceEventId: event.id
26033
+ },
26034
+ now
26035
+ });
24997
26036
  await tx.update(sessions).set({ lastSequence: session.lastSequence + 1, updatedAt: now }).where(eq17(sessions.id, session.id));
24998
26037
  const workflowWakeRevision = await enqueueSessionWorkflowWakeInTransaction(
24999
26038
  tx,
@@ -26054,7 +27093,7 @@ function exactPtyIdentityPredicates(identity) {
26054
27093
  eq17(sandboxPtySessions.providerBackend, identity.providerBackend),
26055
27094
  eq17(sandboxPtySessions.providerInstanceId, identity.providerInstanceId),
26056
27095
  eq17(sandboxPtySessions.routeKind, identity.routeKind),
26057
- identity.routeTargetId === null ? isNull5(sandboxPtySessions.routeTargetId) : eq17(sandboxPtySessions.routeTargetId, identity.routeTargetId),
27096
+ identity.routeTargetId === null ? isNull6(sandboxPtySessions.routeTargetId) : eq17(sandboxPtySessions.routeTargetId, identity.routeTargetId),
26058
27097
  eq17(sandboxPtySessions.routeEpoch, identity.routeEpoch)
26059
27098
  ];
26060
27099
  }
@@ -28079,7 +29118,7 @@ async function settleExactLostProviderWorkspaceBlockersTx(tx, input) {
28079
29118
  eq17(sandboxWorkspaceMutationAdmissions.sandboxGroupId, input.sandboxGroupId),
28080
29119
  eq17(sandboxWorkspaceMutationAdmissions.leaseEpoch, input.lostEpoch),
28081
29120
  eq17(sandboxWorkspaceMutationAdmissions.providerInstanceId, input.lostInstanceId),
28082
- isNull5(sandboxWorkspaceMutationAdmissions.settledAt)
29121
+ isNull6(sandboxWorkspaceMutationAdmissions.settledAt)
28083
29122
  )
28084
29123
  ).returning({ id: sandboxWorkspaceMutationAdmissions.id });
28085
29124
  const closedPtys = await tx.update(sandboxPtySessions).set({ status: "closed", closedAt: /* @__PURE__ */ new Date() }).where(
@@ -29711,8 +30750,8 @@ async function retainWorkspaceMutationProcess(db, input) {
29711
30750
  and17(
29712
30751
  eq17(sandboxRetainedProcesses.id, process.id),
29713
30752
  eq17(sandboxRetainedProcesses.state, "active"),
29714
- isNull5(sandboxRetainedProcesses.providerBindingKey),
29715
- isNull5(sandboxRetainedProcesses.providerBinding)
30753
+ isNull6(sandboxRetainedProcesses.providerBindingKey),
30754
+ isNull6(sandboxRetainedProcesses.providerBinding)
29716
30755
  )
29717
30756
  ).returning();
29718
30757
  if (!bound) {
@@ -29917,8 +30956,8 @@ async function bindRetainedProcessProviderIdentity(db, input) {
29917
30956
  eq17(sandboxRetainedProcesses.id, process.id),
29918
30957
  eq17(sandboxRetainedProcesses.state, "active"),
29919
30958
  eq17(sandboxRetainedProcesses.reconcileClaimId, input.claimId),
29920
- isNull5(sandboxRetainedProcesses.providerBindingKey),
29921
- isNull5(sandboxRetainedProcesses.providerBinding)
30959
+ isNull6(sandboxRetainedProcesses.providerBindingKey),
30960
+ isNull6(sandboxRetainedProcesses.providerBinding)
29922
30961
  )
29923
30962
  ).returning();
29924
30963
  if (!updated) {
@@ -31893,7 +32932,7 @@ async function setEnrollmentDisplayState(db, input) {
31893
32932
  // Only write on a CHANGE to EITHER field — an unchanged display state must
31894
32933
  // not churn a write on every reconnect Hello. `IS DISTINCT FROM` is the
31895
32934
  // null-safe inequality (a plain `ne` skips NULL rows).
31896
- or4(
32935
+ or6(
31897
32936
  ne(enrollments.hasDisplay, input.hasDisplay),
31898
32937
  sql14`${enrollments.desktopUnavailableReason} IS DISTINCT FROM ${input.desktopUnavailableReason}`
31899
32938
  )
@@ -32588,7 +33627,7 @@ async function forceDrainOverLimitViewerOnlyBoxes(db, input) {
32588
33627
  and17(
32589
33628
  eq17(usageEvents.workspaceId, input.workspaceId),
32590
33629
  eq17(usageEvents.eventType, "sandbox.warm_seconds"),
32591
- gt4(usageEvents.occurredAt, since)
33630
+ gt5(usageEvents.occurredAt, since)
32592
33631
  )
32593
33632
  );
32594
33633
  if (Number(total) >= input.maxWarmSecondsPerWorkspace) {
@@ -34575,7 +35614,7 @@ async function claimSessionWorkForAttempt(db, workspaceId, input) {
34575
35614
  "acknowledged",
34576
35615
  "settled"
34577
35616
  ]),
34578
- isNull5(sessionTurnAttempts.quiescedAt)
35617
+ isNull6(sessionTurnAttempts.quiescedAt)
34579
35618
  )
34580
35619
  ).orderBy(desc8(sessionAttemptInterruptions.requestedAt)).limit(1);
34581
35620
  if (unquiescedInterruption) {
@@ -34623,7 +35662,7 @@ async function claimSessionWorkForAttempt(db, workspaceId, input) {
34623
35662
  eq17(sessions.accountId, session.accountId),
34624
35663
  eq17(sessions.workspaceId, workspaceId),
34625
35664
  eq17(sessions.id, sessionId),
34626
- isNull5(sessions.activeTurnId)
35665
+ isNull6(sessions.activeTurnId)
34627
35666
  )
34628
35667
  ).returning({ id: sessions.id });
34629
35668
  if (!claimedSession) {
@@ -35328,11 +36367,10 @@ async function claimSessionWorkForAttempt(db, workspaceId, input) {
35328
36367
  sessionId,
35329
36368
  turnId: row.id,
35330
36369
  position: Number(historyPosition),
35331
- item: sanitizeModelPayload({
35332
- type: "message",
35333
- role: "user",
35334
- content: row.prompt
35335
- }),
36370
+ item: durableUserHistoryItem(
36371
+ row.prompt,
36372
+ Array.isArray(row.resources) ? row.resources : []
36373
+ ),
35336
36374
  producerCodexCredentialId: null
35337
36375
  });
35338
36376
  const providerDelegatedTurn = isSessionRealtimeDelegationTurnMetadata(row.metadata);
@@ -35449,7 +36487,7 @@ async function markSessionAttemptQuiesced(db, input) {
35449
36487
  and17(
35450
36488
  eq17(sessionTurnAttempts.workspaceId, input.workspaceId),
35451
36489
  eq17(sessionTurnAttempts.id, input.attemptId),
35452
- isNull5(sessionTurnAttempts.quiescedAt)
36490
+ isNull6(sessionTurnAttempts.quiescedAt)
35453
36491
  )
35454
36492
  ).returning({ id: sessionTurnAttempts.id });
35455
36493
  if (!marked) {
@@ -35987,7 +37025,7 @@ async function peekSessionWork(db, workspaceId, sessionId) {
35987
37025
  "user.approvalDecision",
35988
37026
  "user.humanInputResponse"
35989
37027
  ]),
35990
- gt4(sessionEvents.sequence, currentTrigger.sequence)
37028
+ gt5(sessionEvents.sequence, currentTrigger.sequence)
35991
37029
  )
35992
37030
  ).orderBy(desc8(sessionEvents.sequence), desc8(sessionEvents.id)).limit(1);
35993
37031
  if (actionResponse) {
@@ -36452,11 +37490,11 @@ async function applySessionTurnSettlement(db, workspaceId, input, hooks = {}) {
36452
37490
  activeTurnId: session.activeTurnId
36453
37491
  };
36454
37492
  }
37493
+ const humanInputRequests = input.runState?.humanInputRequests ?? [];
36455
37494
  if (input.runState) {
36456
37495
  if (input.turnStatus !== "requires_action" || input.sessionStatus !== "requires_action") {
36457
37496
  throw new Error("A frozen run state requires a requires_action settlement");
36458
37497
  }
36459
- const humanInputRequests = input.runState.humanInputRequests ?? [];
36460
37498
  for (const request of humanInputRequests) {
36461
37499
  const parsedQuestions = request.questions.map(
36462
37500
  (question) => HumanInputQuestionContract.parse(question)
@@ -36656,7 +37694,10 @@ async function applySessionTurnSettlement(db, workspaceId, input, hooks = {}) {
36656
37694
  eq17(sessionHumanInputRequests.turnId, input.turnId),
36657
37695
  eq17(sessionHumanInputRequests.status, "pending")
36658
37696
  )
36659
- ).returning({ id: sessionHumanInputRequests.id }) : [];
37697
+ ).returning({
37698
+ id: sessionHumanInputRequests.id,
37699
+ questions: sessionHumanInputRequests.questions
37700
+ }) : [];
36660
37701
  const terminalHumanInputEvents = terminalHumanInputRows.map(
36661
37702
  (request) => ({
36662
37703
  type: "user.humanInputResponse",
@@ -36721,6 +37762,69 @@ async function applySessionTurnSettlement(db, workspaceId, input, hooks = {}) {
36721
37762
  };
36722
37763
  });
36723
37764
  const inserted = values.length > 0 ? await tx.insert(sessionEvents).values(values).returning() : [];
37765
+ const requestedEvents = inserted.filter(
37766
+ (event) => event.type === "session.humanInput.requested"
37767
+ );
37768
+ if (requestedEvents.length > 0) {
37769
+ const requestedIds = new Set(
37770
+ requestedEvents.flatMap((event) => {
37771
+ const request = sessionEventPayloadRecord(event.payload).request;
37772
+ if (!request || typeof request !== "object" || Array.isArray(request)) return [];
37773
+ const id = request.id;
37774
+ return typeof id === "string" ? [id] : [];
37775
+ })
37776
+ );
37777
+ const requests = humanInputRequests.filter((request) => requestedIds.has(request.id));
37778
+ if (requests.length !== requestedIds.size) {
37779
+ throw new Error("Human-input realtime projection lost its durable request contract");
37780
+ }
37781
+ await mirrorSessionRealtimeContextInTransaction(tx, {
37782
+ accountId: session.accountId,
37783
+ workspaceId,
37784
+ sessionId: input.sessionId,
37785
+ sourceKind: "human_input_request",
37786
+ sourceId: requestedEvents.map((event) => event.id).join(":"),
37787
+ turnId: input.turnId,
37788
+ channel: "speakable",
37789
+ text: renderRealtimeHumanInputRequestContext({ requests }),
37790
+ payload: {
37791
+ status: "waiting_for_user",
37792
+ requestIds: requests.map((request) => request.id),
37793
+ sourceEventIds: requestedEvents.map((event) => event.id)
37794
+ },
37795
+ now
37796
+ });
37797
+ }
37798
+ const terminalHumanInputById = new Map(
37799
+ terminalHumanInputRows.map((request) => [request.id, request])
37800
+ );
37801
+ for (const event of inserted) {
37802
+ if (event.type !== "user.humanInputResponse") continue;
37803
+ const payload = sessionEventPayloadRecord(event.payload);
37804
+ const requestId = typeof payload.requestId === "string" ? payload.requestId : null;
37805
+ const request = requestId ? terminalHumanInputById.get(requestId) : null;
37806
+ if (!request) continue;
37807
+ await mirrorSessionRealtimeContextInTransaction(tx, {
37808
+ accountId: session.accountId,
37809
+ workspaceId,
37810
+ sessionId: input.sessionId,
37811
+ sourceKind: "human_input_response",
37812
+ sourceId: event.id,
37813
+ turnId: input.turnId,
37814
+ channel: null,
37815
+ text: renderRealtimeHumanInputResponseContext({
37816
+ requestId: request.id,
37817
+ questions: request.questions,
37818
+ response: { outcome: "cancelled" }
37819
+ }),
37820
+ payload: {
37821
+ requestId: request.id,
37822
+ outcome: "cancelled",
37823
+ sourceEventId: event.id
37824
+ },
37825
+ now
37826
+ });
37827
+ }
36724
37828
  const terminal = isTerminalSessionTurnStatus(input.turnStatus);
36725
37829
  if (isTerminalSessionTurnStatus(input.turnStatus)) {
36726
37830
  const terminalType = terminalSessionTurnEventType(input.turnStatus);
@@ -37217,7 +38321,7 @@ async function requestSessionTurnRecovery(db, workspaceId, input) {
37217
38321
  sessionHistoryItems.producerCodexCredentialId,
37218
38322
  input.providerArtifactInvalidation.codexCredentialId
37219
38323
  ),
37220
- isNull5(sessionHistoryItems.providerArtifactInvalidatedAt),
38324
+ isNull6(sessionHistoryItems.providerArtifactInvalidatedAt),
37221
38325
  sql14`${sessionHistoryItems.item} ->> 'type' in ('reasoning', 'compaction')`
37222
38326
  )
37223
38327
  ).returning({ id: sessionHistoryItems.id });
@@ -37231,7 +38335,7 @@ async function requestSessionTurnRecovery(db, workspaceId, input) {
37231
38335
  agentRunStates.frozenCodexCredentialId,
37232
38336
  input.providerArtifactInvalidation.codexCredentialId
37233
38337
  ),
37234
- isNull5(agentRunStates.providerArtifactInvalidatedAt)
38338
+ isNull6(agentRunStates.providerArtifactInvalidatedAt)
37235
38339
  )
37236
38340
  ).orderBy(desc8(agentRunStates.stateVersion)).limit(1);
37237
38341
  const invalidatedRunState = latestRunState ? await tx.update(agentRunStates).set({
@@ -37241,7 +38345,7 @@ async function requestSessionTurnRecovery(db, workspaceId, input) {
37241
38345
  }).where(
37242
38346
  and17(
37243
38347
  eq17(agentRunStates.id, latestRunState.id),
37244
- isNull5(agentRunStates.providerArtifactInvalidatedAt)
38348
+ isNull6(agentRunStates.providerArtifactInvalidatedAt)
37245
38349
  )
37246
38350
  ).returning({ id: agentRunStates.id }) : [];
37247
38351
  providerArtifactsInvalidated = invalidatedHistory.length + invalidatedRunState.length;
@@ -38029,7 +39133,7 @@ async function markSessionWorkflowWakeDelivered(db, input) {
38029
39133
  and17(
38030
39134
  eq17(sessionTurnAttempts.workspaceId, input.workspaceId),
38031
39135
  eq17(sessionTurnAttempts.sessionId, input.sessionId),
38032
- isNull5(sessionTurnAttempts.quiescedAt),
39136
+ isNull6(sessionTurnAttempts.quiescedAt),
38033
39137
  inArray11(sessionAttemptInterruptions.state, ["settled", "rejected_stale"])
38034
39138
  )
38035
39139
  ).limit(1);
@@ -39744,6 +40848,8 @@ export {
39744
40848
  CODEX_CREDENTIAL_LEASE_TTL_MS,
39745
40849
  CODEX_RESET_REDEMPTION_OUTCOMES,
39746
40850
  CODEX_ROTATION_STRATEGIES,
40851
+ ConnectionDisconnectGenerationError,
40852
+ ConnectionDisconnectIdempotencyError,
39747
40853
  ConnectionRefreshHttpError,
39748
40854
  FORCE_RLS_TABLES,
39749
40855
  GitHubInstallationAuthorityCommitError,
@@ -39852,6 +40958,10 @@ export {
39852
40958
  WorkspaceInstructionPolicyInvalidOperationError,
39853
40959
  WorkspaceInstructionPolicyLegacyUnavailableError,
39854
40960
  WorkspaceInstructionPolicyNotFoundError,
40961
+ WorkspaceInstructionPolicyOnboardingProposalConflictError,
40962
+ WorkspaceInstructionPolicyOnboardingProposalContentError,
40963
+ WorkspaceInstructionPolicyOnboardingProposalStaleError,
40964
+ WorkspaceInstructionPolicyOperationReuseError,
39855
40965
  WorkspaceInstructionPolicySnapshotAuthorityError,
39856
40966
  abandonCodexResetRedemptionBeforeProvider,
39857
40967
  abandonRecordingForTurnAttempt,
@@ -40022,6 +41132,7 @@ export {
40022
41132
  createWorkspaceArtifact,
40023
41133
  createWorkspaceEnvironment,
40024
41134
  createWorkspaceInstructionPolicyDraft,
41135
+ createWorkspaceInstructionPolicyOnboardingProposal,
40025
41136
  databaseFailureCode,
40026
41137
  sql15 as dbSql,
40027
41138
  deactivatePreferenceRegistry,
@@ -40053,6 +41164,8 @@ export {
40053
41164
  disableHostExportConsumer,
40054
41165
  disconnectAllCodexAccounts,
40055
41166
  disconnectCodexAccount,
41167
+ disconnectConnectionIdempotently,
41168
+ durableUserHistoryItem,
40056
41169
  editQueuedTurnInTransaction,
40057
41170
  enableCapabilityInstallation,
40058
41171
  enablePackInstallation,
@@ -40101,11 +41214,13 @@ export {
40101
41214
  getCodexRotationSettings,
40102
41215
  getComposerDraftInTransaction,
40103
41216
  getConnectionMetadata,
41217
+ getCurrentPreferenceRegistryGovernanceMetadata,
40104
41218
  getDeviceEnrollmentRequestByDeviceCode,
40105
41219
  getEligibleKnowledgeClaim,
40106
41220
  getEnrollment,
40107
41221
  getFile,
40108
41222
  getFileUpload,
41223
+ getFiles,
40109
41224
  getHostExportConsumerStatus,
40110
41225
  getHumanInputResumeForEvent,
40111
41226
  getKnowledgeMemory,
@@ -40188,6 +41303,7 @@ export {
40188
41303
  getWorkspaceInstructionPolicyRevision,
40189
41304
  getWorkspaceModelPolicy,
40190
41305
  getWorkspacePack,
41306
+ getWorkspaceStateAcceptedAttemptGovernance,
40191
41307
  grantWorkspaceAccess,
40192
41308
  hasAuditableGitHubInstallationAuthority,
40193
41309
  hasCreditLedgerEntry,
@@ -40282,6 +41398,7 @@ export {
40282
41398
  listWorkspaceArtifacts,
40283
41399
  listWorkspaceControlEvents,
40284
41400
  listWorkspaceEnvironments,
41401
+ listWorkspaceInstructionPolicyOnboardingProposals,
40285
41402
  listWorkspaceInstructionPolicyRevisions,
40286
41403
  listWorkspaceMembers,
40287
41404
  listWorkspacePacks,
@@ -40422,6 +41539,7 @@ export {
40422
41539
  reserveSessionCommandReceipt,
40423
41540
  reserveToolspaceCallForAttempt,
40424
41541
  resolveConnectorActionPolicy,
41542
+ resolveDocumentIndexAuthority,
40425
41543
  resolveSlackInstallationRoute,
40426
41544
  resolveWorkspaceMemoryBlock,
40427
41545
  restoreKnowledgeSourceObject,
@@ -40514,6 +41632,7 @@ export {
40514
41632
  syncSessionRealtimeLedgerInTransaction,
40515
41633
  touchEnrollmentLastSeen,
40516
41634
  touchLeaseHolder,
41635
+ transitionConnectionState,
40517
41636
  updateCodexAllocatorEligibility,
40518
41637
  updateCodexRotationSettings,
40519
41638
  updateConnection,