@opengeni/db 0.36.1 → 3.1.0-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 (274) hide show
  1. package/dist/attached-browser-devices.d.ts +7 -0
  2. package/dist/automations.d.ts +154 -0
  3. package/dist/canonical-human-identities.js +3 -3
  4. package/dist/capability-integrations.d.ts +13 -0
  5. package/dist/child-lifecycle-notices.d.ts +68 -0
  6. package/dist/{chunk-GYO7ED2Q.js → chunk-EULAN2NP.js} +2 -2
  7. package/dist/{chunk-VTPRIXKG.js → chunk-NJVZPWXY.js} +3 -3
  8. package/dist/{chunk-HSOWSYOX.js → chunk-NMUBV7Z5.js} +19 -11
  9. package/dist/chunk-NMUBV7Z5.js.map +1 -0
  10. package/dist/chunk-OF5OBB76.js +4457 -0
  11. package/dist/chunk-OF5OBB76.js.map +1 -0
  12. package/dist/{chunk-5KTIEDX7.js → chunk-PR2WMLOQ.js} +7714 -4443
  13. package/dist/chunk-PR2WMLOQ.js.map +1 -0
  14. package/dist/{chunk-Z7VYMNPZ.js → chunk-SCPUJS53.js} +41 -4
  15. package/dist/chunk-SCPUJS53.js.map +1 -0
  16. package/dist/{chunk-SK7YYHBI.js → chunk-SIBYBA2D.js} +46 -1
  17. package/dist/chunk-SIBYBA2D.js.map +1 -0
  18. package/dist/chunk-TIKF3KTI.js +383 -0
  19. package/dist/chunk-TIKF3KTI.js.map +1 -0
  20. package/dist/chunk-ZZ5LJEFX.js +516 -0
  21. package/dist/chunk-ZZ5LJEFX.js.map +1 -0
  22. package/dist/codemode-operations.d.ts +1 -6
  23. package/dist/company-brain-context-selection-schema.d.ts +705 -0
  24. package/dist/company-brain-context-selection.d.ts +94 -0
  25. package/dist/company-brain-governed-writes.d.ts +24 -0
  26. package/dist/company-brain.d.ts +55 -0
  27. package/dist/company-profile-agent-admin.d.ts +15 -0
  28. package/dist/company-profile-schema.d.ts +619 -2
  29. package/dist/company-profile.d.ts +9 -4
  30. package/dist/connection-authority.d.ts +95 -0
  31. package/dist/connection-scopes.d.ts +8 -0
  32. package/dist/connection-tenancy-backfill.d.ts +41 -0
  33. package/dist/connection-token-resolver.d.ts +30 -1
  34. package/dist/database.d.ts +19 -0
  35. package/dist/editable-artifact-durable-export.d.ts +10 -0
  36. package/dist/editable-artifact-durable-export.js +18 -3
  37. package/dist/editable-artifact-durable-export.js.map +1 -1
  38. package/dist/editable-artifacts.d.ts +2 -2
  39. package/dist/editable-artifacts.js +3 -3
  40. package/dist/governed-learning-activation-schema.d.ts +984 -0
  41. package/dist/governed-learning-activation.d.ts +98 -0
  42. package/dist/governed-learning-evaluator-schema.d.ts +633 -0
  43. package/dist/governed-learning-evaluator.d.ts +28 -0
  44. package/dist/index.d.ts +1633 -87
  45. package/dist/index.js +22004 -8109
  46. package/dist/index.js.map +1 -1
  47. package/dist/insights.d.ts +18 -0
  48. package/dist/integration-bindings.d.ts +1 -0
  49. package/dist/integration-facets.d.ts +30 -0
  50. package/dist/interaction-placement-loss.d.ts +22 -0
  51. package/dist/knowledge-source-sync-schema.d.ts +730 -0
  52. package/dist/knowledge-source-sync.d.ts +60 -0
  53. package/dist/managed-human-provisioning.d.ts +25 -0
  54. package/dist/memory-domain.d.ts +3 -3
  55. package/dist/migrate.d.ts +11 -1
  56. package/dist/migrate.js +1 -1
  57. package/dist/new-session-drafts.d.ts +43 -5
  58. package/dist/organization-membership-backfill.d.ts +174 -0
  59. package/dist/organization-membership-lifecycle.d.ts +162 -0
  60. package/dist/pr-review.d.ts +107 -0
  61. package/dist/preference-registry-schema.d.ts +2 -0
  62. package/dist/preference-registry.d.ts +2 -0
  63. package/dist/provision-roles.js +1 -1
  64. package/dist/runtime-posture.d.ts +23 -9
  65. package/dist/schema.d.ts +24925 -13697
  66. package/dist/schema.js +103 -1
  67. package/dist/scoped-knowledge-schema.d.ts +52 -1
  68. package/dist/session-background-commands.d.ts +125 -0
  69. package/dist/session-background-commands.js +34 -0
  70. package/dist/session-background-commands.js.map +1 -0
  71. package/dist/session-control.d.ts +156 -3
  72. package/dist/session-goal-pacing.d.ts +68 -0
  73. package/dist/session-queue-commands.d.ts +42 -5
  74. package/dist/session-realtime-ledger.d.ts +3 -0
  75. package/dist/session-tenancy.d.ts +71 -1
  76. package/dist/session-tenancy.js +25 -3
  77. package/dist/session-tool-call-settlement.d.ts +9 -4
  78. package/dist/slack-routing-personal-workspace.d.ts +23 -0
  79. package/dist/slack-routing.d.ts +153 -0
  80. package/dist/slack-task-policy-schema.d.ts +34 -0
  81. package/dist/slack-task-policy.d.ts +8 -0
  82. package/dist/slack-user-link-access.d.ts +1 -0
  83. package/dist/task-notes-schema.d.ts +594 -0
  84. package/dist/task-notes.d.ts +39 -0
  85. package/dist/turn-initiator.d.ts +2 -0
  86. package/dist/user-resource-authority.d.ts +109 -0
  87. package/dist/video-generation.js +3 -3
  88. package/dist/workspace-authority.d.ts +81 -0
  89. package/dist/workspace-instruction-policies-schema.d.ts +279 -0
  90. package/dist/workspace-instruction-policies.d.ts +62 -0
  91. package/dist/workspace-learning-policy.d.ts +1 -0
  92. package/dist/workspace-membership-permissions.d.ts +2 -0
  93. package/drizzle/0240_enrollment_connection_authority.sql +39 -0
  94. package/drizzle/0240_model_context_user_messages.sql +204 -0
  95. package/drizzle/0241_atomic_personal_resource_delegation.sql +1000 -0
  96. package/drizzle/0241_enrollment_agent_runtime.sql +70 -0
  97. package/drizzle/0243_google_drive_object_acl_authority.sql +554 -0
  98. package/drizzle/0244_slack_app_home_refresh_queue.sql +120 -0
  99. package/drizzle/0245_model_context_contribution_facts.sql +88 -0
  100. package/drizzle/0246_integration_personal_instance_authority.sql +70 -0
  101. package/drizzle/0247_terraform_stacks_provenance_repair.sql +428 -0
  102. package/drizzle/0248_terraform_stacks_component_resolution_fence.sql +83 -0
  103. package/drizzle/0249_personal_resource_delegation_authority_correction.sql +662 -0
  104. package/drizzle/0250_direct_retained_process_owner_liveness.sql +199 -0
  105. package/drizzle/0251_connected_machine_operation_policy.sql +45 -0
  106. package/drizzle/0252_scheduled_personal_resource_delegation.sql +1867 -0
  107. package/drizzle/0253_common_user_resource_authority_lifecycle.sql +1555 -0
  108. package/drizzle/0254_scoped_variable_set_authority.sql +1255 -0
  109. package/drizzle/0255_company_brain_governed_write_proposals.sql +524 -0
  110. package/drizzle/0256_connection_authority_delegation.sql +703 -0
  111. package/drizzle/0257_goal_revision_decisions_and_root_constraints.sql +436 -0
  112. package/drizzle/0258_three_scope_document_knowledge_authority.sql +1273 -0
  113. package/drizzle/0259_company_brain_context_selection_receipts.sql +869 -0
  114. package/drizzle/0260_task_note_knowledge_promotion.sql +820 -0
  115. package/drizzle/0261_preference_knowledge_proposal_actor_binding.sql +471 -0
  116. package/drizzle/0262_scoped_connected_machines_and_rigs.sql +1700 -0
  117. package/drizzle/0263_organization_membership_lifecycle.sql +3284 -0
  118. package/drizzle/0264_connection_authority_runtime_activation.sql +1084 -0
  119. package/drizzle/0266_company_brain_context_receipt_inspection.sql +156 -0
  120. package/drizzle/0268_governed_learning_decision_receipts.sql +825 -0
  121. package/drizzle/0269_governed_learning_activation_controller.sql +1874 -0
  122. package/drizzle/0270_governed_learning_history_inspection.sql +170 -0
  123. package/drizzle/0271_company_brain_retrieval_only_default.sql +524 -0
  124. package/drizzle/0272_human_confirmed_learning_activation.sql +591 -0
  125. package/drizzle/0273_scheduled_variable_set_materialization.sql +268 -0
  126. package/drizzle/0274_human_confirmed_knowledge_review.sql +310 -0
  127. package/drizzle/0275_scheduled_connection_authority.sql +5527 -0
  128. package/drizzle/0276_onboarding_proposal_initiating_human_guc.sql +198 -0
  129. package/drizzle/0277_workspace_writer_authority_attribution.sql +393 -0
  130. package/drizzle/0278_workspace_membership_removal_fencing.sql +1174 -0
  131. package/drizzle/0279_workspace_connection_use_lane.sql +343 -0
  132. package/drizzle/0280_connection_and_variable_set_audit_attribution.sql +773 -0
  133. package/drizzle/0281_viewer_holder_authority_claims.sql +52 -0
  134. package/drizzle/0282_variable_set_session_attach_attribution.sql +178 -0
  135. package/drizzle/0283_editable_spreadsheet_authored_state.sql +82 -0
  136. package/drizzle/0284_truthful_human_confirmed_review_reason.sql +930 -0
  137. package/drizzle/0285_organization_tenancy_inventory.sql +329 -0
  138. package/drizzle/0286_widen_task_note_expiry_ceiling.sql +391 -0
  139. package/drizzle/0287_open_suffix_pending_tool_calls.sql +18 -0
  140. package/drizzle/0288_attached_browser_reenrollment.sql +64 -0
  141. package/drizzle/0289_session_composer_policy_authority.sql +597 -0
  142. package/drizzle/0290_organization_membership_backfill.sql +268 -0
  143. package/drizzle/0291_resource_authority_classification_assertion.sql +371 -0
  144. package/drizzle/0292_truthful_tenancy_inventory_counters.sql +291 -0
  145. package/drizzle/0293_confirm_time_rule_rebaseline.sql +615 -0
  146. package/drizzle/0294_preference_activation_authority.sql +237 -0
  147. package/drizzle/0295_retire_legacy_standing_memory_mode.sql +476 -0
  148. package/drizzle/0296_force_rls_backfill_noop_repair.sql +215 -0
  149. package/drizzle/0297_session_ownership_classification_and_backfill.sql +752 -0
  150. package/drizzle/0298_organization_tenancy_parity.sql +609 -0
  151. package/drizzle/0299_organization_membership_lock_order.sql +291 -0
  152. package/drizzle/0300_tenancy_backfill_ledger.sql +459 -0
  153. package/drizzle/0301_session_snapshot_and_pin_visibility.sql +181 -0
  154. package/drizzle/0302_personal_workspace_session_ownership.sql +303 -0
  155. package/drizzle/0303_session_tenancy_product_activation.sql +919 -0
  156. package/drizzle/0304_personal_workspace_private_session_reads.sql +97 -0
  157. package/drizzle/0305_personal_resource_grant_management.sql +584 -0
  158. package/drizzle/0306_atomic_personal_resource_attachments.sql +1374 -0
  159. package/drizzle/0307_session_attention_state.sql +51 -0
  160. package/drizzle/0308_session_archives.sql +35 -0
  161. package/drizzle/0309_channel_project_pins.sql +6 -0
  162. package/drizzle/0310_channel_project_order.sql +27 -0
  163. package/drizzle/0311_company_scope_and_private_session_create.sql +656 -0
  164. package/drizzle/0312_quiescent_session_tree_deletion.sql +39 -0
  165. package/drizzle/0313_private_child_session_authority.sql +365 -0
  166. package/drizzle/0314_unregistered_organization_invitations.sql +606 -0
  167. package/drizzle/0315_personal_github_repository_selection.sql +624 -0
  168. package/drizzle/0316_human_confirmed_activation_resumed_generation.sql +869 -0
  169. package/drizzle/0317_session_goal_continuation_hold.sql +64 -0
  170. package/drizzle/0318_session_turn_startup_milestones.sql +115 -0
  171. package/drizzle/0319_event_triggered_automations.sql +254 -0
  172. package/drizzle/0320_pr_review_pack.sql +113 -0
  173. package/drizzle/0321_slack_bot_environment_display_name.sql +15 -0
  174. package/drizzle/0322_session_turns_unclaimed_prompt_trigger_index.sql +5 -0
  175. package/drizzle/0323_organization_private_session_enablement.sql +489 -0
  176. package/drizzle/0324_human_confirmed_company_profile_agent_admin.sql +856 -0
  177. package/drizzle/0325_child_lifecycle_notices.sql +44 -0
  178. package/drizzle/0326_interaction_operation_error_codes.sql +62 -0
  179. package/drizzle/0327_slack_first_task_hint.sql +29 -0
  180. package/drizzle/0328_session_background_commands.sql +590 -0
  181. package/drizzle/0329_slack_orchestration_delivery_events.sql +91 -0
  182. package/drizzle/0330_api_key_descriptions.sql +20 -0
  183. package/drizzle/0331_managed_organization_creation.sql +163 -0
  184. package/drizzle/0332_organization_shared_workspace_control_plane.sql +539 -0
  185. package/drizzle/0333_session_turn_prompt_routing.sql +45 -0
  186. package/drizzle/0334_connected_machine_workspace_root.sql +99 -0
  187. package/drizzle/0335_slack_workspace_routing.sql +460 -0
  188. package/drizzle/0336_atomic_session_fork_visibility.sql +667 -0
  189. package/drizzle/0337_slack_routed_action_handles.sql +189 -0
  190. package/drizzle/0338_atomic_connected_machine_attachments.sql +410 -0
  191. package/drizzle/0339_document_authority_reclassification.sql +1153 -0
  192. package/drizzle/0340_tenancy_backfill_activation_evidence.sql +1347 -0
  193. package/drizzle/0341_slack_routing_probe_organization_fence.sql +109 -0
  194. package/package.json +10 -6
  195. package/src/attached-browser-devices.ts +233 -5
  196. package/src/automations.ts +911 -0
  197. package/src/browser-sessions.ts +10 -0
  198. package/src/capability-integrations.ts +175 -1
  199. package/src/child-lifecycle-notices.ts +241 -0
  200. package/src/codemode-operations.ts +1 -35
  201. package/src/company-brain-context-selection-schema.ts +100 -0
  202. package/src/company-brain-context-selection.ts +359 -0
  203. package/src/company-brain-governed-writes.ts +1170 -0
  204. package/src/company-brain.ts +309 -0
  205. package/src/company-profile-agent-admin.ts +225 -0
  206. package/src/company-profile-schema.ts +121 -1
  207. package/src/company-profile.ts +21 -0
  208. package/src/computer-sessions.ts +10 -1
  209. package/src/connection-authority.ts +290 -0
  210. package/src/connection-scopes.ts +20 -0
  211. package/src/connection-tenancy-backfill.ts +81 -0
  212. package/src/connection-token-resolver.ts +263 -31
  213. package/src/database.ts +75 -2
  214. package/src/editable-artifact-durable-export.ts +27 -0
  215. package/src/editable-artifacts-schema.ts +10 -5
  216. package/src/editable-artifacts.ts +21 -11
  217. package/src/governed-learning-activation-schema.ts +121 -0
  218. package/src/governed-learning-activation.ts +588 -0
  219. package/src/governed-learning-evaluator-schema.ts +72 -0
  220. package/src/governed-learning-evaluator.ts +217 -0
  221. package/src/index.ts +12001 -1699
  222. package/src/insights.ts +107 -0
  223. package/src/integration-bindings.ts +88 -6
  224. package/src/integration-facets.ts +287 -84
  225. package/src/interaction-placement-loss.ts +234 -0
  226. package/src/knowledge-source-sync-schema.ts +83 -0
  227. package/src/knowledge-source-sync.ts +530 -0
  228. package/src/managed-human-provisioning.ts +116 -0
  229. package/src/memory-domain.ts +27 -32
  230. package/src/migrate.ts +77 -1
  231. package/src/new-session-drafts.ts +229 -35
  232. package/src/organization-membership-backfill.ts +735 -0
  233. package/src/organization-membership-lifecycle.ts +985 -0
  234. package/src/pr-review.ts +890 -0
  235. package/src/preference-registry.ts +31 -1
  236. package/src/provision-roles.ts +931 -24
  237. package/src/runtime-posture-cli.ts +2 -0
  238. package/src/runtime-posture.ts +1315 -52
  239. package/src/schema.ts +3336 -438
  240. package/src/scoped-knowledge-schema.ts +16 -8
  241. package/src/scoped-knowledge.ts +1 -1
  242. package/src/session-background-commands.ts +759 -0
  243. package/src/session-control.ts +640 -74
  244. package/src/session-goal-pacing.ts +126 -0
  245. package/src/session-queue-commands.ts +450 -98
  246. package/src/session-realtime-context.ts +19 -3
  247. package/src/session-realtime-ledger.ts +75 -12
  248. package/src/session-realtime-mirror.ts +1 -1
  249. package/src/session-tenancy.ts +403 -49
  250. package/src/session-tool-call-settlement.ts +38 -29
  251. package/src/slack-routing-personal-workspace.ts +67 -0
  252. package/src/slack-routing.ts +469 -0
  253. package/src/slack-task-policy-schema.ts +5 -0
  254. package/src/slack-task-policy.ts +18 -0
  255. package/src/slack-user-link-access.ts +17 -1
  256. package/src/task-notes-schema.ts +74 -0
  257. package/src/task-notes.ts +124 -2
  258. package/src/turn-initiator.ts +8 -0
  259. package/src/user-resource-authority.ts +377 -0
  260. package/src/workspace-authority.ts +160 -0
  261. package/src/workspace-instruction-policies-schema.ts +53 -1
  262. package/src/workspace-instruction-policies.ts +528 -77
  263. package/src/workspace-learning-policy.ts +21 -5
  264. package/src/workspace-membership-permissions.ts +9 -0
  265. package/dist/chunk-5KTIEDX7.js.map +0 -1
  266. package/dist/chunk-FPVAD4CO.js +0 -117
  267. package/dist/chunk-FPVAD4CO.js.map +0 -1
  268. package/dist/chunk-HSOWSYOX.js.map +0 -1
  269. package/dist/chunk-SK7YYHBI.js.map +0 -1
  270. package/dist/chunk-VKLB2ZGI.js +0 -2389
  271. package/dist/chunk-VKLB2ZGI.js.map +0 -1
  272. package/dist/chunk-Z7VYMNPZ.js.map +0 -1
  273. /package/dist/{chunk-GYO7ED2Q.js.map → chunk-EULAN2NP.js.map} +0 -0
  274. /package/dist/{chunk-VTPRIXKG.js.map → chunk-NJVZPWXY.js.map} +0 -0
@@ -237,6 +237,7 @@ export async function flushSessionRealtimeTranscriptTailInTransaction(
237
237
  textCodecVersion: schema.sessionRealtimeEntries.textCodecVersion,
238
238
  payload: schema.sessionRealtimeEntries.payload,
239
239
  payloadCodecVersion: schema.sessionRealtimeEntries.payloadCodecVersion,
240
+ modelContext: schema.sessionRealtimeEntries.modelContext,
240
241
  })
241
242
  .from(schema.sessionRealtimeEntries)
242
243
  .where(
@@ -258,9 +259,23 @@ export async function flushSessionRealtimeTranscriptTailInTransaction(
258
259
  }));
259
260
  const rendered = renderSessionRealtimeTail(decodedRows);
260
261
  if (!rendered.context) return null;
262
+ const renderedRows = decodedRows.slice(decodedRows.length - rendered.includedEntryCount);
263
+ let foundUserTranscript = false;
264
+ let modelContext: string | null = null;
265
+ for (let index = renderedRows.length - 1; index >= 0; index -= 1) {
266
+ const entry = renderedRows[index]!;
267
+ if (entry.role === "user") {
268
+ foundUserTranscript = true;
269
+ modelContext = entry.modelContext;
270
+ break;
271
+ }
272
+ }
273
+ if (!foundUserTranscript) {
274
+ modelContext = renderedRows.at(-1)?.modelContext ?? null;
275
+ }
261
276
 
262
277
  const [session] = await db
263
- .select({ metadata: schema.sessions.metadata })
278
+ .select({ reasoningEffort: schema.sessions.reasoningEffort })
264
279
  .from(schema.sessions)
265
280
  .where(
266
281
  and(
@@ -270,7 +285,7 @@ export async function flushSessionRealtimeTranscriptTailInTransaction(
270
285
  )
271
286
  .limit(1);
272
287
  if (!session) throw new Error(`Realtime tail session ${input.sessionId} disappeared`);
273
- const reasoning = ReasoningEffort.safeParse(session.metadata.reasoningEffort);
288
+ const reasoningEffort = ReasoningEffort.parse(session.reasoningEffort);
274
289
  const admitted = await submitHumanPromptInTransaction(db, {
275
290
  accountId: input.accountId,
276
291
  workspaceId: input.workspaceId,
@@ -286,13 +301,14 @@ export async function flushSessionRealtimeTranscriptTailInTransaction(
286
301
  operationKey: deterministicUuid(`opengeni:session-realtime-tail-flush:${mode.id}`),
287
302
  delivery: "steer",
288
303
  text: rendered.context,
304
+ modelContext,
289
305
  messagePresentation: {
290
306
  kind: "realtime_voice_handoff",
291
307
  text: "Voice session ended. Remaining conversation context was sent to the agent.",
292
308
  context: rendered.context,
293
309
  },
294
310
  resources: [],
295
- reasoningEffortFallback: reasoning.success ? reasoning.data : "medium",
311
+ reasoningEffortFallback: reasoningEffort,
296
312
  turnMetadata: {
297
313
  realtimeTailFlush: {
298
314
  source: SESSION_REALTIME_TAIL_SOURCE,
@@ -15,7 +15,10 @@ import {
15
15
  SessionRealtimeConflictError,
16
16
  type AssertSessionRealtimeOwnerInput,
17
17
  } from "./session-realtime";
18
- import { lockSessionEventWriteRows, lockWorkspaceInferenceControl } from "./session-control";
18
+ import {
19
+ lockSessionEventWriteRows,
20
+ lockWorkspaceInferenceControlForAdmission,
21
+ } from "./session-control";
19
22
  import { submitHumanPromptInTransaction } from "./session-queue-commands";
20
23
  import { mirrorSessionRealtimeContextInTransaction } from "./session-realtime-mirror";
21
24
 
@@ -155,9 +158,12 @@ export type SessionRealtimeInboundEntryInput = {
155
158
  delegationItemId?: string | null | undefined;
156
159
  text?: string | null | undefined;
157
160
  payload?: Record<string, unknown> | undefined;
161
+ modelContext?: string | undefined;
158
162
  };
159
163
 
160
164
  export type SyncSessionRealtimeLedgerInput = AssertSessionRealtimeOwnerInput & {
165
+ /** Request-scoped callers bound the control prefix wait; lifecycle callers omit it. */
166
+ controlLockTimeoutMs?: number;
161
167
  connectionId: string;
162
168
  connectionEpoch: number;
163
169
  entries?: SessionRealtimeInboundEntryInput[] | undefined;
@@ -1016,12 +1022,34 @@ function canonicalJsonValue(value: unknown): unknown {
1016
1022
  return value;
1017
1023
  }
1018
1024
 
1025
+ function normalizedModelContext(input: SessionRealtimeInboundEntryInput): string | null {
1026
+ const value = input.modelContext?.trim();
1027
+ if (!value) {
1028
+ if (input.modelContext !== undefined) {
1029
+ throw new Error("Realtime modelContext must not be empty");
1030
+ }
1031
+ return null;
1032
+ }
1033
+ if (value.length > 32_768) {
1034
+ throw new Error("Realtime modelContext exceeds the server limit");
1035
+ }
1036
+ if (
1037
+ input.kind !== "delegation_call" &&
1038
+ input.kind !== "user_transcript" &&
1039
+ input.kind !== "assistant_transcript"
1040
+ ) {
1041
+ throw new Error("Realtime modelContext requires a delegation or finalized transcript");
1042
+ }
1043
+ return value;
1044
+ }
1045
+
1019
1046
  function inboundReplayMatches(
1020
1047
  row: EntryRow,
1021
1048
  input: SessionRealtimeInboundEntryInput,
1022
1049
  role: "user" | "assistant" | null,
1023
1050
  text: string | null,
1024
1051
  payload: Record<string, unknown>,
1052
+ modelContext: string | null,
1025
1053
  ): boolean {
1026
1054
  const storedText =
1027
1055
  row.text === null ? null : fromPostgresLosslessText(row.text, row.textCodecVersion);
@@ -1034,11 +1062,32 @@ function inboundReplayMatches(
1034
1062
  row.delegationItemId === (input.delegationItemId ?? null) &&
1035
1063
  row.sourceUpdateId === null &&
1036
1064
  storedText === text &&
1065
+ row.modelContext === modelContext &&
1037
1066
  JSON.stringify(canonicalJsonValue(storedPayload)) ===
1038
1067
  JSON.stringify(canonicalJsonValue(payload))
1039
1068
  );
1040
1069
  }
1041
1070
 
1071
+ async function delegationModelContextMatches(
1072
+ db: Database,
1073
+ row: EntryRow,
1074
+ modelContext: string | null,
1075
+ ): Promise<boolean> {
1076
+ if (row.kind !== "delegation_call" || row.turnId === null) return true;
1077
+ const [turn] = await db
1078
+ .select({ modelContext: schema.sessionTurns.modelContext })
1079
+ .from(schema.sessionTurns)
1080
+ .where(
1081
+ and(
1082
+ eq(schema.sessionTurns.workspaceId, row.workspaceId),
1083
+ eq(schema.sessionTurns.sessionId, row.sessionId),
1084
+ eq(schema.sessionTurns.id, row.turnId),
1085
+ ),
1086
+ )
1087
+ .limit(1);
1088
+ return turn?.modelContext === modelContext;
1089
+ }
1090
+
1042
1091
  async function appendInvalidDelegationFailure(
1043
1092
  db: Database,
1044
1093
  input: Pick<
@@ -1083,6 +1132,7 @@ async function admitRealtimeDelegationInTransaction(
1083
1132
  accountId: string,
1084
1133
  incoming: SessionRealtimeInboundEntryInput,
1085
1134
  entryId: string,
1135
+ modelContext: string | null,
1086
1136
  ): Promise<{ turnId: string; eventIds: string[]; wakeRevision: number }> {
1087
1137
  const [session] = await db
1088
1138
  .select()
@@ -1097,7 +1147,8 @@ async function admitRealtimeDelegationInTransaction(
1097
1147
  if (!session || session.accountId !== accountId || session.status === "cancelled") {
1098
1148
  throw new SessionRealtimeConflictError("REALTIME_NOT_FOUND", "Session not found");
1099
1149
  }
1100
- const reasoning = ReasoningEffort.safeParse(session.metadata.reasoningEffort);
1150
+ const sessionReasoning = ReasoningEffort.parse(session.reasoningEffort);
1151
+ const sessionLatency = LatencyMode.parse(session.latencyMode);
1101
1152
  const [latestStarted] = await db
1102
1153
  .select({
1103
1154
  model: schema.sessionTurns.model,
@@ -1142,6 +1193,7 @@ async function admitRealtimeDelegationInTransaction(
1142
1193
  operationKey: incoming.operationId,
1143
1194
  delivery: "steer",
1144
1195
  text: incoming.text!,
1196
+ modelContext,
1145
1197
  messagePresentation: {
1146
1198
  kind: "realtime_voice",
1147
1199
  text: inputTranscript,
@@ -1149,13 +1201,9 @@ async function admitRealtimeDelegationInTransaction(
1149
1201
  },
1150
1202
  resources: [],
1151
1203
  model: latestStarted?.model ?? session.model,
1152
- reasoningEffort: latestReasoning.success
1153
- ? latestReasoning.data
1154
- : reasoning.success
1155
- ? reasoning.data
1156
- : "medium",
1157
- latencyMode: latestLatency.success ? latestLatency.data : "standard",
1158
- reasoningEffortFallback: reasoning.success ? reasoning.data : "medium",
1204
+ reasoningEffort: latestReasoning.success ? latestReasoning.data : sessionReasoning,
1205
+ latencyMode: latestLatency.success ? latestLatency.data : sessionLatency,
1206
+ reasoningEffortFallback: sessionReasoning,
1159
1207
  turnMetadata: {
1160
1208
  realtimeDelegation: { ...provenance, inputTranscript },
1161
1209
  },
@@ -1277,8 +1325,17 @@ export async function syncSessionRealtimeLedgerInTransaction(
1277
1325
  throw new Error("Realtime ledger batch exceeds the server limit");
1278
1326
  }
1279
1327
  // Realtime sync may admit canonical Steer work. Preserve the global lock
1280
- // order before owner proof locks the session row.
1281
- await lockWorkspaceInferenceControl(db, input.workspaceId, "update");
1328
+ // order before owner proof locks the session row. The prefix is shared while
1329
+ // the session branch is active; the delegation Steer below re-enters the same
1330
+ // admission helper and observes this already-held prefix.
1331
+ await lockWorkspaceInferenceControlForAdmission(db, {
1332
+ workspaceId: input.workspaceId,
1333
+ sessionId: input.sessionId,
1334
+ resumePausedBranch: true,
1335
+ ...(input.controlLockTimeoutMs !== undefined
1336
+ ? { lockTimeoutMs: input.controlLockTimeoutMs }
1337
+ : {}),
1338
+ });
1282
1339
  const mode = await assertSessionRealtimeOwnerInTransaction(db, input);
1283
1340
  if (mode.connectionEpoch !== input.connectionEpoch) {
1284
1341
  throw new SessionRealtimeConflictError(
@@ -1359,6 +1416,7 @@ export async function syncSessionRealtimeLedgerInTransaction(
1359
1416
  const payload = boundedPayload(incoming.payload);
1360
1417
  const role = expectedRole(incoming);
1361
1418
  const text = incoming.text ?? null;
1419
+ const modelContext = normalizedModelContext(incoming);
1362
1420
  assertBoundedString(text, SESSION_REALTIME_LEDGER_MAX_TEXT_BYTES, "Realtime text");
1363
1421
  if (
1364
1422
  (incoming.kind === "user_transcript" || incoming.kind === "assistant_transcript") &&
@@ -1392,7 +1450,10 @@ export async function syncSessionRealtimeLedgerInTransaction(
1392
1450
  )
1393
1451
  .limit(1);
1394
1452
  if (existing) {
1395
- if (!inboundReplayMatches(existing, incoming, role, text, payload)) {
1453
+ if (
1454
+ !inboundReplayMatches(existing, incoming, role, text, payload, modelContext) ||
1455
+ !(await delegationModelContextMatches(db, existing, modelContext))
1456
+ ) {
1396
1457
  throw new SessionRealtimeConflictError(
1397
1458
  incoming.kind === "delegation_call"
1398
1459
  ? "REALTIME_DELEGATION_CHANGED"
@@ -1423,6 +1484,7 @@ export async function syncSessionRealtimeLedgerInTransaction(
1423
1484
  textCodecVersion: LOSSLESS_CONTENT_CODEC_VERSION,
1424
1485
  payload,
1425
1486
  payloadCodecVersion: LOSSLESS_CONTENT_CODEC_VERSION,
1487
+ modelContext,
1426
1488
  createdAt: now,
1427
1489
  updatedAt: now,
1428
1490
  })
@@ -1447,6 +1509,7 @@ export async function syncSessionRealtimeLedgerInTransaction(
1447
1509
  modeRow.accountId,
1448
1510
  incoming,
1449
1511
  entry.id,
1512
+ modelContext,
1450
1513
  );
1451
1514
  const [linked] = await db
1452
1515
  .update(schema.sessionRealtimeEntries)
@@ -215,7 +215,7 @@ export function renderRealtimeHumanInputRequestContext(input: {
215
215
  lines.push(" </options>");
216
216
  }
217
217
  lines.push(
218
- ` <allow_other>${String(question.allowOther)}</allow_other>`,
218
+ ` <allow_other>${String(question.kind !== "text")}</allow_other>`,
219
219
  " </question>",
220
220
  );
221
221
  }