@opengeni/db 0.28.9 → 0.36.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 (225) hide show
  1. package/dist/attached-browser-devices.d.ts +42 -0
  2. package/dist/attempt-tool-catalogs.d.ts +16 -0
  3. package/dist/browser-auth.d.ts +299 -0
  4. package/dist/browser-downloads.d.ts +51 -0
  5. package/dist/browser-identities.d.ts +137 -0
  6. package/dist/browser-sessions.d.ts +354 -0
  7. package/dist/browser-state-artifacts.d.ts +91 -0
  8. package/dist/canonical-human-identities.d.ts +48 -0
  9. package/dist/canonical-human-identities.js +28 -0
  10. package/dist/canonical-human-identities.js.map +1 -0
  11. package/dist/capability-components.d.ts +37 -0
  12. package/dist/capability-integrations.d.ts +194 -0
  13. package/dist/chunk-5KTIEDX7.js +13200 -0
  14. package/dist/chunk-5KTIEDX7.js.map +1 -0
  15. package/dist/chunk-CQZ4QSP5.js +995 -0
  16. package/dist/chunk-CQZ4QSP5.js.map +1 -0
  17. package/dist/chunk-F32YT7MP.js +117 -0
  18. package/dist/chunk-F32YT7MP.js.map +1 -0
  19. package/dist/chunk-JC5QPLUM.js +666 -0
  20. package/dist/chunk-JC5QPLUM.js.map +1 -0
  21. package/dist/chunk-P3RE4D2B.js +3535 -0
  22. package/dist/chunk-P3RE4D2B.js.map +1 -0
  23. package/dist/chunk-TAUTWOS5.js +259 -0
  24. package/dist/chunk-TAUTWOS5.js.map +1 -0
  25. package/dist/chunk-VKLB2ZGI.js +2389 -0
  26. package/dist/chunk-VKLB2ZGI.js.map +1 -0
  27. package/dist/codemode-operations.d.ts +117 -0
  28. package/dist/codex-token-resolver.d.ts +2 -2
  29. package/dist/company-profile-schema.d.ts +798 -0
  30. package/dist/company-profile.d.ts +268 -0
  31. package/dist/computer-sessions.d.ts +109 -0
  32. package/dist/connection-token-resolver.d.ts +9 -4
  33. package/dist/database.d.ts +57 -3
  34. package/dist/editable-artifact-durable-export.d.ts +153 -0
  35. package/dist/editable-artifact-durable-export.js +788 -0
  36. package/dist/editable-artifact-durable-export.js.map +1 -0
  37. package/dist/editable-artifact-materialization.d.ts +123 -0
  38. package/dist/editable-artifacts-schema.d.ts +4152 -0
  39. package/dist/editable-artifacts.d.ts +610 -0
  40. package/dist/editable-artifacts.js +26 -0
  41. package/dist/editable-artifacts.js.map +1 -0
  42. package/dist/generated-images.d.ts +139 -0
  43. package/dist/index.d.ts +1122 -126
  44. package/dist/index.js +42329 -18407
  45. package/dist/index.js.map +1 -1
  46. package/dist/insights.d.ts +73 -10
  47. package/dist/integration-bindings.d.ts +70 -0
  48. package/dist/integration-facets.d.ts +99 -0
  49. package/dist/interaction-revisions.d.ts +14 -0
  50. package/dist/interaction-schema.d.ts +6036 -0
  51. package/dist/knowledge-source-sync-schema.d.ts +1679 -0
  52. package/dist/knowledge-source-sync.d.ts +274 -0
  53. package/dist/memory-governance.d.ts +2 -2
  54. package/dist/memory-slack-delivery.d.ts +101 -0
  55. package/dist/new-session-drafts.d.ts +2 -2
  56. package/dist/pack-components.d.ts +76 -0
  57. package/dist/pack-installations.d.ts +86 -0
  58. package/dist/persistence-errors.d.ts +3 -3
  59. package/dist/plugin-packages.d.ts +126 -0
  60. package/dist/preference-registry.d.ts +1 -1
  61. package/dist/provision-roles.d.ts +9 -1
  62. package/dist/provision-roles.js +1 -1
  63. package/dist/runtime-posture.d.ts +19 -6
  64. package/dist/schema.d.ts +22654 -9359
  65. package/dist/schema.js +209 -3
  66. package/dist/scoped-knowledge.d.ts +97 -1
  67. package/dist/session-control.d.ts +33 -7
  68. package/dist/session-queue-commands.d.ts +19 -11
  69. package/dist/session-realtime-context.d.ts +2 -2
  70. package/dist/session-realtime-ledger.d.ts +4 -4
  71. package/dist/session-realtime-mirror.d.ts +2 -2
  72. package/dist/session-realtime-state.d.ts +1 -1
  73. package/dist/session-realtime-terminal.d.ts +1 -1
  74. package/dist/session-realtime.d.ts +7 -7
  75. package/dist/session-tenancy.d.ts +44 -0
  76. package/dist/session-tenancy.js +16 -0
  77. package/dist/session-tenancy.js.map +1 -0
  78. package/dist/session-tool-call-settlement.d.ts +1 -1
  79. package/dist/slack-task-policy-schema.d.ts +847 -0
  80. package/dist/slack-task-policy.d.ts +65 -0
  81. package/dist/slack-user-link-access.d.ts +54 -0
  82. package/dist/task-notes-schema.d.ts +924 -0
  83. package/dist/task-notes.d.ts +85 -0
  84. package/dist/transcription-recordings.d.ts +2 -2
  85. package/dist/turn-initiator.d.ts +2 -2
  86. package/dist/video-generation.d.ts +225 -0
  87. package/dist/video-generation.js +68 -0
  88. package/dist/video-generation.js.map +1 -0
  89. package/dist/workspace-artifacts.d.ts +1 -1
  90. package/dist/workspace-instruction-policies.d.ts +1 -1
  91. package/dist/workspace-learning-policy-schema.d.ts +932 -0
  92. package/dist/workspace-learning-policy.d.ts +161 -0
  93. package/dist/xai-subscription.d.ts +326 -0
  94. package/drizzle/0183_model_call_provider_cost_estimates.sql +39 -0
  95. package/drizzle/0184_sandbox_drain_teardown_fence.sql +682 -0
  96. package/drizzle/0185_temporal_schedule_cleanup_outbox.sql +168 -0
  97. package/drizzle/0186_sandbox_capture_provider_contract.sql +400 -0
  98. package/drizzle/0187_generated_image_artifacts.sql +173 -0
  99. package/drizzle/0188_image_generation_retention_failure.sql +25 -0
  100. package/drizzle/0189_retained_session_image_formats.sql +13 -0
  101. package/drizzle/0190_timeline_annotations.sql +31 -0
  102. package/drizzle/0191_editable_artifact_engine.sql +3853 -0
  103. package/drizzle/0192_editable_artifact_live_tickets.sql +338 -0
  104. package/drizzle/0193_editable_artifact_authorization.sql +190 -0
  105. package/drizzle/0194_editable_artifact_durable_exports.sql +160 -0
  106. package/drizzle/0195_editable_artifact_import_authorization.sql +203 -0
  107. package/drizzle/0196_rig_provider_images.sql +152 -0
  108. package/drizzle/0197_knowledge_source_sync_schedules.sql +523 -0
  109. package/drizzle/0198_memory_slack_publication_delivery.sql +393 -0
  110. package/drizzle/0199_workspace_learning_policy.sql +980 -0
  111. package/drizzle/0201_company_profile_authority.sql +849 -0
  112. package/drizzle/0202_document_index_checkpoints.sql +85 -0
  113. package/drizzle/0203_durable_video_generation.sql +353 -0
  114. package/drizzle/0204_video_generation_funding.sql +44 -0
  115. package/drizzle/0205_attempt_tool_catalogs.sql +230 -0
  116. package/drizzle/0206_browser_sessions.sql +646 -0
  117. package/drizzle/0207_browser_identities.sql +379 -0
  118. package/drizzle/0208_attached_browser_devices.sql +165 -0
  119. package/drizzle/0209_computer_sessions.sql +575 -0
  120. package/drizzle/0210_browser_auth_network_interventions.sql +441 -0
  121. package/drizzle/0211_editable_artifact_session_links.sql +58 -0
  122. package/drizzle/0212_browser_state_transfer_hardening.sql +560 -0
  123. package/drizzle/0212_slack_installation_bindings.sql +348 -0
  124. package/drizzle/0213_browser_interaction_authority.sql +67 -0
  125. package/drizzle/0213_slack_user_link_access_requests.sql +177 -0
  126. package/drizzle/0214_browser_download_saves.sql +34 -0
  127. package/drizzle/0214_session_activity_commit_gate.sql +262 -0
  128. package/drizzle/0215_browser_controller_host.sql +385 -0
  129. package/drizzle/0215_capabilities_platform.sql +980 -0
  130. package/drizzle/0216_browser_auth_health_evidence.sql +137 -0
  131. package/drizzle/0216_pack_component_ownership.sql +235 -0
  132. package/drizzle/0217_capability_definition_delete_authority.sql +32 -0
  133. package/drizzle/0217_external_browser_auth_operations.sql +22 -0
  134. package/drizzle/0218_organization_tenancy_foundation.sql +299 -0
  135. package/drizzle/0219_organization_tenancy_managed_human_provisioning.sql +317 -0
  136. package/drizzle/0219_site_auth_maintenance_sessions.sql +234 -0
  137. package/drizzle/0220_memory_slack_append_only_cascade.sql +38 -0
  138. package/drizzle/0220_session_channels.sql +54 -0
  139. package/drizzle/0221_sessions_channel_index.sql +5 -0
  140. package/drizzle/0222_session_visibility_authority_epochs.sql +158 -0
  141. package/drizzle/0222_sessions_channel_fk.sql +89 -0
  142. package/drizzle/0223_pending_tool_event_output.sql +55 -0
  143. package/drizzle/0223_sessions_channel_fk_validate.sql +118 -0
  144. package/drizzle/0224_slack_post_outcome_reconciliation.sql +123 -0
  145. package/drizzle/0225_session_visibility_fork_activation.sql +1363 -0
  146. package/drizzle/0226_personal_codex_authority_foundation.sql +365 -0
  147. package/drizzle/0227_slack_native_actions.sql +145 -0
  148. package/drizzle/0228_interaction_controller_data_plane.sql +14 -0
  149. package/drizzle/0228_slack_task_policy.sql +400 -0
  150. package/drizzle/0229_slack_inbox_file_fact.sql +10 -0
  151. package/drizzle/0230_user_scoped_variable_sets_rigs.sql +84 -0
  152. package/drizzle/0231_integration_definition_identity_cutover.sql +271 -0
  153. package/drizzle/0232_integration_facet_authority_cutover.sql +610 -0
  154. package/drizzle/0233_skill_and_integration_authority_cutover.sql +1162 -0
  155. package/drizzle/0234_xai_subscription_authority.sql +1139 -0
  156. package/drizzle/0235_canonical_human_login_bindings.sql +920 -0
  157. package/drizzle/0236_browser_identity_lifecycle.sql +39 -0
  158. package/drizzle/0236_session_visibility_slack_policy.sql +72 -0
  159. package/drizzle/0237_interaction_transition_reaper.sql +263 -0
  160. package/drizzle/0238_goal_persistence_policy.sql +471 -0
  161. package/drizzle/0238_supergrok_realtime_model.sql +29 -0
  162. package/drizzle/0239_supergrok_video_funding.sql +50 -0
  163. package/drizzle/0239_task_tree_notes.sql +990 -0
  164. package/package.json +26 -5
  165. package/src/attached-browser-devices.ts +371 -0
  166. package/src/attempt-tool-catalogs.ts +131 -0
  167. package/src/browser-auth.ts +4373 -0
  168. package/src/browser-downloads.ts +517 -0
  169. package/src/browser-identities.ts +1385 -0
  170. package/src/browser-sessions.ts +2294 -0
  171. package/src/browser-state-artifacts.ts +449 -0
  172. package/src/canonical-human-identities.ts +317 -0
  173. package/src/capability-components.ts +166 -0
  174. package/src/capability-integrations.ts +1571 -0
  175. package/src/codemode-operations.ts +674 -0
  176. package/src/company-profile-schema.ts +143 -0
  177. package/src/company-profile.ts +968 -0
  178. package/src/computer-sessions.ts +1130 -0
  179. package/src/connection-token-resolver.ts +270 -25
  180. package/src/database.ts +468 -24
  181. package/src/editable-artifact-durable-export.ts +1201 -0
  182. package/src/editable-artifact-materialization.ts +893 -0
  183. package/src/editable-artifacts-schema.ts +879 -0
  184. package/src/editable-artifacts.ts +5404 -0
  185. package/src/generated-images.ts +740 -0
  186. package/src/index.ts +9963 -1465
  187. package/src/insights.ts +251 -23
  188. package/src/integration-bindings.ts +455 -0
  189. package/src/integration-facets.ts +862 -0
  190. package/src/interaction-revisions.ts +70 -0
  191. package/src/interaction-schema.ts +1606 -0
  192. package/src/knowledge-source-sync-schema.ts +192 -0
  193. package/src/knowledge-source-sync.ts +1922 -0
  194. package/src/memory-slack-delivery.ts +801 -0
  195. package/src/pack-components.ts +954 -0
  196. package/src/pack-installations.ts +886 -0
  197. package/src/persistence-errors.ts +4 -7
  198. package/src/plugin-packages.ts +1186 -0
  199. package/src/provision-roles.ts +534 -1
  200. package/src/runtime-posture-cli.ts +9 -0
  201. package/src/runtime-posture.ts +721 -5
  202. package/src/schema.ts +6270 -3159
  203. package/src/scoped-knowledge-schema.ts +1 -1
  204. package/src/scoped-knowledge.ts +655 -3
  205. package/src/session-control.ts +130 -42
  206. package/src/session-queue-commands.ts +265 -15
  207. package/src/session-realtime-context.ts +2 -2
  208. package/src/session-realtime-ledger.ts +3 -3
  209. package/src/session-realtime.ts +7 -7
  210. package/src/session-tenancy.ts +188 -0
  211. package/src/session-tool-call-settlement.ts +18 -3
  212. package/src/slack-task-policy-schema.ts +130 -0
  213. package/src/slack-task-policy.ts +341 -0
  214. package/src/slack-user-link-access.ts +702 -0
  215. package/src/task-notes-schema.ts +135 -0
  216. package/src/task-notes.ts +178 -0
  217. package/src/video-generation.ts +1530 -0
  218. package/src/workspace-artifacts.ts +1 -1
  219. package/src/workspace-learning-policy-schema.ts +139 -0
  220. package/src/workspace-learning-policy.ts +595 -0
  221. package/src/xai-subscription.ts +1887 -0
  222. package/dist/chunk-P6CUHXQZ.js +0 -7248
  223. package/dist/chunk-P6CUHXQZ.js.map +0 -1
  224. package/dist/chunk-VHBFHMPC.js +0 -1219
  225. package/dist/chunk-VHBFHMPC.js.map +0 -1
@@ -1,20 +1,40 @@
1
1
  import {
2
+ WORKSPACE_XAI_PROVIDER_ACCOUNT_AUTHORITY_SNAPSHOT_V1,
3
+ XaiProviderAccountAuthoritySnapshotV1,
4
+ DraftTimelineAnnotations,
2
5
  McpPersonalConnectionDelegations,
6
+ TimelineAnnotations,
3
7
  metadataWithTurnExecutionPolicyV1,
4
8
  mergeResourceRefs,
9
+ renderTimelineAnnotationsForModel,
5
10
  ResourceRef,
6
11
  resourceMountPath,
7
12
  stableJson,
8
13
  turnExecutionPolicyAuditMetadata,
9
14
  type McpPersonalConnectionDelegation,
15
+ type DraftTimelineAnnotation,
10
16
  type LatencyMode,
11
17
  type ReasoningEffort,
18
+ type SandboxBackend,
19
+ type SandboxOs,
20
+ type SessionEvent,
21
+ type SessionEventType,
22
+ type SessionTurn,
23
+ type SessionTurnSource,
24
+ type SessionTurnStatus,
25
+ type ToolRef,
12
26
  type TurnExecutionPolicyV1,
27
+ type TimelineAnnotation,
13
28
  } from "@opengeni/contracts";
14
29
  import { and, asc, eq, inArray, sql } from "drizzle-orm";
15
- import type { Database } from "./database";
16
- import { withLosslessContentWriteVersion } from "./lossless-json";
30
+ import type { Database, SessionActivityDatabase } from "./database";
31
+ import {
32
+ fromPostgresLosslessJson,
33
+ fromPostgresLosslessText,
34
+ withLosslessContentWriteVersion,
35
+ } from "./lossless-json";
17
36
  import { closePendingSessionToolCallsInTransaction } from "./session-tool-call-settlement";
37
+ import { cancelTurnInteractionInterventionsInTransaction } from "./browser-auth";
18
38
  import {
19
39
  assertAgentCommandAuthorityInTransaction,
20
40
  autoResumeSessionBranchInTransaction,
@@ -44,6 +64,7 @@ import {
44
64
  initiatorFromStorage,
45
65
  type FrozenTurnInitiator,
46
66
  } from "./turn-initiator";
67
+ import { resolveXaiProviderAccountAuthoritySnapshotForAcceptanceInTransaction } from "./xai-subscription";
47
68
 
48
69
  type SessionEventInsertWithPayload = typeof schema.sessionEvents.$inferInsert & {
49
70
  payload: unknown;
@@ -97,6 +118,10 @@ export type SteerQueueCommandResult = QueueCommandResult & {
97
118
  export type SubmitHumanPromptResult = {
98
119
  receipt: SessionCommandReceiptRow;
99
120
  queueVersion: number;
121
+ accepted: SessionEvent;
122
+ events: SessionEvent[];
123
+ turn: SessionTurn;
124
+ /** Backward-compatible row identities for lower-level callers. */
100
125
  acceptedEventId: string;
101
126
  eventIds: string[];
102
127
  turnId: string;
@@ -106,6 +131,69 @@ export type SubmitHumanPromptResult = {
106
131
  replay: boolean;
107
132
  };
108
133
 
134
+ function mapSubmittedPromptEvent(row: typeof schema.sessionEvents.$inferSelect): SessionEvent {
135
+ return {
136
+ id: row.id,
137
+ workspaceId: row.workspaceId,
138
+ sessionId: row.sessionId,
139
+ sequence: row.sequence,
140
+ type: row.type as SessionEventType,
141
+ payload: fromPostgresLosslessJson(row.payload, row.payloadCodecVersion),
142
+ occurredAt: row.occurredAt.toISOString(),
143
+ clientEventId: row.clientEventId,
144
+ turnId: row.turnId,
145
+ turnGeneration: row.turnGeneration,
146
+ turnAttemptId: row.turnAttemptId,
147
+ turnAssociation: row.turnAssociation as SessionEvent["turnAssociation"],
148
+ duplicateOfEventId: row.duplicateOfEventId,
149
+ duplicateReason: row.duplicateReason,
150
+ };
151
+ }
152
+
153
+ function mapSubmittedPromptTurn(row: typeof schema.sessionTurns.$inferSelect): SessionTurn {
154
+ const personalConnections = McpPersonalConnectionDelegations.parse(
155
+ row.personalConnectionDelegations,
156
+ ).map(({ serverId, providerDomain }) => ({ serverId, providerDomain }));
157
+ return {
158
+ id: row.id,
159
+ workspaceId: row.workspaceId,
160
+ sessionId: row.sessionId,
161
+ triggerEventId: row.triggerEventId,
162
+ temporalWorkflowId: row.temporalWorkflowId,
163
+ status: row.status as SessionTurnStatus,
164
+ source: row.source as SessionTurnSource,
165
+ position: row.position,
166
+ prompt: fromPostgresLosslessText(row.prompt, row.promptCodecVersion),
167
+ annotations: TimelineAnnotations.parse(row.annotations),
168
+ resources: row.resources as ResourceRef[],
169
+ tools: row.tools as ToolRef[],
170
+ toolsProvided: row.toolsProvided,
171
+ model: row.model,
172
+ reasoningEffort: row.reasoningEffort as ReasoningEffort,
173
+ latencyMode: (row.latencyMode as LatencyMode | null | undefined) ?? "standard",
174
+ sandboxBackend: row.sandboxBackend as SandboxBackend,
175
+ sandboxOs: (row.sandboxOs as SandboxOs | null) ?? null,
176
+ metadata: row.metadata,
177
+ version: row.version,
178
+ executionGeneration: row.executionGeneration,
179
+ activeAttemptId: row.activeAttemptId,
180
+ lineage: row.lineage,
181
+ initiator: initiatorFromStorage(
182
+ row.initiatorKind,
183
+ row.initiatorSubjectId,
184
+ row.initiatorContext ?? {},
185
+ ),
186
+ initiatorContext: row.initiatorContext ?? {},
187
+ personalConnections,
188
+ cancelledBy: row.cancelledBy,
189
+ cancelReason: row.cancelReason,
190
+ startedAt: row.startedAt ? row.startedAt.toISOString() : null,
191
+ finishedAt: row.finishedAt ? row.finishedAt.toISOString() : null,
192
+ createdAt: row.createdAt.toISOString(),
193
+ updatedAt: row.updatedAt.toISOString(),
194
+ };
195
+ }
196
+
109
197
  export type AgentInternalUpdateCommandResult = {
110
198
  receipt: SessionCommandReceiptRow;
111
199
  updateId: string;
@@ -149,6 +237,43 @@ async function personalConnectionDelegationsForAgentActor(
149
237
  return parsed.data.map((delegation) => ({ ...delegation }));
150
238
  }
151
239
 
240
+ async function xaiAuthorityForAgentActor(
241
+ db: Database,
242
+ workspaceId: string,
243
+ actor: Extract<SessionCommandActor, { type: "agent_attempt" }>,
244
+ ): Promise<{
245
+ snapshot: ReturnType<typeof XaiProviderAccountAuthoritySnapshotV1.parse>;
246
+ subjectId: string | null;
247
+ }> {
248
+ const [row] = await db
249
+ .select({
250
+ snapshot: schema.sessionTurns.xaiProviderAccountAuthoritySnapshot,
251
+ initiatingHumanSubjectId: schema.sessionTurns.initiatingHumanSubjectId,
252
+ initiatorKind: schema.sessionTurns.initiatorKind,
253
+ initiatorSubjectId: schema.sessionTurns.initiatorSubjectId,
254
+ })
255
+ .from(schema.sessionTurns)
256
+ .where(
257
+ and(
258
+ eq(schema.sessionTurns.workspaceId, workspaceId),
259
+ eq(schema.sessionTurns.sessionId, actor.sessionId),
260
+ eq(schema.sessionTurns.id, actor.turnId),
261
+ ),
262
+ )
263
+ .limit(1);
264
+ if (!row) {
265
+ throw new SessionControlInvariantError(
266
+ `Agent xAI authority turn not found: ${actor.sessionId}/${actor.turnId}`,
267
+ );
268
+ }
269
+ return {
270
+ snapshot: XaiProviderAccountAuthoritySnapshotV1.parse(row.snapshot),
271
+ subjectId:
272
+ row.initiatingHumanSubjectId ??
273
+ (row.initiatorKind === "subject" ? row.initiatorSubjectId : null),
274
+ };
275
+ }
276
+
152
277
  async function lockSession(
153
278
  db: Database,
154
279
  workspaceId: string,
@@ -260,6 +385,12 @@ export async function supersedeSessionCurrentDirectionInTransaction(
260
385
  }
261
386
 
262
387
  const now = new Date();
388
+ await cancelTurnInteractionInterventionsInTransaction(db, {
389
+ accountId: input.accountId,
390
+ workspaceId: input.workspaceId,
391
+ sessionId: input.sessionId,
392
+ turnId: current.id,
393
+ });
263
394
  const closedTools = await closePendingSessionToolCallsInTransaction(db, {
264
395
  accountId: input.accountId,
265
396
  workspaceId: input.workspaceId,
@@ -308,7 +439,10 @@ export async function supersedeSessionCurrentDirectionInTransaction(
308
439
  turnId: current.id,
309
440
  turnGeneration: current.executionGeneration,
310
441
  turnAssociation: "current",
311
- payload: { requestId: request.id, response: { outcome: "cancelled" } },
442
+ payload: {
443
+ requestId: request.id,
444
+ response: { outcome: "cancelled" },
445
+ },
312
446
  occurredAt: now,
313
447
  })),
314
448
  "payload",
@@ -370,6 +504,17 @@ export async function supersedeSessionCurrentDirectionInTransaction(
370
504
  eq(schema.codexCapacityWaiters.status, "waiting"),
371
505
  ),
372
506
  );
507
+ await db
508
+ .update(schema.xaiCapacityWaiters)
509
+ .set({ status: "superseded", lastWakeReason: "steer", updatedAt: now })
510
+ .where(
511
+ and(
512
+ eq(schema.xaiCapacityWaiters.workspaceId, input.workspaceId),
513
+ eq(schema.xaiCapacityWaiters.sessionId, input.sessionId),
514
+ eq(schema.xaiCapacityWaiters.blockedTurnId, current.id),
515
+ eq(schema.xaiCapacityWaiters.status, "waiting"),
516
+ ),
517
+ );
373
518
  }
374
519
  return {
375
520
  interruptionCount: 0,
@@ -414,7 +559,7 @@ async function loadQueuedTurns(
414
559
  }
415
560
 
416
561
  async function normalizeQueuePositions(
417
- db: Database,
562
+ db: SessionActivityDatabase,
418
563
  workspaceId: string,
419
564
  sessionId: string,
420
565
  orderedIds: string[],
@@ -446,7 +591,19 @@ async function normalizeQueuePositions(
446
591
  }
447
592
 
448
593
  function draftIsNonEmpty(draft: ComposerDraftRow): boolean {
449
- return draft.text.length > 0 || draft.resources.length > 0 || draft.sourceTurnId !== null;
594
+ return (
595
+ draft.text.length > 0 ||
596
+ DraftTimelineAnnotations.parse(draft.annotations).length > 0 ||
597
+ draft.resources.length > 0 ||
598
+ draft.sourceTurnId !== null
599
+ );
600
+ }
601
+
602
+ function draftAnnotationsFromTurn(value: unknown): DraftTimelineAnnotation[] {
603
+ return TimelineAnnotations.parse(value).map(({ ordinal: _ordinal, ...annotation }) => ({
604
+ ...annotation,
605
+ source: { ...annotation.source },
606
+ }));
450
607
  }
451
608
 
452
609
  function withCanonicalResourceMountPaths(resources: readonly unknown[]): unknown[] {
@@ -503,6 +660,7 @@ export async function saveComposerDraftInTransaction(
503
660
  subjectId: string;
504
661
  expectedRevision: number;
505
662
  text: string;
663
+ annotations?: DraftTimelineAnnotation[];
506
664
  resources: ResourceRef[];
507
665
  model: string;
508
666
  reasoningEffort: ReasoningEffort;
@@ -534,6 +692,7 @@ export async function saveComposerDraftInTransaction(
534
692
  subjectId: input.subjectId,
535
693
  revision,
536
694
  text: input.text,
695
+ annotations: DraftTimelineAnnotations.parse(input.annotations ?? []),
537
696
  resources: withCanonicalResourceMountPaths(input.resources),
538
697
  tools: [],
539
698
  toolsProvided: false,
@@ -559,7 +718,7 @@ export async function saveComposerDraftInTransaction(
559
718
  }
560
719
 
561
720
  export async function moveQueuedTurnInTransaction(
562
- db: Database,
721
+ db: SessionActivityDatabase,
563
722
  input: {
564
723
  accountId: string;
565
724
  workspaceId: string;
@@ -695,7 +854,7 @@ export async function moveQueuedTurnInTransaction(
695
854
  }
696
855
 
697
856
  export async function deleteSessionQueueItemInTransaction(
698
- db: Database,
857
+ db: SessionActivityDatabase,
699
858
  input: {
700
859
  accountId: string;
701
860
  workspaceId: string;
@@ -826,7 +985,7 @@ export async function deleteSessionQueueItemInTransaction(
826
985
  }
827
986
 
828
987
  export async function editQueuedTurnInTransaction(
829
- db: Database,
988
+ db: SessionActivityDatabase,
830
989
  input: {
831
990
  accountId: string;
832
991
  workspaceId: string;
@@ -919,6 +1078,7 @@ export async function editQueuedTurnInTransaction(
919
1078
  subjectId: input.subjectId,
920
1079
  revision: nextDraftRevision,
921
1080
  text: turn.prompt,
1081
+ annotations: draftAnnotationsFromTurn(turn.annotations),
922
1082
  resources: withCanonicalResourceMountPaths(turn.resources),
923
1083
  tools: [],
924
1084
  toolsProvided: false,
@@ -1007,7 +1167,7 @@ export async function editQueuedTurnInTransaction(
1007
1167
  }
1008
1168
 
1009
1169
  export async function steerQueuedTurnInTransaction(
1010
- db: Database,
1170
+ db: SessionActivityDatabase,
1011
1171
  input: {
1012
1172
  accountId: string;
1013
1173
  workspaceId: string;
@@ -1240,7 +1400,7 @@ export async function steerQueuedTurnInTransaction(
1240
1400
  }
1241
1401
 
1242
1402
  export async function submitHumanPromptInTransaction(
1243
- db: Database,
1403
+ db: SessionActivityDatabase,
1244
1404
  input: {
1245
1405
  accountId: string;
1246
1406
  workspaceId: string;
@@ -1253,6 +1413,7 @@ export async function submitHumanPromptInTransaction(
1253
1413
  controlEtag?: string | null;
1254
1414
  expectedDraftRevision?: number | null;
1255
1415
  text: string;
1416
+ annotations?: TimelineAnnotation[];
1256
1417
  turnInstructions?: string | null;
1257
1418
  resources: ResourceRef[];
1258
1419
  model?: string | null;
@@ -1270,6 +1431,8 @@ export async function submitHumanPromptInTransaction(
1270
1431
  context: string;
1271
1432
  };
1272
1433
  source: "user" | "api";
1434
+ /** Record the admitted run's durable usage fact in this transaction. */
1435
+ recordAgentRunUsage?: boolean;
1273
1436
  personalConnectionDelegations?: McpPersonalConnectionDelegation[];
1274
1437
  mcpCredentialUpdates?: Array<{
1275
1438
  id: string;
@@ -1277,6 +1440,7 @@ export async function submitHumanPromptInTransaction(
1277
1440
  }>;
1278
1441
  },
1279
1442
  ): Promise<SubmitHumanPromptResult> {
1443
+ const annotations = TimelineAnnotations.parse(input.annotations ?? []);
1280
1444
  const workspaceControl = await lockWorkspaceInferenceControl(db, input.workspaceId, "update");
1281
1445
  await lockSessionEventWriteRows(db, {
1282
1446
  workspaceId: input.workspaceId,
@@ -1293,6 +1457,7 @@ export async function submitHumanPromptInTransaction(
1293
1457
  controlEtag: input.controlEtag ?? null,
1294
1458
  expectedDraftRevision: input.expectedDraftRevision ?? null,
1295
1459
  text: input.text,
1460
+ annotations,
1296
1461
  turnInstructions: input.turnInstructions ?? null,
1297
1462
  resources: withCanonicalResourceMountPaths(input.resources),
1298
1463
  model: input.model ?? null,
@@ -1332,9 +1497,39 @@ export async function submitHumanPromptInTransaction(
1332
1497
  if (!turnId || !acceptedEventId || wakeRevision < 1) {
1333
1498
  throw new SessionControlInvariantError("Replayed prompt receipt is incomplete");
1334
1499
  }
1500
+ const replayEvents = await db
1501
+ .select()
1502
+ .from(schema.sessionEvents)
1503
+ .where(
1504
+ and(
1505
+ eq(schema.sessionEvents.workspaceId, input.workspaceId),
1506
+ eq(schema.sessionEvents.sessionId, input.sessionId),
1507
+ inArray(schema.sessionEvents.id, eventIds),
1508
+ ),
1509
+ )
1510
+ .orderBy(asc(schema.sessionEvents.sequence));
1511
+ const [replayTurn] = await db
1512
+ .select()
1513
+ .from(schema.sessionTurns)
1514
+ .where(
1515
+ and(
1516
+ eq(schema.sessionTurns.workspaceId, input.workspaceId),
1517
+ eq(schema.sessionTurns.sessionId, input.sessionId),
1518
+ eq(schema.sessionTurns.id, turnId),
1519
+ ),
1520
+ )
1521
+ .limit(1);
1522
+ const events = replayEvents.map(mapSubmittedPromptEvent);
1523
+ const accepted = events.find((event) => event.id === acceptedEventId);
1524
+ if (!accepted || !replayTurn || events.length !== eventIds.length) {
1525
+ throw new SessionControlInvariantError("Replayed prompt rows are incomplete");
1526
+ }
1335
1527
  return {
1336
1528
  receipt: reserved.receipt,
1337
1529
  queueVersion: Number(reserved.receipt.appliedQueueVersion),
1530
+ accepted,
1531
+ events,
1532
+ turn: mapSubmittedPromptTurn(replayTurn),
1338
1533
  acceptedEventId,
1339
1534
  eventIds,
1340
1535
  turnId,
@@ -1404,6 +1599,7 @@ export async function submitHumanPromptInTransaction(
1404
1599
  draft &&
1405
1600
  canonicalSessionCommandHash({
1406
1601
  text: draft.text,
1602
+ annotations: DraftTimelineAnnotations.parse(draft.annotations),
1407
1603
  resources: withCanonicalResourceMountPaths(draft.resources),
1408
1604
  model: draft.model,
1409
1605
  reasoningEffort: draft.reasoningEffort,
@@ -1411,6 +1607,7 @@ export async function submitHumanPromptInTransaction(
1411
1607
  }) !==
1412
1608
  canonicalSessionCommandHash({
1413
1609
  text: input.text,
1610
+ annotations: annotations.map(({ ordinal: _ordinal, ...annotation }) => annotation),
1414
1611
  resources: withCanonicalResourceMountPaths(input.resources),
1415
1612
  model: input.model ?? session.model,
1416
1613
  reasoningEffort: input.reasoningEffort ?? input.reasoningEffortFallback,
@@ -1516,6 +1713,15 @@ export async function submitHumanPromptInTransaction(
1516
1713
  input.subjectLabel,
1517
1714
  );
1518
1715
  }
1716
+ const xaiProviderAccountAuthoritySnapshot = editedSourceTurn
1717
+ ? XaiProviderAccountAuthoritySnapshotV1.parse(
1718
+ editedSourceTurn.xaiProviderAccountAuthoritySnapshot,
1719
+ )
1720
+ : input.actor.type === "human"
1721
+ ? await resolveXaiProviderAccountAuthoritySnapshotForAcceptanceInTransaction(db, {
1722
+ workspaceId: input.workspaceId,
1723
+ })
1724
+ : WORKSPACE_XAI_PROVIDER_ACCOUNT_AUTHORITY_SNAPSHOT_V1;
1519
1725
  const acceptedEventId = crypto.randomUUID();
1520
1726
  const turnId = crypto.randomUUID();
1521
1727
  const workflowId = session.temporalWorkflowId ?? `session-${session.id}`;
@@ -1531,6 +1737,7 @@ export async function submitHumanPromptInTransaction(
1531
1737
  clientEventId: input.operationKey,
1532
1738
  payload: {
1533
1739
  text: input.messagePresentation?.text ?? input.text,
1740
+ ...(annotations.length > 0 ? { annotations } : {}),
1534
1741
  ...(input.messagePresentation
1535
1742
  ? {
1536
1743
  presentation: {
@@ -1565,6 +1772,7 @@ export async function submitHumanPromptInTransaction(
1565
1772
  source: input.source,
1566
1773
  position: input.delivery === "steer" ? 0 : existingQueued.length + 1,
1567
1774
  prompt: input.text,
1775
+ annotations,
1568
1776
  turnInstructions:
1569
1777
  editedSourceTurnInstructions !== undefined
1570
1778
  ? editedSourceTurnInstructions
@@ -1592,6 +1800,7 @@ export async function submitHumanPromptInTransaction(
1592
1800
  personalConnectionDelegations: editedSourceTurn
1593
1801
  ? editedSourceTurn.personalConnectionDelegations
1594
1802
  : (input.personalConnectionDelegations ?? []),
1803
+ xaiProviderAccountAuthoritySnapshot,
1595
1804
  createdAt: now,
1596
1805
  updatedAt: now,
1597
1806
  },
@@ -1601,6 +1810,7 @@ export async function submitHumanPromptInTransaction(
1601
1810
  )
1602
1811
  .returning();
1603
1812
  if (!turn) throw new SessionControlInvariantError("Prompt turn was not inserted");
1813
+ let committedTurn = turn;
1604
1814
  eventValues.push({
1605
1815
  accountId: input.accountId,
1606
1816
  workspaceId: input.workspaceId,
@@ -1651,7 +1861,7 @@ export async function submitHumanPromptInTransaction(
1651
1861
  // settlement has already cleared sessions.active_turn_id. Do not infer this
1652
1862
  // state from a local request spinner or queue position.
1653
1863
  if (input.delivery === "steer") {
1654
- await db
1864
+ const [updatedTurn] = await db
1655
1865
  .update(schema.sessionTurns)
1656
1866
  .set({
1657
1867
  metadata: {
@@ -1669,7 +1879,12 @@ export async function submitHumanPromptInTransaction(
1669
1879
  eq(schema.sessionTurns.sessionId, input.sessionId),
1670
1880
  eq(schema.sessionTurns.id, turnId),
1671
1881
  ),
1672
- );
1882
+ )
1883
+ .returning();
1884
+ if (!updatedTurn) {
1885
+ throw new SessionControlInvariantError("Steer prompt turn metadata was not updated");
1886
+ }
1887
+ committedTurn = updatedTurn;
1673
1888
  }
1674
1889
  if (supersession.replacedTurn) {
1675
1890
  const current = supersession.replacedTurn;
@@ -1749,7 +1964,7 @@ export async function submitHumanPromptInTransaction(
1749
1964
  text: renderRealtimeHumanInputContext({
1750
1965
  delivery: input.delivery,
1751
1966
  routing: realtimeRouting,
1752
- text: input.text,
1967
+ text: renderTimelineAnnotationsForModel(input.text, annotations),
1753
1968
  }),
1754
1969
  payload: {
1755
1970
  delivery: input.delivery,
@@ -1811,6 +2026,27 @@ export async function submitHumanPromptInTransaction(
1811
2026
  "metadataCodecVersion",
1812
2027
  ),
1813
2028
  );
2029
+ if (input.recordAgentRunUsage) {
2030
+ await db
2031
+ .insert(schema.usageEvents)
2032
+ .values({
2033
+ accountId: input.accountId,
2034
+ workspaceId: input.workspaceId,
2035
+ subjectId: input.subjectId,
2036
+ eventType: "agent_run.created",
2037
+ quantity: 1,
2038
+ unit: "run",
2039
+ sourceResourceType: "session_turn",
2040
+ sourceResourceId: turnId,
2041
+ sessionId: input.sessionId,
2042
+ turnId,
2043
+ ...initiatorColumns(frozenInitiator),
2044
+ origin: input.source,
2045
+ idempotencyKey: `agent_run.created:${input.workspaceId}:${turnId}`,
2046
+ occurredAt: now,
2047
+ })
2048
+ .onConflictDoNothing({ target: schema.usageEvents.idempotencyKey });
2049
+ }
1814
2050
  const eventIds = eventRows.map((event) => event.id);
1815
2051
  const receipt = await updateSessionCommandReceiptResult(db, reserved.receipt.id, {
1816
2052
  controlRevision: resumed.revision,
@@ -1832,9 +2068,17 @@ export async function submitHumanPromptInTransaction(
1832
2068
  : {}),
1833
2069
  },
1834
2070
  });
2071
+ const events = eventRows.map(mapSubmittedPromptEvent);
2072
+ const accepted = events.find((event) => event.id === acceptedEventId);
2073
+ if (!accepted) {
2074
+ throw new SessionControlInvariantError("Inserted user.message event is missing");
2075
+ }
1835
2076
  return {
1836
2077
  receipt,
1837
2078
  queueVersion,
2079
+ accepted,
2080
+ events,
2081
+ turn: mapSubmittedPromptTurn(committedTurn),
1838
2082
  acceptedEventId,
1839
2083
  eventIds,
1840
2084
  turnId,
@@ -1846,7 +2090,7 @@ export async function submitHumanPromptInTransaction(
1846
2090
  }
1847
2091
 
1848
2092
  export async function sendAgentMessageInTransaction(
1849
- db: Database,
2093
+ db: SessionActivityDatabase,
1850
2094
  input: {
1851
2095
  accountId: string;
1852
2096
  workspaceId: string;
@@ -1910,6 +2154,7 @@ export async function sendAgentMessageInTransaction(
1910
2154
  input.workspaceId,
1911
2155
  input.actor,
1912
2156
  );
2157
+ const xaiAuthority = await xaiAuthorityForAgentActor(db, input.workspaceId, input.actor);
1913
2158
  const session = await lockSession(db, input.workspaceId, input.targetSessionId);
1914
2159
  if (session.status === "cancelled") {
1915
2160
  throw new QueueCommandConflictError(
@@ -1951,8 +2196,10 @@ export async function sendAgentMessageInTransaction(
1951
2196
  callerTurnId: input.actor.turnId,
1952
2197
  callerAttemptId: input.actor.attemptId,
1953
2198
  callerExecutionGeneration: input.actor.executionGeneration,
2199
+ ...(xaiAuthority.subjectId ? { xaiAuthoritySubjectId: xaiAuthority.subjectId } : {}),
1954
2200
  },
1955
2201
  personalConnectionDelegations,
2202
+ xaiProviderAccountAuthoritySnapshot: xaiAuthority.snapshot,
1956
2203
  state: "pending",
1957
2204
  },
1958
2205
  "summary",
@@ -2050,7 +2297,7 @@ export async function sendAgentMessageInTransaction(
2050
2297
  }
2051
2298
 
2052
2299
  export async function steerAgentSessionInTransaction(
2053
- db: Database,
2300
+ db: SessionActivityDatabase,
2054
2301
  input: {
2055
2302
  accountId: string;
2056
2303
  workspaceId: string;
@@ -2117,6 +2364,7 @@ export async function steerAgentSessionInTransaction(
2117
2364
  input.workspaceId,
2118
2365
  input.actor,
2119
2366
  );
2367
+ const xaiAuthority = await xaiAuthorityForAgentActor(db, input.workspaceId, input.actor);
2120
2368
  const resumed = await autoResumeSessionBranchInTransaction(db, {
2121
2369
  workspaceId: input.workspaceId,
2122
2370
  sessionId: input.targetSessionId,
@@ -2178,8 +2426,10 @@ export async function steerAgentSessionInTransaction(
2178
2426
  callerTurnId: input.actor.turnId,
2179
2427
  callerAttemptId: input.actor.attemptId,
2180
2428
  callerExecutionGeneration: input.actor.executionGeneration,
2429
+ ...(xaiAuthority.subjectId ? { xaiAuthoritySubjectId: xaiAuthority.subjectId } : {}),
2181
2430
  },
2182
2431
  personalConnectionDelegations,
2432
+ xaiProviderAccountAuthoritySnapshot: xaiAuthority.snapshot,
2183
2433
  state: "pending",
2184
2434
  },
2185
2435
  "summary",
@@ -3,7 +3,7 @@ import { createHash } from "node:crypto";
3
3
  import { ReasoningEffort } from "@opengeni/contracts";
4
4
  import { and, asc, desc, eq, inArray, isNull, sql } from "drizzle-orm";
5
5
 
6
- import type { Database } from "./database";
6
+ import type { Database, SessionActivityDatabase } from "./database";
7
7
  import { fromPostgresLosslessJson, fromPostgresLosslessText } from "./lossless-json";
8
8
  import * as schema from "./schema";
9
9
  import { submitHumanPromptInTransaction } from "./session-queue-commands";
@@ -178,7 +178,7 @@ function mapProjection(
178
178
  * delegation into the same canonical Steer-or-start path used by a human.
179
179
  */
180
180
  export async function flushSessionRealtimeTranscriptTailInTransaction(
181
- db: Database,
181
+ db: SessionActivityDatabase,
182
182
  input: {
183
183
  accountId: string;
184
184
  workspaceId: string;
@@ -3,7 +3,7 @@ import { createHash } from "node:crypto";
3
3
  import { LatencyMode, ReasoningEffort, type SessionRealtimeMode } from "@opengeni/contracts";
4
4
  import { and, asc, desc, eq, inArray, isNull, or, sql } from "drizzle-orm";
5
5
 
6
- import type { Database } from "./database";
6
+ import type { Database, SessionActivityDatabase } from "./database";
7
7
  import {
8
8
  fromPostgresLosslessJson,
9
9
  fromPostgresLosslessText,
@@ -1075,7 +1075,7 @@ async function appendInvalidDelegationFailure(
1075
1075
  }
1076
1076
 
1077
1077
  async function admitRealtimeDelegationInTransaction(
1078
- db: Database,
1078
+ db: SessionActivityDatabase,
1079
1079
  input: Pick<
1080
1080
  SyncSessionRealtimeLedgerInput,
1081
1081
  "workspaceId" | "sessionId" | "realtimeId" | "connectionEpoch" | "ownerSubjectId"
@@ -1268,7 +1268,7 @@ function assertProviderAckSequences(values: number[] | undefined, maximum: numbe
1268
1268
  }
1269
1269
 
1270
1270
  export async function syncSessionRealtimeLedgerInTransaction(
1271
- db: Database,
1271
+ db: SessionActivityDatabase,
1272
1272
  input: SyncSessionRealtimeLedgerInput,
1273
1273
  hooks: SyncSessionRealtimeLedgerHooks = {},
1274
1274
  ): Promise<SyncSessionRealtimeLedgerResult> {
@@ -8,7 +8,7 @@ import type {
8
8
  } from "@opengeni/contracts";
9
9
  import { and, asc, eq, gt, inArray, isNull, or } from "drizzle-orm";
10
10
 
11
- import type { Database } from "./database";
11
+ import type { Database, SessionActivityDatabase } from "./database";
12
12
  import { LOSSLESS_CONTENT_CODEC_VERSION } from "./lossless-json";
13
13
  import { flushSessionRealtimeTranscriptTailInTransaction } from "./session-realtime-context";
14
14
  import {
@@ -161,7 +161,7 @@ function assertOwner(
161
161
  }
162
162
 
163
163
  async function appendRealtimeLifecycleEvent(
164
- db: Database,
164
+ db: SessionActivityDatabase,
165
165
  session: SessionRow,
166
166
  sequence: number,
167
167
  type: Extract<SessionEventType, "session.realtime.started" | "session.realtime.ended">,
@@ -259,7 +259,7 @@ async function registerNormalModeWake(db: Database, session: SessionRow, reason:
259
259
  }
260
260
 
261
261
  async function endWithEvent(
262
- db: Database,
262
+ db: SessionActivityDatabase,
263
263
  session: SessionRow,
264
264
  row: RealtimeRow,
265
265
  reason: SessionRealtimeEndReason,
@@ -352,7 +352,7 @@ function assertRealtimeAdmission(session: SessionRow): void {
352
352
  }
353
353
 
354
354
  export async function beginSessionRealtimeInTransaction(
355
- db: Database,
355
+ db: SessionActivityDatabase,
356
356
  input: BeginSessionRealtimeInput,
357
357
  ): Promise<SessionRealtimeMutationResult> {
358
358
  const now = input.now ?? new Date();
@@ -553,7 +553,7 @@ export async function assertSessionRealtimeOwnerInTransaction(
553
553
  }
554
554
 
555
555
  export async function renewSessionRealtimeInTransaction(
556
- db: Database,
556
+ db: SessionActivityDatabase,
557
557
  input: RenewSessionRealtimeInput,
558
558
  ): Promise<RenewSessionRealtimeResult> {
559
559
  const now = input.now ?? new Date();
@@ -616,7 +616,7 @@ export async function renewSessionRealtimeInTransaction(
616
616
  }
617
617
 
618
618
  export async function endSessionRealtimeInTransaction(
619
- db: Database,
619
+ db: SessionActivityDatabase,
620
620
  input: EndSessionRealtimeInput,
621
621
  ): Promise<SessionRealtimeMutationResult> {
622
622
  const now = input.now ?? new Date();
@@ -649,7 +649,7 @@ export async function endSessionRealtimeInTransaction(
649
649
 
650
650
  /** Lazily settle an expired voice lease under the canonical session lock. */
651
651
  export async function settleExpiredSessionRealtimeInTransaction(
652
- db: Database,
652
+ db: SessionActivityDatabase,
653
653
  session: SessionRow,
654
654
  now = new Date(),
655
655
  ): Promise<SessionRow> {