@opengeni/db 3.6.0 → 3.7.3-canary.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 (80) hide show
  1. package/dist/canonical-human-identities.js +3 -3
  2. package/dist/{chunk-744DFC65.js → chunk-4NAR7FBA.js} +92 -6
  3. package/dist/chunk-4NAR7FBA.js.map +1 -0
  4. package/dist/{chunk-IW6O6G7R.js → chunk-5NNCGFQY.js} +2 -2
  5. package/dist/{chunk-G3732M3T.js → chunk-DZCYW2WT.js} +2 -2
  6. package/dist/{chunk-WW7AJ5IC.js → chunk-F6PBS6WE.js} +5 -7
  7. package/dist/chunk-F6PBS6WE.js.map +1 -0
  8. package/dist/{chunk-UJ2EW3QI.js → chunk-O56DM5GZ.js} +340 -85
  9. package/dist/chunk-O56DM5GZ.js.map +1 -0
  10. package/dist/{chunk-CDMMSUWJ.js → chunk-S3TDDCS2.js} +3 -3
  11. package/dist/{chunk-Q5YUGQVK.js → chunk-SZAWDXQC.js} +3 -3
  12. package/dist/{chunk-UGDVSQ6U.js → chunk-U4WPPEBH.js} +2 -2
  13. package/dist/{chunk-2NT476HD.js → chunk-US4IS6IV.js} +2 -2
  14. package/dist/codex-token-resolver.d.ts +12 -1
  15. package/dist/company-profile-agent-admin.d.ts +4 -2
  16. package/dist/company-profile-agent-policy.d.ts +20 -0
  17. package/dist/company-profile-schema.d.ts +573 -0
  18. package/dist/editable-artifact-durable-export.js +2 -2
  19. package/dist/editable-artifacts.js +3 -3
  20. package/dist/index.d.ts +382 -18
  21. package/dist/index.js +4513 -2065
  22. package/dist/index.js.map +1 -1
  23. package/dist/managed-auth-session-sets.js +3 -3
  24. package/dist/managed-human-provisioning.d.ts +3 -3
  25. package/dist/memory-domain.d.ts +5 -3
  26. package/dist/provision-roles.js +1 -1
  27. package/dist/runtime-posture.d.ts +5 -5
  28. package/dist/schema.d.ts +725 -4
  29. package/dist/schema.js +13 -1
  30. package/dist/session-background-commands.js +3 -3
  31. package/dist/session-control.d.ts +40 -5
  32. package/dist/session-queue-commands.d.ts +2 -0
  33. package/dist/session-tenancy.js +3 -3
  34. package/dist/user-resource-authority.d.ts +8 -0
  35. package/dist/video-generation.js +3 -3
  36. package/drizzle/0369_local_human_personal_authority.sql +350 -0
  37. package/drizzle/0370_workspace_member_management_scope.sql +98 -0
  38. package/drizzle/0371_workspace_member_candidate_inventory.sql +128 -0
  39. package/drizzle/0372_ordered_variable_set_runtime_authority.sql +287 -0
  40. package/drizzle/0373_sandbox_shared_preparation.sql +59 -0
  41. package/drizzle/0374_session_event_cursors.sql +315 -0
  42. package/drizzle/0375_session_recovery_observability.sql +73 -0
  43. package/drizzle/0376_organization_workspace_inventory.sql +88 -0
  44. package/drizzle/0377_scoped_rig_health_projection.sql +80 -0
  45. package/drizzle/0378_scoped_rig_health_audit_timestamp.sql +77 -0
  46. package/drizzle/0379_session_event_raw_lane_activation.sql +518 -0
  47. package/drizzle/0380_autonomous_company_profile_agent_policy.sql +829 -0
  48. package/drizzle/0381_organization_codex_subscription_inheritance.sql +720 -0
  49. package/drizzle/0382_organization_api_key_provenance.sql +91 -0
  50. package/drizzle/0383_codex_cooldown_reconciliation.sql +51 -0
  51. package/drizzle/0384_codex_cooldown_revision_guard_privileges.sql +6 -0
  52. package/drizzle/0385_connected_machine_legacy_tilde_workdirs.sql +25 -0
  53. package/drizzle/0386_local_organization_administration.sql +157 -0
  54. package/package.json +6 -6
  55. package/src/codex-token-resolver.ts +26 -1
  56. package/src/company-brain-governed-writes.ts +30 -1
  57. package/src/company-profile-agent-admin.ts +68 -1
  58. package/src/company-profile-agent-policy.ts +126 -0
  59. package/src/company-profile-schema.ts +115 -1
  60. package/src/database.ts +3 -5
  61. package/src/index.ts +3626 -456
  62. package/src/managed-human-provisioning.ts +3 -3
  63. package/src/memory-domain.ts +9 -4
  64. package/src/organization-membership-lifecycle.ts +0 -1
  65. package/src/provision-roles.ts +83 -4
  66. package/src/runtime-posture.ts +22 -0
  67. package/src/schema.ts +161 -8
  68. package/src/session-control.ts +177 -59
  69. package/src/session-queue-commands.ts +146 -40
  70. package/src/session-tool-call-settlement.ts +34 -7
  71. package/src/user-resource-authority.ts +56 -0
  72. package/dist/chunk-744DFC65.js.map +0 -1
  73. package/dist/chunk-UJ2EW3QI.js.map +0 -1
  74. package/dist/chunk-WW7AJ5IC.js.map +0 -1
  75. /package/dist/{chunk-IW6O6G7R.js.map → chunk-5NNCGFQY.js.map} +0 -0
  76. /package/dist/{chunk-G3732M3T.js.map → chunk-DZCYW2WT.js.map} +0 -0
  77. /package/dist/{chunk-CDMMSUWJ.js.map → chunk-S3TDDCS2.js.map} +0 -0
  78. /package/dist/{chunk-Q5YUGQVK.js.map → chunk-SZAWDXQC.js.map} +0 -0
  79. /package/dist/{chunk-UGDVSQ6U.js.map → chunk-U4WPPEBH.js.map} +0 -0
  80. /package/dist/{chunk-2NT476HD.js.map → chunk-US4IS6IV.js.map} +0 -0
@@ -29,7 +29,7 @@ import {
29
29
  type TimelineAnnotation,
30
30
  type PersonalResourceAttachmentIntent,
31
31
  } from "@opengeni/contracts";
32
- import { and, asc, eq, inArray, sql } from "drizzle-orm";
32
+ import { and, asc, desc, eq, inArray, sql } from "drizzle-orm";
33
33
  import { setSubjectRlsContext, type Database, type SessionActivityDatabase } from "./database";
34
34
  import {
35
35
  fromPostgresLosslessJson,
@@ -345,11 +345,55 @@ async function lockSession(
345
345
 
346
346
  type SteerSupersessionResult = {
347
347
  interruptionCount: number;
348
+ steerTargetTurn: typeof schema.sessionTurns.$inferSelect | null;
348
349
  replacedTurn: typeof schema.sessionTurns.$inferSelect | null;
349
350
  liveCurrentTurnId: string | null;
351
+ deferredUntilCompaction: boolean;
350
352
  lastSequence: number;
351
353
  };
352
354
 
355
+ async function turnAttemptIsCompacting(
356
+ db: Database,
357
+ input: {
358
+ workspaceId: string;
359
+ sessionId: string;
360
+ turn: typeof schema.sessionTurns.$inferSelect;
361
+ },
362
+ ): Promise<boolean> {
363
+ // A standalone operator compaction is maintenance rather than replaceable
364
+ // direction. Once claimed, let it finish even before its provider-visible
365
+ // started landmark is appended.
366
+ if (input.turn.source === "compaction") return true;
367
+ if (!input.turn.activeAttemptId) return false;
368
+
369
+ // Automatic/proactive/overflow compaction happens inside an ordinary turn.
370
+ // The latest exact-attempt landmark is durable state: `started` means the
371
+ // checkpoint provider call is still in flight, while compacted/skipped opens
372
+ // ordinary Steer interruption again. Multiple compactions in one attempt are
373
+ // therefore handled by the newest lifecycle event rather than a historical
374
+ // existence test.
375
+ const [latest] = await db
376
+ .select({ type: schema.sessionEvents.type })
377
+ .from(schema.sessionEvents)
378
+ .where(
379
+ and(
380
+ eq(schema.sessionEvents.workspaceId, input.workspaceId),
381
+ eq(schema.sessionEvents.sessionId, input.sessionId),
382
+ eq(schema.sessionEvents.turnId, input.turn.id),
383
+ eq(schema.sessionEvents.turnGeneration, input.turn.executionGeneration),
384
+ eq(schema.sessionEvents.turnAttemptId, input.turn.activeAttemptId),
385
+ inArray(schema.sessionEvents.type, [
386
+ "session.context.compaction.started",
387
+ "session.context.compacted",
388
+ "session.context.compaction.skipped",
389
+ ]),
390
+ ),
391
+ )
392
+ .orderBy(desc(schema.sessionEvents.sequence), desc(schema.sessionEvents.id))
393
+ .limit(1);
394
+ return latest?.type === "session.context.compaction.started";
395
+ }
396
+
353
397
  /**
354
398
  * One canonical replacement transition shared by human row/new-prompt Steer
355
399
  * and Agent Steer. A live owner is interrupted and remains current until exact
@@ -371,8 +415,10 @@ export async function supersedeSessionCurrentDirectionInTransaction(
371
415
  if (!input.activeTurnId) {
372
416
  return {
373
417
  interruptionCount: 0,
418
+ steerTargetTurn: null,
374
419
  replacedTurn: null,
375
420
  liveCurrentTurnId: null,
421
+ deferredUntilCompaction: false,
376
422
  lastSequence: input.lastSequence,
377
423
  };
378
424
  }
@@ -391,6 +437,7 @@ export async function supersedeSessionCurrentDirectionInTransaction(
391
437
  workspaceId: input.workspaceId,
392
438
  controlLock: "already_locked",
393
439
  workspaceLock: "already_locked",
440
+ sessionIds: [input.sessionId],
394
441
  turnIds: [input.activeTurnId],
395
442
  attemptIds: preview?.activeAttemptId ? [preview.activeAttemptId] : [],
396
443
  });
@@ -410,6 +457,26 @@ export async function supersedeSessionCurrentDirectionInTransaction(
410
457
  `Running turn ${current.id} has no first-class attempt owner`,
411
458
  );
412
459
  }
460
+ if (
461
+ current.activeAttemptId &&
462
+ (await turnAttemptIsCompacting(db, {
463
+ workspaceId: input.workspaceId,
464
+ sessionId: input.sessionId,
465
+ turn: current,
466
+ }))
467
+ ) {
468
+ return {
469
+ interruptionCount: 0,
470
+ steerTargetTurn: current,
471
+ // An ordinary turn is superseded cooperatively as soon as its checkpoint
472
+ // settles. Standalone maintenance completes normally, then the Steer is
473
+ // already first in line.
474
+ replacedTurn: current.source === "compaction" ? null : current,
475
+ liveCurrentTurnId: current.id,
476
+ deferredUntilCompaction: true,
477
+ lastSequence: input.lastSequence,
478
+ };
479
+ }
413
480
  if (current.activeAttemptId) {
414
481
  if (current.status !== "running") {
415
482
  throw new SessionControlInvariantError(
@@ -431,8 +498,10 @@ export async function supersedeSessionCurrentDirectionInTransaction(
431
498
  .returning({ id: schema.sessionAttemptInterruptions.id });
432
499
  return {
433
500
  interruptionCount: interruption ? 1 : 0,
501
+ steerTargetTurn: current,
434
502
  replacedTurn: current,
435
503
  liveCurrentTurnId: current.id,
504
+ deferredUntilCompaction: false,
436
505
  lastSequence: input.lastSequence,
437
506
  };
438
507
  }
@@ -571,8 +640,10 @@ export async function supersedeSessionCurrentDirectionInTransaction(
571
640
  }
572
641
  return {
573
642
  interruptionCount: 0,
643
+ steerTargetTurn: current,
574
644
  replacedTurn: current,
575
645
  liveCurrentTurnId: null,
646
+ deferredUntilCompaction: false,
576
647
  lastSequence,
577
648
  };
578
649
  }
@@ -1388,9 +1459,11 @@ export async function steerQueuedTurnInTransaction(
1388
1459
  lastSequence: session.lastSequence,
1389
1460
  });
1390
1461
  const interruptionCount = supersession.interruptionCount;
1462
+ const steerTargetTurn = supersession.steerTargetTurn;
1391
1463
  const supersededTurnId = supersession.replacedTurn?.id ?? null;
1392
1464
  const supersededAttemptId = supersession.replacedTurn?.activeAttemptId ?? null;
1393
1465
  const liveCurrentTurnId = supersession.liveCurrentTurnId;
1466
+ const deferredUntilCompaction = supersession.deferredUntilCompaction;
1394
1467
 
1395
1468
  const withoutTarget = rows.filter((row) => row.id !== target.id);
1396
1469
  const ordered = [target, ...withoutTarget];
@@ -1412,6 +1485,7 @@ export async function steerQueuedTurnInTransaction(
1412
1485
  replacedTurnId: supersededTurnId,
1413
1486
  replacedAttemptId: supersededAttemptId,
1414
1487
  interruptionCount,
1488
+ ...(deferredUntilCompaction ? { deferredUntilCompaction: true } : {}),
1415
1489
  },
1416
1490
  updatedAt: now,
1417
1491
  })
@@ -1440,12 +1514,16 @@ export async function steerQueuedTurnInTransaction(
1440
1514
  sessionId: input.sessionId,
1441
1515
  sequence: ++sequence,
1442
1516
  type: "session.control.steer_requested",
1443
- turnId: supersededTurnId ?? target.id,
1517
+ turnId: steerTargetTurn?.id ?? target.id,
1518
+ turnGeneration: steerTargetTurn?.executionGeneration ?? null,
1519
+ turnAttemptId: steerTargetTurn?.activeAttemptId ?? null,
1520
+ turnAssociation: steerTargetTurn ? "current" : null,
1444
1521
  payload: {
1445
1522
  operationId: reserved.receipt.id,
1446
1523
  targetTurnId: target.id,
1447
1524
  replacedTurnId: supersededTurnId,
1448
- stopping: liveCurrentTurnId !== null,
1525
+ stopping: liveCurrentTurnId !== null && !deferredUntilCompaction,
1526
+ ...(deferredUntilCompaction ? { deferredUntilCompaction: true } : {}),
1449
1527
  },
1450
1528
  occurredAt: now,
1451
1529
  });
@@ -1480,6 +1558,7 @@ export async function steerQueuedTurnInTransaction(
1480
1558
  operationId: reserved.receipt.id,
1481
1559
  replacedTurnId: supersededTurnId,
1482
1560
  interruptionCount,
1561
+ deferredUntilCompaction,
1483
1562
  },
1484
1563
  },
1485
1564
  "metadata",
@@ -1501,6 +1580,7 @@ export async function steerQueuedTurnInTransaction(
1501
1580
  result: {
1502
1581
  interruptionCount,
1503
1582
  supersededTurnId,
1583
+ deferredUntilCompaction,
1504
1584
  wakeRevision,
1505
1585
  workspaceControlEventId: resumed.workspaceControlEventId,
1506
1586
  },
@@ -1730,12 +1810,37 @@ export async function submitHumanPromptInTransaction(
1730
1810
  );
1731
1811
  }
1732
1812
 
1733
- // Send is queue admission, never a hidden control mutation. A paused Send
1734
- // remains inert behind the existing gate until the user explicitly resumes.
1735
- // Steer is the intentional exception: it replaces the current direction and
1736
- // therefore activates the selected branch atomically.
1813
+ const draft =
1814
+ input.expectedDraftRevision === null || input.expectedDraftRevision === undefined
1815
+ ? null
1816
+ : await getComposerDraftInTransaction(db, {
1817
+ workspaceId: input.workspaceId,
1818
+ sessionId: input.sessionId,
1819
+ subjectId: input.subjectId,
1820
+ lock: true,
1821
+ });
1822
+ const isQueueEditSubmission = draft?.sourceTurnId !== null && draft?.sourceTurnId !== undefined;
1823
+
1824
+ // A normal Send received while the active branch is waiting in
1825
+ // `requires_action` is the human choosing to continue conversationally
1826
+ // instead of through the pending decision surface. Promote only that active
1827
+ // wait to Steer semantics so the frozen wait is cancelled and the new prompt
1828
+ // runs next. A queue-edit submission preserves the identity and placement of
1829
+ // already accepted queued work, so it must never cancel an unrelated active
1830
+ // wait. An explicitly paused branch remains inert until Resume or an explicit
1831
+ // Steer; running, recovering, and capacity-waiting work also retain ordinary
1832
+ // queue semantics.
1833
+ const effectiveDelivery =
1834
+ input.delivery === "send" &&
1835
+ (input.actor.type === "human" || input.actor.type === "operator") &&
1836
+ !isQueueEditSubmission &&
1837
+ before.state === "active" &&
1838
+ session.status === "requires_action" &&
1839
+ session.activeTurnId !== null
1840
+ ? "steer"
1841
+ : input.delivery;
1737
1842
  const resumed =
1738
- input.delivery === "send"
1843
+ effectiveDelivery === "send"
1739
1844
  ? {
1740
1845
  revision: before.controlVersion,
1741
1846
  control: before,
@@ -1753,16 +1858,6 @@ export async function submitHumanPromptInTransaction(
1753
1858
  observedControlEtag: input.controlEtag ?? null,
1754
1859
  admission,
1755
1860
  });
1756
-
1757
- const draft =
1758
- input.expectedDraftRevision === null || input.expectedDraftRevision === undefined
1759
- ? null
1760
- : await getComposerDraftInTransaction(db, {
1761
- workspaceId: input.workspaceId,
1762
- sessionId: input.sessionId,
1763
- subjectId: input.subjectId,
1764
- lock: true,
1765
- });
1766
1861
  if (input.expectedDraftRevision !== null && input.expectedDraftRevision !== undefined) {
1767
1862
  const actualRevision = draft?.revision ?? 0;
1768
1863
  if (actualRevision !== input.expectedDraftRevision) {
@@ -1928,7 +2023,7 @@ export async function submitHumanPromptInTransaction(
1928
2023
  : (input.modelContext ?? null);
1929
2024
  const existingQueued = await loadQueuedTurns(db, input.workspaceId, input.sessionId, true);
1930
2025
  const routing: SessionPromptRouting =
1931
- input.delivery === "steer"
2026
+ effectiveDelivery === "steer"
1932
2027
  ? "accepted_for_steering"
1933
2028
  : before.state === "paused" || session.activeTurnId || existingQueued.length > 0
1934
2029
  ? "queued_for_execution"
@@ -1959,7 +2054,7 @@ export async function submitHumanPromptInTransaction(
1959
2054
  ...(input.model ? { model: input.model } : {}),
1960
2055
  ...(input.reasoningEffort ? { reasoningEffort: input.reasoningEffort } : {}),
1961
2056
  ...(input.latencyMode ? { latencyMode: input.latencyMode } : {}),
1962
- delivery: input.delivery,
2057
+ delivery: effectiveDelivery,
1963
2058
  routing,
1964
2059
  initiator: frozenInitiator.initiator,
1965
2060
  },
@@ -1980,7 +2075,7 @@ export async function submitHumanPromptInTransaction(
1980
2075
  status: "queued",
1981
2076
  source: input.source,
1982
2077
  promptRouting: routing,
1983
- position: input.delivery === "steer" ? 0 : existingQueued.length + 1,
2078
+ position: effectiveDelivery === "steer" ? 0 : existingQueued.length + 1,
1984
2079
  prompt: input.text,
1985
2080
  annotations,
1986
2081
  modelContext: effectiveModelContext,
@@ -2072,7 +2167,7 @@ export async function submitHumanPromptInTransaction(
2072
2167
  });
2073
2168
 
2074
2169
  const supersession =
2075
- input.delivery === "steer"
2170
+ effectiveDelivery === "steer"
2076
2171
  ? await supersedeSessionCurrentDirectionInTransaction(db, {
2077
2172
  accountId: input.accountId,
2078
2173
  workspaceId: input.workspaceId,
@@ -2085,8 +2180,10 @@ export async function submitHumanPromptInTransaction(
2085
2180
  })
2086
2181
  : {
2087
2182
  interruptionCount: 0,
2183
+ steerTargetTurn: null,
2088
2184
  replacedTurn: null,
2089
2185
  liveCurrentTurnId: null,
2186
+ deferredUntilCompaction: false,
2090
2187
  lastSequence: session.lastSequence,
2091
2188
  };
2092
2189
  // Ownerless Steer settlement may have appended interrupted tool results.
@@ -2094,9 +2191,11 @@ export async function submitHumanPromptInTransaction(
2094
2191
  sequence = supersession.lastSequence;
2095
2192
  for (const event of eventValues) event.sequence = ++sequence;
2096
2193
  const interruptionCount = supersession.interruptionCount;
2194
+ const steerTargetTurn = supersession.steerTargetTurn;
2097
2195
  const replacedTurnId = supersession.replacedTurn?.id ?? null;
2098
2196
  const replacedAttemptId = supersession.replacedTurn?.activeAttemptId ?? null;
2099
2197
  const liveCurrentTurnId = supersession.liveCurrentTurnId;
2198
+ const deferredUntilCompaction = supersession.deferredUntilCompaction;
2100
2199
  // Durable provenance for the queue projection. Until the superseded attempt
2101
2200
  // loses inference, user-visible output, and workspace-persistence authority,
2102
2201
  // its exact first-class attempt has no quiescence receipt. Pairing that
@@ -2104,7 +2203,7 @@ export async function submitHumanPromptInTransaction(
2104
2203
  // attempt…" truthfully across refresh/reconnect, even though logical
2105
2204
  // settlement has already cleared sessions.active_turn_id. Do not infer this
2106
2205
  // state from a local request spinner or queue position.
2107
- if (input.delivery === "steer") {
2206
+ if (effectiveDelivery === "steer") {
2108
2207
  const [updatedTurn] = await db
2109
2208
  .update(schema.sessionTurns)
2110
2209
  .set({
@@ -2114,6 +2213,7 @@ export async function submitHumanPromptInTransaction(
2114
2213
  replacedTurnId,
2115
2214
  replacedAttemptId,
2116
2215
  interruptionCount,
2216
+ ...(deferredUntilCompaction ? { deferredUntilCompaction: true } : {}),
2117
2217
  },
2118
2218
  updatedAt: now,
2119
2219
  })
@@ -2130,8 +2230,8 @@ export async function submitHumanPromptInTransaction(
2130
2230
  }
2131
2231
  committedTurn = updatedTurn;
2132
2232
  }
2133
- if (supersession.replacedTurn) {
2134
- const current = supersession.replacedTurn;
2233
+ if (steerTargetTurn) {
2234
+ const current = steerTargetTurn;
2135
2235
  if (!liveCurrentTurnId) {
2136
2236
  eventValues.push({
2137
2237
  accountId: input.accountId,
@@ -2157,8 +2257,9 @@ export async function submitHumanPromptInTransaction(
2157
2257
  payload: {
2158
2258
  operationId: reserved.receipt.id,
2159
2259
  targetTurnId: turnId,
2160
- replacedTurnId: current.id,
2161
- stopping: liveCurrentTurnId !== null,
2260
+ replacedTurnId,
2261
+ stopping: liveCurrentTurnId !== null && !deferredUntilCompaction,
2262
+ ...(deferredUntilCompaction ? { deferredUntilCompaction: true } : {}),
2162
2263
  },
2163
2264
  occurredAt: now,
2164
2265
  });
@@ -2188,7 +2289,7 @@ export async function submitHumanPromptInTransaction(
2188
2289
  }
2189
2290
 
2190
2291
  const ordered =
2191
- input.delivery === "steer" ? [turn, ...existingQueued] : [...existingQueued, turn];
2292
+ effectiveDelivery === "steer" ? [turn, ...existingQueued] : [...existingQueued, turn];
2192
2293
  await normalizeQueuePositions(
2193
2294
  db,
2194
2295
  input.workspaceId,
@@ -2196,7 +2297,7 @@ export async function submitHumanPromptInTransaction(
2196
2297
  ordered.map((row) => row.id),
2197
2298
  );
2198
2299
  const noCurrentAfter =
2199
- input.delivery === "steer" ? liveCurrentTurnId === null : !session.activeTurnId;
2300
+ effectiveDelivery === "steer" ? liveCurrentTurnId === null : !session.activeTurnId;
2200
2301
  const nextStatus = noCurrentAfter ? "queued" : session.status;
2201
2302
  if (nextStatus !== session.status) {
2202
2303
  eventValues.push({
@@ -2223,12 +2324,12 @@ export async function submitHumanPromptInTransaction(
2223
2324
  turnId,
2224
2325
  channel: null,
2225
2326
  text: renderRealtimeHumanInputContext({
2226
- delivery: input.delivery,
2327
+ delivery: effectiveDelivery,
2227
2328
  routing,
2228
2329
  text: renderTimelineAnnotationsForModel(input.text, annotations),
2229
2330
  }),
2230
2331
  payload: {
2231
- delivery: input.delivery,
2332
+ delivery: effectiveDelivery,
2232
2333
  routing,
2233
2334
  acceptedEventId,
2234
2335
  instruction: "OpenGeni accepted and routed this user input; do not delegate it again.",
@@ -2242,7 +2343,7 @@ export async function submitHumanPromptInTransaction(
2242
2343
  .set({
2243
2344
  resources: mergeResourceRefs(session.resources as ResourceRef[], input.resources),
2244
2345
  tools: session.tools,
2245
- activeTurnId: input.delivery === "steer" ? liveCurrentTurnId : session.activeTurnId,
2346
+ activeTurnId: effectiveDelivery === "steer" ? liveCurrentTurnId : session.activeTurnId,
2246
2347
  status: nextStatus,
2247
2348
  queueVersion,
2248
2349
  queueHeadPosition: 0,
@@ -2276,8 +2377,8 @@ export async function submitHumanPromptInTransaction(
2276
2377
  workspaceId: input.workspaceId,
2277
2378
  sessionId: input.sessionId,
2278
2379
  temporalWorkflowId: workflowId,
2279
- reason: input.delivery === "steer" ? "prompt_steer" : "prompt_send",
2280
- controlRequested: input.delivery === "steer",
2380
+ reason: effectiveDelivery === "steer" ? "prompt_steer" : "prompt_send",
2381
+ controlRequested: effectiveDelivery === "steer",
2281
2382
  });
2282
2383
  await db.insert(schema.auditEvents).values(
2283
2384
  withLosslessContentWriteVersion(
@@ -2288,13 +2389,14 @@ export async function submitHumanPromptInTransaction(
2288
2389
  input.actor.type === "agent_attempt"
2289
2390
  ? `attempt:${input.actor.attemptId}`
2290
2391
  : input.actor.subjectId,
2291
- action: input.delivery === "steer" ? "session.prompt.steer" : "session.prompt.send",
2392
+ action: effectiveDelivery === "steer" ? "session.prompt.steer" : "session.prompt.send",
2292
2393
  targetType: "session_turn",
2293
2394
  targetId: turnId,
2294
2395
  metadata: {
2295
2396
  operationId: reserved.receipt.id,
2296
2397
  replacedTurnId,
2297
2398
  interruptionCount,
2399
+ deferredUntilCompaction,
2298
2400
  ...(input.turnExecutionPolicy
2299
2401
  ? turnExecutionPolicyAuditMetadata(input.turnExecutionPolicy, turnId)
2300
2402
  : {}),
@@ -2338,6 +2440,7 @@ export async function submitHumanPromptInTransaction(
2338
2440
  wakeRevision,
2339
2441
  interruptionCount,
2340
2442
  replacedTurnId,
2443
+ deferredUntilCompaction,
2341
2444
  workspaceControlEventId: resumed.workspaceControlEventId,
2342
2445
  routing,
2343
2446
  ...(input.turnExecutionPolicy
@@ -2815,16 +2918,17 @@ export async function steerAgentSessionInTransaction(
2815
2918
  sessionId: input.targetSessionId,
2816
2919
  sequence: ++sequence,
2817
2920
  type: "session.control.steer_requested",
2818
- turnId: supersession.replacedTurn?.id ?? null,
2819
- turnGeneration: supersession.replacedTurn?.executionGeneration ?? null,
2820
- turnAttemptId: supersession.replacedTurn?.activeAttemptId ?? null,
2821
- turnAssociation: supersession.replacedTurn ? "current" : null,
2921
+ turnId: supersession.steerTargetTurn?.id ?? null,
2922
+ turnGeneration: supersession.steerTargetTurn?.executionGeneration ?? null,
2923
+ turnAttemptId: supersession.steerTargetTurn?.activeAttemptId ?? null,
2924
+ turnAssociation: supersession.steerTargetTurn ? "current" : null,
2822
2925
  payload: {
2823
2926
  operationId: reserved.receipt.id,
2824
2927
  targetUpdateId: update.id,
2825
2928
  replacedTurnId: supersession.replacedTurn?.id ?? null,
2826
2929
  actorSessionId: input.actor.sessionId,
2827
- stopping: supersession.liveCurrentTurnId !== null,
2930
+ stopping: supersession.liveCurrentTurnId !== null && !supersession.deferredUntilCompaction,
2931
+ ...(supersession.deferredUntilCompaction ? { deferredUntilCompaction: true } : {}),
2828
2932
  },
2829
2933
  occurredAt: now,
2830
2934
  },
@@ -2912,6 +3016,7 @@ export async function steerAgentSessionInTransaction(
2912
3016
  callerExecutionGeneration: input.actor.executionGeneration,
2913
3017
  controlRevision: resumed.revision,
2914
3018
  interruptionCount: supersession.interruptionCount,
3019
+ deferredUntilCompaction: supersession.deferredUntilCompaction,
2915
3020
  workspaceControlEventId: resumed.workspaceControlEventId,
2916
3021
  },
2917
3022
  },
@@ -2928,6 +3033,7 @@ export async function steerAgentSessionInTransaction(
2928
3033
  wakeRevision,
2929
3034
  workflowId,
2930
3035
  interruptionCount: supersession.interruptionCount,
3036
+ deferredUntilCompaction: supersession.deferredUntilCompaction,
2931
3037
  },
2932
3038
  });
2933
3039
  return {
@@ -19,9 +19,16 @@ export function historyCallId(item: Record<string, unknown>): string | null {
19
19
  item.providerData && typeof item.providerData === "object" && !Array.isArray(item.providerData)
20
20
  ? (item.providerData as Record<string, unknown>)
21
21
  : null;
22
- const value =
23
- item.callId ?? item.call_id ?? providerData?.callId ?? providerData?.call_id ?? item.id;
24
- return typeof value === "string" && value.length > 0 ? value : null;
22
+ // Native tool-search `id` is the provider item id, not the call correlation
23
+ // id. Validate direct and provider identities before the item-id fallback.
24
+ const value = [
25
+ item.callId,
26
+ item.call_id,
27
+ providerData?.callId,
28
+ providerData?.call_id,
29
+ item.id,
30
+ ].find((candidate): candidate is string => typeof candidate === "string" && candidate.length > 0);
31
+ return value ?? null;
25
32
  }
26
33
 
27
34
  export function historyItemType(item: Record<string, unknown>): string | null {
@@ -68,13 +75,33 @@ export function interruptedToolCallResult(input: {
68
75
  }
69
76
  if (input.callType === "computer_call") return null;
70
77
  if (input.callType === "tool_search_call") {
78
+ const providerData =
79
+ input.callItem.providerData &&
80
+ typeof input.callItem.providerData === "object" &&
81
+ !Array.isArray(input.callItem.providerData)
82
+ ? (input.callItem.providerData as Record<string, unknown>)
83
+ : null;
84
+ const execution =
85
+ input.callItem.execution === "client" || input.callItem.execution === "server"
86
+ ? input.callItem.execution
87
+ : providerData?.execution === "client" || providerData?.execution === "server"
88
+ ? providerData.execution
89
+ : null;
90
+ const providerIdentity =
91
+ typeof providerData?.call_id === "string" || typeof providerData?.callId === "string";
71
92
  const snakeId = typeof input.callItem.call_id === "string";
72
93
  return {
73
94
  type: "tool_search_output",
74
- ...(snakeId ? { call_id: input.callId } : { callId: input.callId }),
75
- ...(input.callItem.execution === "client" || input.callItem.execution === "server"
76
- ? { execution: input.callItem.execution }
77
- : {}),
95
+ ...(providerIdentity
96
+ ? {
97
+ providerData: {
98
+ call_id: input.callId,
99
+ ...(execution ? { execution } : {}),
100
+ },
101
+ }
102
+ : snakeId
103
+ ? { call_id: input.callId, ...(execution ? { execution } : {}) }
104
+ : { callId: input.callId, ...(execution ? { execution } : {}) }),
78
105
  status: "incomplete",
79
106
  tools: [],
80
107
  };
@@ -301,6 +301,62 @@ export async function issueSelfUserResourceGrant(
301
301
  });
302
302
  }
303
303
 
304
+ export async function issueSelfLocalConnectionUseGrant(
305
+ db: Database,
306
+ input: {
307
+ accountId: string;
308
+ workspaceId: string;
309
+ subjectId: string;
310
+ authorityId: string;
311
+ context: "user_private" | "workspace_shared";
312
+ workspaceSharedAcknowledged: boolean;
313
+ },
314
+ ): Promise<UserResourceAuthorityGrant> {
315
+ return await withOwnerContext(db, input, async (scopedDb) => {
316
+ const [row] = await rawRows<
317
+ Omit<UserResourceAuthorityGrant, "delegation"> & {
318
+ organizationId: string;
319
+ authorityGeneration: number;
320
+ }
321
+ >(
322
+ scopedDb,
323
+ sql`
324
+ select grant_id as "grantId", organization_id as "organizationId",
325
+ authority_generation::int as "authorityGeneration",
326
+ target_workspace_id as "targetWorkspaceId",
327
+ target_session_id as "targetSessionId", action, grant_mode as mode,
328
+ grant_context as context, authority_epoch::int as "authorityEpoch",
329
+ grant_generation::int as generation, grant_status as status,
330
+ expires_at::text as "expiresAt"
331
+ from issue_self_local_connection_use_grant(
332
+ ${input.accountId}::uuid, ${input.authorityId}::uuid,
333
+ ${input.workspaceId}::uuid, ${input.context},
334
+ ${input.workspaceSharedAcknowledged}
335
+ )
336
+ `,
337
+ );
338
+ if (!row) throw new Error("local connection grant was not returned");
339
+ const { organizationId, authorityGeneration, ...grant } = row;
340
+ return {
341
+ ...grant,
342
+ expiresAt: rfc3339(grant.expiresAt),
343
+ delegation: {
344
+ authorityId: input.authorityId,
345
+ grantId: grant.grantId,
346
+ organizationId,
347
+ workspaceId: grant.targetWorkspaceId,
348
+ sessionId: grant.targetSessionId,
349
+ action: grant.action,
350
+ mode: grant.mode,
351
+ context: grant.context,
352
+ authorityEpoch: grant.authorityEpoch,
353
+ authorityGeneration,
354
+ grantGeneration: grant.generation,
355
+ },
356
+ };
357
+ });
358
+ }
359
+
304
360
  export async function revokeSelfUserResourceGrant(
305
361
  db: Database,
306
362
  input: { accountId: string; workspaceId: string; subjectId: string; grantId: string },