@opengeni/db 5.0.1 → 6.0.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 (212) hide show
  1. package/dist/automations.d.ts +0 -2
  2. package/dist/canonical-human-identities.d.ts +4 -0
  3. package/dist/canonical-human-identities.js +3 -3
  4. package/dist/capability-components.d.ts +5 -13
  5. package/dist/capability-integrations.d.ts +23 -8
  6. package/dist/capability-reconciliation.d.ts +5 -0
  7. package/dist/capability-reconciliation.js +21 -0
  8. package/dist/capability-reconciliation.js.map +1 -0
  9. package/dist/{chunk-6T2GGYWE.js → chunk-4UJCXBR2.js} +4 -5800
  10. package/dist/chunk-4UJCXBR2.js.map +1 -0
  11. package/dist/{chunk-MWMXWHJD.js → chunk-7JCDSMX2.js} +2 -2
  12. package/dist/chunk-AJA2ZIUW.js +219 -0
  13. package/dist/chunk-AJA2ZIUW.js.map +1 -0
  14. package/dist/chunk-CDAT6EKW.js +247 -0
  15. package/dist/chunk-CDAT6EKW.js.map +1 -0
  16. package/dist/{chunk-DPONPYJD.js → chunk-CJI6G254.js} +70 -18
  17. package/dist/chunk-CJI6G254.js.map +1 -0
  18. package/dist/chunk-G32NVMRJ.js +276 -0
  19. package/dist/chunk-G32NVMRJ.js.map +1 -0
  20. package/dist/chunk-GABXCG3N.js +5811 -0
  21. package/dist/chunk-GABXCG3N.js.map +1 -0
  22. package/dist/{chunk-ERKVSPDX.js → chunk-LVY33EWL.js} +3 -3
  23. package/dist/{chunk-45CP2YKY.js → chunk-MAMBI2HR.js} +9 -3
  24. package/dist/{chunk-45CP2YKY.js.map → chunk-MAMBI2HR.js.map} +1 -1
  25. package/dist/{chunk-F73UKJY6.js → chunk-MN5PZMEK.js} +91 -108
  26. package/dist/chunk-MN5PZMEK.js.map +1 -0
  27. package/dist/chunk-PJI4MUZ7.js +131 -0
  28. package/dist/chunk-PJI4MUZ7.js.map +1 -0
  29. package/dist/{chunk-T6BWIGWJ.js → chunk-RIYHP2WU.js} +2 -2
  30. package/dist/{chunk-7HMK3B45.js → chunk-RL2MUXM3.js} +16 -7
  31. package/dist/chunk-RL2MUXM3.js.map +1 -0
  32. package/dist/{chunk-HQDVI2DB.js → chunk-SYKHLPTK.js} +4 -3
  33. package/dist/{chunk-HQDVI2DB.js.map → chunk-SYKHLPTK.js.map} +1 -1
  34. package/dist/{chunk-T6YLHJLS.js → chunk-XIXVVBW2.js} +198 -51
  35. package/dist/chunk-XIXVVBW2.js.map +1 -0
  36. package/dist/chunk-ZPJ6V2VG.js +156 -0
  37. package/dist/chunk-ZPJ6V2VG.js.map +1 -0
  38. package/dist/codex-capacity-recovery.d.ts +12 -0
  39. package/dist/codex-failure-eligibility.d.ts +9 -0
  40. package/dist/company-profile-schema.d.ts +4 -2
  41. package/dist/connect-attempts.d.ts +15 -0
  42. package/dist/connect-attempts.js +25 -0
  43. package/dist/connect-attempts.js.map +1 -0
  44. package/dist/connection-authority.d.ts +7 -63
  45. package/dist/connection-refresh-lock.d.ts +4 -0
  46. package/dist/connection-token-resolver.d.ts +8 -43
  47. package/dist/database-timing.d.ts +10 -0
  48. package/dist/database.d.ts +4 -0
  49. package/dist/editable-artifact-durable-export.js +2 -2
  50. package/dist/editable-artifacts.d.ts +9 -0
  51. package/dist/editable-artifacts.js +7 -5
  52. package/dist/index.d.ts +447 -78
  53. package/dist/index.js +12705 -12872
  54. package/dist/index.js.map +1 -1
  55. package/dist/insights-usage-bundle.d.ts +3 -0
  56. package/dist/integration-bindings.d.ts +1 -1
  57. package/dist/integration-facets.d.ts +18 -1
  58. package/dist/knowledge-entries-schema.d.ts +2 -0
  59. package/dist/knowledge-entries.d.ts +1 -0
  60. package/dist/knowledge-indexing.d.ts +1 -0
  61. package/dist/live-session-attempt.d.ts +35 -137
  62. package/dist/managed-auth-session-sets.js +3 -3
  63. package/dist/mcp-account-bindings.d.ts +4 -0
  64. package/dist/mcp-oauth.d.ts +11 -0
  65. package/dist/mcp-operations.js +2 -2
  66. package/dist/migrate.js +1 -1
  67. package/dist/organization-integration-policy.d.ts +51 -0
  68. package/dist/organization-integration-policy.js +18 -0
  69. package/dist/organization-integration-policy.js.map +1 -0
  70. package/dist/organization-usage.d.ts +20 -0
  71. package/dist/plugin-packages.d.ts +9 -12
  72. package/dist/pr-review.d.ts +0 -11
  73. package/dist/preference-registry-schema.d.ts +17 -0
  74. package/dist/provision-roles.js +1 -1
  75. package/dist/retained-provider-commands.d.ts +124 -6
  76. package/dist/retained-provider-commands.js +29 -97
  77. package/dist/retained-provider-commands.js.map +1 -1
  78. package/dist/retired-session-create-metadata.d.ts +4 -0
  79. package/dist/runtime-posture.d.ts +7 -5
  80. package/dist/schema.d.ts +876 -656
  81. package/dist/schema.js +5 -7
  82. package/dist/session-admission-block.d.ts +32 -0
  83. package/dist/session-attempt-writers.d.ts +4 -0
  84. package/dist/session-background-commands.js +5 -4
  85. package/dist/session-command-output.js +8 -126
  86. package/dist/session-command-output.js.map +1 -1
  87. package/dist/session-control.d.ts +5 -1
  88. package/dist/session-event-slices.d.ts +10 -0
  89. package/dist/session-event-slices.js +8 -222
  90. package/dist/session-event-slices.js.map +1 -1
  91. package/dist/session-file-attachments.d.ts +28 -0
  92. package/dist/session-goal-reports.d.ts +43 -0
  93. package/dist/session-mcp-approval.d.ts +4 -0
  94. package/dist/session-mcp-credential-rotation.js +5 -4
  95. package/dist/session-mcp-credential-rotation.js.map +1 -1
  96. package/dist/session-message-search.d.ts +22 -0
  97. package/dist/session-queue-commands.d.ts +2 -6
  98. package/dist/session-retry.d.ts +36 -0
  99. package/dist/session-tenancy.js +3 -3
  100. package/dist/skill-source-release-impact.d.ts +18 -0
  101. package/dist/skill-source-release.d.ts +9 -0
  102. package/dist/skills.d.ts +7 -1
  103. package/dist/user-resource-authority.d.ts +0 -8
  104. package/dist/video-generation.js +3 -3
  105. package/dist/workspace-tool-defaults.js +5 -4
  106. package/dist/workspace-tool-defaults.js.map +1 -1
  107. package/drizzle/0468_knowledge_relationship_projection.sql +30 -0
  108. package/drizzle/0469_knowledge_source_discovery.sql +85 -0
  109. package/drizzle/0470_organization_integration_policy.sql +151 -0
  110. package/drizzle/0471_usage_events_account_recent_index.sql +4 -0
  111. package/drizzle/0472_usage_events_workspace_recent_index.sql +4 -0
  112. package/drizzle/0473_organization_usage_analytical_capability.sql +237 -0
  113. package/drizzle/0474_goal_report_requirements.sql +156 -0
  114. package/drizzle/0475_session_event_history_statistics.sql +15 -0
  115. package/drizzle/0476_session_event_history_policy_planning.sql +29 -0
  116. package/drizzle/0477_managed_sign_in_methods.sql +303 -0
  117. package/drizzle/0478_sender_owned_connections.sql +2772 -0
  118. package/drizzle/0479_connection_create_idempotency.sql +16 -0
  119. package/drizzle/0480_private_session_organization_key_administration.sql +154 -0
  120. package/drizzle/0481_personal_connection_visibility_cleanup.sql +45 -0
  121. package/drizzle/0482_remove_packs.sql +417 -0
  122. package/drizzle/0483_preclaim_admission_block.sql +85 -0
  123. package/drizzle/0484_insights_usage_projection.sql +211 -0
  124. package/drizzle/0485_inherited_mcp_approval_policies.sql +6 -0
  125. package/drizzle/0486_reasoning_configuration_message_forks.sql +35 -0
  126. package/drizzle/0487_skill_catalog_message_forks.sql +26 -0
  127. package/drizzle/0488_permanent_skill_removal.sql +207 -0
  128. package/drizzle/0489_modal_command_byte_offsets.sql +17 -0
  129. package/drizzle/0490_periodic_capture_attempt_cadence.sql +6 -0
  130. package/drizzle/0491_warm_capture_holder_reclamation.sql +57 -0
  131. package/drizzle/0492_codex_accepted_source_authority.sql +249 -0
  132. package/drizzle/0493_stopping_command_error_containment.sql +58 -0
  133. package/drizzle/0494_mcp_account_bindings.sql +334 -0
  134. package/drizzle/0495_consented_sandbox_recovery.sql +220 -0
  135. package/drizzle/0496_supervised_command_settlement.sql +386 -0
  136. package/drizzle/0497_modal_inventory_owner_read_capability.sql +112 -0
  137. package/drizzle/0498_enrollment_membership_fence.sql +87 -0
  138. package/drizzle/0499_session_attachment_access.sql +224 -0
  139. package/drizzle/0500_session_execution_epoch.sql +37 -0
  140. package/drizzle/0501_session_sharing_execution.sql +591 -0
  141. package/drizzle/0502_active_message_boundary_forks.sql +30 -0
  142. package/package.json +17 -5
  143. package/src/automations.ts +17 -73
  144. package/src/canonical-human-identities.ts +17 -5
  145. package/src/capability-components.ts +7 -24
  146. package/src/capability-integrations.ts +301 -21
  147. package/src/capability-reconciliation.ts +19 -0
  148. package/src/codex-capacity-recovery.ts +47 -0
  149. package/src/codex-failure-eligibility.ts +93 -0
  150. package/src/connect-attempts.ts +49 -18
  151. package/src/connection-authority.ts +12 -158
  152. package/src/connection-refresh-lock.ts +22 -0
  153. package/src/connection-token-resolver.ts +58 -530
  154. package/src/database-timing.ts +43 -0
  155. package/src/database.ts +61 -26
  156. package/src/editable-artifacts.ts +1 -1
  157. package/src/index.ts +3578 -1273
  158. package/src/insights-model-bundle.ts +19 -7
  159. package/src/insights-usage-bundle.ts +16 -19
  160. package/src/integration-bindings.ts +2 -7
  161. package/src/integration-facets.ts +73 -6
  162. package/src/knowledge-entries.ts +8 -1
  163. package/src/live-session-attempt.ts +0 -22
  164. package/src/mcp-account-bindings.ts +12 -0
  165. package/src/mcp-oauth.ts +26 -0
  166. package/src/organization-integration-policy.ts +235 -0
  167. package/src/organization-usage.ts +83 -0
  168. package/src/plugin-packages.ts +226 -42
  169. package/src/pr-review.ts +7 -69
  170. package/src/preference-registry-schema.ts +1 -0
  171. package/src/provision-roles.ts +50 -37
  172. package/src/retained-provider-commands.ts +286 -9
  173. package/src/retired-session-create-metadata.ts +16 -0
  174. package/src/runtime-posture.ts +217 -13
  175. package/src/schema.ts +104 -120
  176. package/src/session-admission-block.ts +29 -0
  177. package/src/session-attempt-writers.ts +48 -0
  178. package/src/session-control.ts +21 -5
  179. package/src/session-event-slices.ts +76 -26
  180. package/src/session-file-attachments.ts +66 -0
  181. package/src/session-goal-reports.ts +255 -0
  182. package/src/session-mcp-approval.ts +30 -0
  183. package/src/session-message-search.ts +348 -0
  184. package/src/session-queue-commands.ts +60 -36
  185. package/src/session-retry.ts +319 -0
  186. package/src/skill-config-migration.ts +11 -2
  187. package/src/skill-source-release-impact.ts +33 -0
  188. package/src/skill-source-release.ts +67 -26
  189. package/src/skills.ts +44 -6
  190. package/src/user-resource-authority.ts +0 -56
  191. package/dist/chunk-6T2GGYWE.js.map +0 -1
  192. package/dist/chunk-7HMK3B45.js.map +0 -1
  193. package/dist/chunk-DPONPYJD.js.map +0 -1
  194. package/dist/chunk-F73UKJY6.js.map +0 -1
  195. package/dist/chunk-T6YLHJLS.js.map +0 -1
  196. package/dist/host-mcp-binding-match.d.ts +0 -5
  197. package/dist/host-mcp-bindings.d.ts +0 -79
  198. package/dist/host-mcp-resolvers.d.ts +0 -47
  199. package/dist/host-mcp-task-authority.d.ts +0 -43
  200. package/dist/host-selection-identity.d.ts +0 -6
  201. package/dist/pack-components.d.ts +0 -83
  202. package/dist/pack-installations.d.ts +0 -86
  203. package/src/host-mcp-binding-match.ts +0 -34
  204. package/src/host-mcp-bindings.ts +0 -777
  205. package/src/host-mcp-resolvers.ts +0 -266
  206. package/src/host-mcp-task-authority.ts +0 -384
  207. package/src/host-selection-identity.ts +0 -29
  208. package/src/pack-components.ts +0 -980
  209. package/src/pack-installations.ts +0 -950
  210. /package/dist/{chunk-MWMXWHJD.js.map → chunk-7JCDSMX2.js.map} +0 -0
  211. /package/dist/{chunk-ERKVSPDX.js.map → chunk-LVY33EWL.js.map} +0 -0
  212. /package/dist/{chunk-T6BWIGWJ.js.map → chunk-RIYHP2WU.js.map} +0 -0
package/dist/schema.js CHANGED
@@ -189,6 +189,8 @@ import {
189
189
  organizationCodexRotationSettings,
190
190
  organizationCompanyProfileAgentPolicies,
191
191
  organizationCompanyProfileAgentPolicyEvents,
192
+ organizationIntegrationPolicies,
193
+ organizationIntegrationPolicyOperations,
192
194
  organizationInvitationBindingEvents,
193
195
  organizationMembershipInvitations,
194
196
  organizationMembershipLifecycleEvents,
@@ -217,8 +219,6 @@ import {
217
219
  organizationUserRetentionObjectDeletionReceipts,
218
220
  organizationUserRetentionObjectObligations,
219
221
  organizationUserRetentionPolicies,
220
- packInstallationComponents,
221
- packInstallations,
222
222
  personalGitHubRepositorySelectionHeads,
223
223
  personalGitHubRepositorySelectionOperations,
224
224
  personalGitHubRepositorySelections,
@@ -360,7 +360,6 @@ import {
360
360
  workspaceLearningPolicySnapshots,
361
361
  workspaceMemberships,
362
362
  workspaceModelPolicies,
363
- workspacePacks,
364
363
  workspaceScreenshotQuotas,
365
364
  workspaceSessionActivityRevisions,
366
365
  workspaceVariableSetVariables,
@@ -373,7 +372,7 @@ import {
373
372
  xaiRotationSettings,
374
373
  xaiSessionAccountPins,
375
374
  xaiSubscriptionCredentials
376
- } from "./chunk-F73UKJY6.js";
375
+ } from "./chunk-MN5PZMEK.js";
377
376
  import "./chunk-S2TZ3F4L.js";
378
377
  import "./chunk-PZ5AY32C.js";
379
378
  export {
@@ -567,6 +566,8 @@ export {
567
566
  organizationCodexRotationSettings,
568
567
  organizationCompanyProfileAgentPolicies,
569
568
  organizationCompanyProfileAgentPolicyEvents,
569
+ organizationIntegrationPolicies,
570
+ organizationIntegrationPolicyOperations,
570
571
  organizationInvitationBindingEvents,
571
572
  organizationMembershipInvitations,
572
573
  organizationMembershipLifecycleEvents,
@@ -595,8 +596,6 @@ export {
595
596
  organizationUserRetentionObjectDeletionReceipts,
596
597
  organizationUserRetentionObjectObligations,
597
598
  organizationUserRetentionPolicies,
598
- packInstallationComponents,
599
- packInstallations,
600
599
  personalGitHubRepositorySelectionHeads,
601
600
  personalGitHubRepositorySelectionOperations,
602
601
  personalGitHubRepositorySelections,
@@ -738,7 +737,6 @@ export {
738
737
  workspaceLearningPolicySnapshots,
739
738
  workspaceMemberships,
740
739
  workspaceModelPolicies,
741
- workspacePacks,
742
740
  workspaceScreenshotQuotas,
743
741
  workspaceSessionActivityRevisions,
744
742
  workspaceVariableSetVariables,
@@ -0,0 +1,32 @@
1
+ import { SessionAdmissionBlock } from "@opengeni/contracts";
2
+ import { z } from "zod";
3
+ export type SessionAdmissionFence = {
4
+ lastSequence: number;
5
+ controlVersion: number;
6
+ };
7
+ export declare const StoredSessionAdmissionBlock: z.ZodObject<{
8
+ reason: z.ZodEnum<{
9
+ database_claim_rejected: "database_claim_rejected";
10
+ initiator_membership_required: "initiator_membership_required";
11
+ personal_resource_grant_required: "personal_resource_grant_required";
12
+ }>;
13
+ sqlState: z.ZodNullable<z.ZodString>;
14
+ retryPolicy: z.ZodLiteral<"explicit_recheck">;
15
+ blockedAt: z.ZodString;
16
+ attemptId: z.ZodString;
17
+ fence: z.ZodObject<{
18
+ lastSequence: z.ZodNumber;
19
+ controlVersion: z.ZodNumber;
20
+ }, z.core.$strict>;
21
+ previousStatus: z.ZodEnum<{
22
+ idle: "idle";
23
+ queued: "queued";
24
+ recovering: "recovering";
25
+ requires_action: "requires_action";
26
+ running: "running";
27
+ waiting_capacity: "waiting_capacity";
28
+ }>;
29
+ }, z.core.$strict>;
30
+ export type StoredSessionAdmissionBlock = z.infer<typeof StoredSessionAdmissionBlock>;
31
+ /** Never expose internal attempt/fence identities through the public projection. */
32
+ export declare function projectSessionAdmissionBlock(value: StoredSessionAdmissionBlock | null | undefined): SessionAdmissionBlock | null;
@@ -0,0 +1,4 @@
1
+ import { type SQL } from "drizzle-orm";
2
+ /** Physical writers retain ownership after logical settlement. A durably
3
+ * adopted background command owns its lifetime independently of the turn. */
4
+ export declare function sessionAttemptPendingWritersSql(attempt: SQL): SQL;
@@ -22,10 +22,11 @@ import {
22
22
  settleClaimedConnectedMachineBackgroundCommandWithMutation,
23
23
  settleConnectedMachineSessionBackgroundCommandWithMutation,
24
24
  settleSessionBackgroundCommandForRetainedProcessInTransaction
25
- } from "./chunk-6T2GGYWE.js";
26
- import "./chunk-ERKVSPDX.js";
27
- import "./chunk-DPONPYJD.js";
28
- import "./chunk-F73UKJY6.js";
25
+ } from "./chunk-GABXCG3N.js";
26
+ import "./chunk-LVY33EWL.js";
27
+ import "./chunk-4UJCXBR2.js";
28
+ import "./chunk-CJI6G254.js";
29
+ import "./chunk-MN5PZMEK.js";
29
30
  import "./chunk-S2TZ3F4L.js";
30
31
  import "./chunk-PZ5AY32C.js";
31
32
  export {
@@ -1,131 +1,13 @@
1
1
  import {
2
- lockSessionEventWriteRows
3
- } from "./chunk-6T2GGYWE.js";
4
- import "./chunk-ERKVSPDX.js";
5
- import {
6
- withSessionActivityRlsContext
7
- } from "./chunk-DPONPYJD.js";
8
- import {
9
- sandboxRetainedProcesses,
10
- sessionBackgroundCommands,
11
- sessionEvents,
12
- sessions
13
- } from "./chunk-F73UKJY6.js";
14
- import {
15
- fromPostgresLosslessJson,
16
- withLosslessContentWriteVersion
17
- } from "./chunk-S2TZ3F4L.js";
2
+ appendSessionCommandOutput
3
+ } from "./chunk-PJI4MUZ7.js";
4
+ import "./chunk-GABXCG3N.js";
5
+ import "./chunk-LVY33EWL.js";
6
+ import "./chunk-4UJCXBR2.js";
7
+ import "./chunk-CJI6G254.js";
8
+ import "./chunk-MN5PZMEK.js";
9
+ import "./chunk-S2TZ3F4L.js";
18
10
  import "./chunk-PZ5AY32C.js";
19
-
20
- // src/session-command-output.ts
21
- import { and, eq } from "drizzle-orm";
22
- async function appendSessionCommandOutput(db, input) {
23
- if (!input.chunkId || input.chunkId.length > 200)
24
- throw new Error("Invalid command output chunk ID");
25
- if (!input.chunk) return [];
26
- return await withSessionActivityRlsContext(db, input, async (tx) => {
27
- const events = [];
28
- const locks = await lockSessionEventWriteRows(tx, {
29
- workspaceId: input.workspaceId,
30
- controlLock: "share",
31
- sessionIds: [input.sessionId]
32
- });
33
- const session = locks.sessions[0];
34
- if (!session || session.accountId !== input.accountId)
35
- throw new Error("Command output session not found");
36
- const [command] = await tx.select({ id: sessionBackgroundCommands.id }).from(sessionBackgroundCommands).where(
37
- and(
38
- eq(sessionBackgroundCommands.accountId, input.accountId),
39
- eq(sessionBackgroundCommands.workspaceId, input.workspaceId),
40
- eq(sessionBackgroundCommands.sessionId, input.sessionId),
41
- eq(sessionBackgroundCommands.id, input.commandId)
42
- )
43
- ).limit(1);
44
- if (!command) {
45
- const [process] = await tx.select({ id: sandboxRetainedProcesses.id }).from(sandboxRetainedProcesses).where(
46
- and(
47
- eq(sandboxRetainedProcesses.accountId, input.accountId),
48
- eq(sandboxRetainedProcesses.workspaceId, input.workspaceId),
49
- eq(sandboxRetainedProcesses.sessionId, input.sessionId),
50
- eq(sandboxRetainedProcesses.id, input.commandId)
51
- )
52
- ).limit(1);
53
- if (!process) throw new Error("Command output has no retained command identity");
54
- }
55
- let sequence = session.lastSequence;
56
- let part = 0;
57
- for (let offset = 0; offset < input.chunk.length; ) {
58
- let end = Math.min(offset + 16384, input.chunk.length);
59
- if (end < input.chunk.length && /[\uD800-\uDBFF]/u.test(input.chunk[end - 1])) end -= 1;
60
- const clientEventId = `command-output:${input.commandId}:${input.chunkId}:${input.stream}:${part++}`;
61
- const chunk = input.chunk.slice(offset, end);
62
- offset = end;
63
- const [existing] = await tx.select({
64
- payload: sessionEvents.payload,
65
- version: sessionEvents.payloadCodecVersion
66
- }).from(sessionEvents).where(
67
- and(
68
- eq(sessionEvents.workspaceId, input.workspaceId),
69
- eq(sessionEvents.sessionId, input.sessionId),
70
- eq(sessionEvents.clientEventId, clientEventId)
71
- )
72
- ).limit(1);
73
- if (existing) {
74
- const payload = fromPostgresLosslessJson(existing.payload, existing.version);
75
- if (payload.chunk !== chunk || payload.commandId !== input.commandId || payload.stream !== input.stream) {
76
- throw new Error("Command output retry changed the captured chunk");
77
- }
78
- continue;
79
- }
80
- const [inserted] = await tx.insert(sessionEvents).values(
81
- withLosslessContentWriteVersion(
82
- {
83
- accountId: input.accountId,
84
- workspaceId: input.workspaceId,
85
- sessionId: input.sessionId,
86
- sequence: ++sequence,
87
- type: "sandbox.command.output.delta",
88
- clientEventId,
89
- payload: {
90
- commandId: input.commandId,
91
- stream: input.stream,
92
- streamFidelity: input.streamFidelity ?? "separate",
93
- chunk
94
- }
95
- },
96
- "payload",
97
- "payloadCodecVersion"
98
- )
99
- ).returning();
100
- if (inserted)
101
- events.push({
102
- id: inserted.id,
103
- workspaceId: input.workspaceId,
104
- sessionId: input.sessionId,
105
- sequence: inserted.sequence,
106
- type: "sandbox.command.output.delta",
107
- payload: fromPostgresLosslessJson(inserted.payload, inserted.payloadCodecVersion),
108
- occurredAt: inserted.occurredAt.toISOString(),
109
- clientEventId,
110
- turnId: null,
111
- turnGeneration: null,
112
- turnAttemptId: null,
113
- turnAssociation: null,
114
- duplicateOfEventId: null,
115
- duplicateReason: null
116
- });
117
- }
118
- if (sequence !== session.lastSequence) {
119
- await tx.update(sessions).set({ lastSequence: sequence }).where(
120
- and(
121
- eq(sessions.workspaceId, input.workspaceId),
122
- eq(sessions.id, input.sessionId)
123
- )
124
- );
125
- }
126
- return events;
127
- });
128
- }
129
11
  export {
130
12
  appendSessionCommandOutput
131
13
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/session-command-output.ts"],"sourcesContent":["import { and, eq } from \"drizzle-orm\";\nimport type { SessionEvent } from \"@opengeni/contracts\";\nimport type { Database } from \"./database\";\nimport { withSessionActivityRlsContext } from \"./database\";\nimport { lockSessionEventWriteRows } from \"./session-control\";\nimport { fromPostgresLosslessJson, withLosslessContentWriteVersion } from \"./lossless-json\";\nimport * as schema from \"./schema\";\n\nexport type SessionCommandOutputInput = {\n accountId: string;\n workspaceId: string;\n sessionId: string;\n commandId: string;\n /** Stable identity of this consumed provider chunk, reused on persistence retry. */\n chunkId: string;\n stream: \"stdout\" | \"stderr\";\n streamFidelity?: \"separate\" | \"merged\";\n chunk: string;\n};\n\n/** Capture is independent of terminal observation and remains valid after the\n * launching attempt ends. Only an exact retained process/background command in\n * this session is eligible; this helper never creates command authority. */\nexport async function appendSessionCommandOutput(\n db: Database,\n input: SessionCommandOutputInput,\n): Promise<SessionEvent[]> {\n if (!input.chunkId || input.chunkId.length > 200)\n throw new Error(\"Invalid command output chunk ID\");\n if (!input.chunk) return [];\n return await withSessionActivityRlsContext(db, input, async (tx) => {\n const events: SessionEvent[] = [];\n const locks = await lockSessionEventWriteRows(tx, {\n workspaceId: input.workspaceId,\n controlLock: \"share\",\n sessionIds: [input.sessionId],\n });\n const session = locks.sessions[0];\n if (!session || session.accountId !== input.accountId)\n throw new Error(\"Command output session not found\");\n const [command] = await tx\n .select({ id: schema.sessionBackgroundCommands.id })\n .from(schema.sessionBackgroundCommands)\n .where(\n and(\n eq(schema.sessionBackgroundCommands.accountId, input.accountId),\n eq(schema.sessionBackgroundCommands.workspaceId, input.workspaceId),\n eq(schema.sessionBackgroundCommands.sessionId, input.sessionId),\n eq(schema.sessionBackgroundCommands.id, input.commandId),\n ),\n )\n .limit(1);\n if (!command) {\n const [process] = await tx\n .select({ id: schema.sandboxRetainedProcesses.id })\n .from(schema.sandboxRetainedProcesses)\n .where(\n and(\n eq(schema.sandboxRetainedProcesses.accountId, input.accountId),\n eq(schema.sandboxRetainedProcesses.workspaceId, input.workspaceId),\n eq(schema.sandboxRetainedProcesses.sessionId, input.sessionId),\n eq(schema.sandboxRetainedProcesses.id, input.commandId),\n ),\n )\n .limit(1);\n if (!process) throw new Error(\"Command output has no retained command identity\");\n }\n let sequence = session.lastSequence;\n let part = 0;\n for (let offset = 0; offset < input.chunk.length;) {\n let end = Math.min(offset + 16_384, input.chunk.length);\n if (end < input.chunk.length && /[\\uD800-\\uDBFF]/u.test(input.chunk[end - 1]!)) end -= 1;\n const clientEventId = `command-output:${input.commandId}:${input.chunkId}:${input.stream}:${part++}`;\n const chunk = input.chunk.slice(offset, end);\n offset = end;\n const [existing] = await tx\n .select({\n payload: schema.sessionEvents.payload,\n version: schema.sessionEvents.payloadCodecVersion,\n })\n .from(schema.sessionEvents)\n .where(\n and(\n eq(schema.sessionEvents.workspaceId, input.workspaceId),\n eq(schema.sessionEvents.sessionId, input.sessionId),\n eq(schema.sessionEvents.clientEventId, clientEventId),\n ),\n )\n .limit(1);\n if (existing) {\n const payload = fromPostgresLosslessJson(existing.payload, existing.version) as Record<\n string,\n unknown\n >;\n if (\n payload.chunk !== chunk ||\n payload.commandId !== input.commandId ||\n payload.stream !== input.stream\n ) {\n throw new Error(\"Command output retry changed the captured chunk\");\n }\n continue;\n }\n const [inserted] = await tx\n .insert(schema.sessionEvents)\n .values(\n withLosslessContentWriteVersion(\n {\n accountId: input.accountId,\n workspaceId: input.workspaceId,\n sessionId: input.sessionId,\n sequence: ++sequence,\n type: \"sandbox.command.output.delta\",\n clientEventId,\n payload: {\n commandId: input.commandId,\n stream: input.stream,\n streamFidelity: input.streamFidelity ?? \"separate\",\n chunk,\n },\n },\n \"payload\",\n \"payloadCodecVersion\",\n ),\n )\n .returning();\n if (inserted)\n events.push({\n id: inserted.id,\n workspaceId: input.workspaceId,\n sessionId: input.sessionId,\n sequence: inserted.sequence,\n type: \"sandbox.command.output.delta\",\n payload: fromPostgresLosslessJson(inserted.payload, inserted.payloadCodecVersion),\n occurredAt: inserted.occurredAt.toISOString(),\n clientEventId,\n turnId: null,\n turnGeneration: null,\n turnAttemptId: null,\n turnAssociation: null,\n duplicateOfEventId: null,\n duplicateReason: null,\n });\n }\n if (sequence !== session.lastSequence) {\n await tx\n .update(schema.sessions)\n .set({ lastSequence: sequence })\n .where(\n and(\n eq(schema.sessions.workspaceId, input.workspaceId),\n eq(schema.sessions.id, input.sessionId),\n ),\n );\n }\n return events;\n });\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -223,6 +223,8 @@ export type WorkspaceControlLockOptions = {
223
223
  /** Share an already running budget (used by the admission helper). */
224
224
  budget?: WorkspaceControlLockBudget;
225
225
  };
226
+ /** Run one lock-acquiring statement under the remaining budget. */
227
+ export declare function boundedLockStep<T>(db: Database, workspaceId: string, budget: WorkspaceControlLockBudget | null, step: () => Promise<T>): Promise<T>;
226
228
  /**
227
229
  * Lock the mandatory workspace inference-control row.
228
230
  *
@@ -381,7 +383,9 @@ export declare function assertSessionAuthoritySnapshot(input: {
381
383
  authorityVisibility: unknown;
382
384
  authorityOwnerOrganizationMembershipId: unknown;
383
385
  }): SessionAuthoritySnapshot;
384
- export declare function sessionAuthoritySnapshotMatchesSession(snapshot: SessionAuthoritySnapshot, session: Pick<typeof schema.sessions.$inferSelect, "authorityEpoch" | "visibility" | "ownerOrganizationMembershipId">): boolean;
386
+ export declare function sessionAuthoritySnapshotMatchesSession(snapshot: SessionAuthoritySnapshot, session: Pick<typeof schema.sessions.$inferSelect, "authorityEpoch" | "visibility" | "ownerOrganizationMembershipId"> & {
387
+ executionAuthorityEpoch?: number;
388
+ }): boolean;
385
389
  export declare function sessionAuthoritySnapshotsEqual(left: Pick<SessionAuthoritySnapshot, "authorityEpoch" | "authorityVisibility" | "authorityOwnerOrganizationMembershipId">, right: Pick<SessionAuthoritySnapshot, "authorityEpoch" | "authorityVisibility" | "authorityOwnerOrganizationMembershipId">): boolean;
386
390
  /**
387
391
  * Close the exact first-class owner while the caller still holds the owning
@@ -1,3 +1,4 @@
1
+ import { type SessionEvent } from "@opengeni/contracts";
1
2
  import { type Database } from "./database.js";
2
3
  type ListSessionEventPageOptions = import("./index.js").ListSessionEventPageOptions;
3
4
  type SessionEventPage = import("./index.js").SessionEventPage;
@@ -19,6 +20,15 @@ export type SessionEventSlice = {
19
20
  export type SessionEventSlicePage = SessionEventPage & {
20
21
  slices?: Record<number, SessionEventSlice>;
21
22
  };
23
+ type SliceIdentity = Pick<SessionEvent, "id" | "sequence" | "type" | "turnId" | "turnAssociation" | "duplicateOfEventId">;
24
+ /** Internal search projection, NOT authorization. The scanner has selected this
25
+ * exact identity under its subject RLS/list filters and still holds that same
26
+ * transaction and tenancy/membership fences. Reuse them rather than creating
27
+ * two nested scopes and rediscovering the identity for every scalar window.
28
+ * The scalar query still checks the exact workspace/session/event and RLS.
29
+ * Keep the codec/window implementation shared with the conversation reader.
30
+ */
31
+ export declare function readSessionMessageSliceInScope(db: Database, workspaceId: string, sessionId: string, identity: SliceIdentity, offset: number, windows?: number): Promise<SessionEventSlice | undefined>;
22
32
  /** Bounded transfer over retained scalar truth. JSONB extraction/detoasting still
23
33
  * costs PostgreSQL work proportional to the individual source value, not history.
24
34
  * This is a read projection, not authorization: the MCP caller must authorize the
@@ -1,227 +1,13 @@
1
1
  import {
2
- rawRows,
3
- withWorkspaceRls
4
- } from "./chunk-DPONPYJD.js";
5
- import {
6
- sessionEvents,
7
- sessionTurns
8
- } from "./chunk-F73UKJY6.js";
9
- import {
10
- LOSSLESS_JSON_STRING_PREFIX,
11
- fromPostgresLosslessJson
12
- } from "./chunk-S2TZ3F4L.js";
2
+ listSessionEventSlices,
3
+ readSessionMessageSliceInScope
4
+ } from "./chunk-CDAT6EKW.js";
5
+ import "./chunk-CJI6G254.js";
6
+ import "./chunk-MN5PZMEK.js";
7
+ import "./chunk-S2TZ3F4L.js";
13
8
  import "./chunk-PZ5AY32C.js";
14
-
15
- // src/session-event-slices.ts
16
- import { and, asc, desc, eq, gt, inArray, lt, notInArray, sql } from "drizzle-orm";
17
- import { resolveSessionEventTypeFilters } from "@opengeni/contracts";
18
- var WINDOW = 8192;
19
- var STRUCTURED_BYTES = 1024 * 1024;
20
- async function listSessionEventSlices(db, workspaceId, sessionId, options, legacyRead) {
21
- if (options.legacyUtf16) {
22
- if (!legacyRead) throw new Error("Legacy continuation requires its original bounded reader");
23
- return legacyRead({
24
- ...options,
25
- limit: 1,
26
- maxBytes: 1024 * 1024
27
- });
28
- }
29
- const offset = options.sourceOffset ?? 0;
30
- if (!Number.isSafeInteger(offset) || offset < 0 || offset > 2147483647)
31
- throw new Error("Invalid message continuation offset");
32
- const direction = options.direction ?? (options.before === void 0 ? "after" : "before");
33
- const limit = options.sourceSequence ? 1 : Math.max(1, Math.min(options.limit ?? 8, 8));
34
- const filters = resolveSessionEventTypeFilters(options);
35
- const predicates = [
36
- eq(sessionEvents.workspaceId, workspaceId),
37
- eq(sessionEvents.sessionId, sessionId),
38
- gt(sessionEvents.sequence, Math.min(options.after ?? 0, 2147483647)),
39
- // Same indexed exclusion as the audit/discovery reader. Do not substitute
40
- // turn status: terminal-before-claim prompts must remain excluded too.
41
- sql`(${sessionEvents.type} <> 'user.message' or not exists (
42
- select 1 from ${sessionTurns} unclaimed_prompt_turn
43
- where unclaimed_prompt_turn.workspace_id = ${workspaceId}
44
- and unclaimed_prompt_turn.workspace_id = ${sessionEvents.workspaceId}
45
- and unclaimed_prompt_turn.session_id = ${sessionEvents.sessionId}
46
- and unclaimed_prompt_turn.trigger_event_id = ${sessionEvents.id}
47
- and unclaimed_prompt_turn.source in ('user', 'api')
48
- and unclaimed_prompt_turn.started_at is null
49
- ))`
50
- ];
51
- if (options.before !== void 0 && options.before <= 2147483647)
52
- predicates.push(lt(sessionEvents.sequence, options.before));
53
- if (filters.includeTypes.length)
54
- predicates.push(inArray(sessionEvents.type, filters.includeTypes));
55
- if (filters.excludeTypes.length)
56
- predicates.push(notInArray(sessionEvents.type, filters.excludeTypes));
57
- const identities = await withWorkspaceRls(
58
- db,
59
- workspaceId,
60
- (tx) => tx.select({
61
- id: sessionEvents.id,
62
- sequence: sessionEvents.sequence,
63
- type: sql`case when octet_length(${sessionEvents.type}) <= 256 then ${sessionEvents.type} else 'session.event.envelope_omitted' end`,
64
- turnId: sessionEvents.turnId,
65
- turnAssociation: sql`case when ${sessionEvents.turnAssociation} is null then null when ${sessionEvents.turnAssociation} = 'current' then 'current' else 'late_rejected' end`,
66
- duplicateOfEventId: sessionEvents.duplicateOfEventId
67
- }).from(sessionEvents).where(and(...predicates)).orderBy(
68
- direction === "before" ? desc(sessionEvents.sequence) : asc(sessionEvents.sequence)
69
- ).limit(limit + 1)
70
- );
71
- const ordered = identities.slice(0, limit).map(
72
- (identity) => ({
73
- ...identity,
74
- workspaceId,
75
- sessionId,
76
- payload: {},
77
- occurredAt: ""
78
- })
79
- );
80
- const page = {
81
- events: [],
82
- hasMore: identities.length > limit,
83
- bytes: 2,
84
- fullPayloadsExact: true,
85
- direction,
86
- coveredSequence: null,
87
- nextAfter: null,
88
- nextBefore: null,
89
- truncatedBy: identities.length > limit ? "count" : null
90
- };
91
- const slices = {};
92
- const events = [];
93
- let consumed = 0;
94
- await withWorkspaceRls(db, workspaceId, async (tx) => {
95
- for (const event of ordered) {
96
- consumed++;
97
- if (event.duplicateOfEventId || event.turnAssociation && event.turnAssociation !== "current")
98
- continue;
99
- const p = sessionEvents.payload;
100
- const output = event.type === "agent.toolCall.output";
101
- let value = sql`${p}->'text'`;
102
- if (options.view === "tools")
103
- value = output ? sql`${p}->'output'` : sql`coalesce(nullif(${p}->'arguments', 'null'::jsonb), ${p}->'args')`;
104
- else if (options.view === "results")
105
- value = event.type === "turn.completed" ? sql`coalesce(nullif(${p}->'output', 'null'::jsonb), ${p}->'result')` : sql`${p}`;
106
- const include = options.view !== "tools" || (output ? options.includeOutput : options.includeArguments);
107
- if (!include) value = sql`null::jsonb`;
108
- const start = options.sourceSequence === event.sequence ? offset : 0;
109
- const prefix = LOSSLESS_JSON_STRING_PREFIX;
110
- const raw = sql`raw`;
111
- const encoded = sql`encoded`;
112
- const tagged = sql`case when version = 1
113
- and left(${raw}, ${prefix.length}) = ${prefix}
114
- and length(${encoded}) > 0
115
- and ${encoded} ~ '^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$'
116
- then (length(${encoded}) / 4 * 3 - case when right(${encoded}, 2) = '==' then 2 when right(${encoded}, 1) = '=' then 1 else 0 end) % 2 = 0
117
- and encode(decode(right(${encoded}, 4), 'base64'), 'base64') = right(${encoded}, 4)
118
- else false end`;
119
- const group = Math.floor(Math.max(0, start - 1) / 3);
120
- const safeMetadata = (key) => sql`case when octet_length((${p}->${key})::text) <= 4096 then ${p}->${key} else null end`;
121
- const callId = sql`coalesce(nullif(${p}->'callId', 'null'::jsonb), nullif(${p}->'call_id', 'null'::jsonb), ${p}->'id')`;
122
- const metadataSql = options.view === "tools" ? sql`jsonb_strip_nulls(jsonb_build_object(
123
- 'callId', case when octet_length((${callId})::text) <= 4096 then ${callId} else null end,
124
- 'identityOmitted', case when octet_length((${callId})::text) > 4096 or octet_length((${p}->'name')::text) > 4096 then true else null end,
125
- 'name', ${safeMetadata("name")}, 'isError', case when ${p}->'isError' = 'true'::jsonb or (${output} and ${p}->'output'->'isError' = 'true'::jsonb) then true else null end,
126
- 'maintenance', case when ${p} ? 'maintenance' then true else null end,
127
- 'segmentLimit', case when ${p} ? 'segmentLimit' then true else null end))` : options.view === "results" && event.type === "turn.completed" ? sql`jsonb_strip_nulls(jsonb_build_object(
128
- 'maintenance', case when ${p} ? 'maintenance' then true else null end,
129
- 'segmentLimit', case when ${p} ? 'segmentLimit' then true else null end))` : sql`'{}'::jsonb`;
130
- const [row] = await rawRows(
131
- tx,
132
- sql`with source as (
133
- select ${value} as value, ${metadataSql} as metadata,
134
- ${sessionEvents.payloadCodecVersion} as version
135
- from ${sessionEvents}
136
- where ${sessionEvents.workspaceId} = ${workspaceId}
137
- and ${sessionEvents.sessionId} = ${sessionId}
138
- and ${sessionEvents.id} = ${event.id}
139
- and (${sessionEvents.turnAssociation} is null or ${sessionEvents.turnAssociation} = 'current')
140
- and ${sessionEvents.duplicateOfEventId} is null
141
- limit 1
142
- ), scalar as (
143
- select *, jsonb_typeof(value) as kind,
144
- case when jsonb_typeof(value) = 'string' then value #>> '{}' else null end as raw,
145
- case when jsonb_typeof(value) <> 'string' then octet_length(value::text) else 0 end as structured_bytes
146
- from source offset 0
147
- ), encoding as (
148
- select *, case when version = 1 and left(raw, ${prefix.length}) = ${prefix}
149
- then substring(raw from ${prefix.length + 1}::integer) else null end as encoded
150
- from scalar offset 0
151
- ), validated as (
152
- select *, ${tagged} as tagged from encoding offset 0
153
- )
154
- select metadata, version, kind, tagged,
155
- case when kind = 'string' then
156
- case when tagged then (length(encoded) / 4 * 3 - case when right(encoded, 2) = '==' then 2 when right(encoded, 1) = '=' then 1 else 0 end) / 2
157
- else length(raw) end else 0 end as total,
158
- case when kind = 'string' then
159
- case when tagged then substring(encoded from ${Math.min(group * 8 + 1, 2147483647)}::integer for ${Math.ceil((WINDOW + 6) / 3) * 8}::integer)
160
- else substring(raw from ${Math.min(start + 1, 2147483647)}::integer for ${WINDOW}::integer) end else null end as window,
161
- case when kind <> 'string' and structured_bytes <= ${STRUCTURED_BYTES} then value else null end as structured,
162
- coalesce(kind <> 'string' and structured_bytes > ${STRUCTURED_BYTES}, false) as omitted
163
- from validated`
164
- );
165
- if (!row) continue;
166
- const metadata = fromPostgresLosslessJson(row.metadata, row.version);
167
- for (const [key, budget] of [
168
- ["callId", 4096],
169
- ["name", 1024]
170
- ]) {
171
- if (metadata[key] !== void 0 && Buffer.byteLength(JSON.stringify(metadata[key]), "utf8") > budget) {
172
- delete metadata[key];
173
- metadata.identityOmitted = true;
174
- }
175
- }
176
- let text = row.window ?? "";
177
- if (row.tagged) {
178
- text = fromPostgresLosslessJson(prefix + text, 1);
179
- const local = start - group * 3;
180
- if (local > 0 && /[\uD800-\uDBFF]/.test(text[local - 1]) && /[\uDC00-\uDFFF]/.test(text[local] ?? ""))
181
- throw new Error("Invalid message continuation offset: splits a surrogate pair");
182
- text = text.slice(local, local + WINDOW);
183
- if (start + text.length < row.total && /[\uD800-\uDBFF]/.test(text.at(-1)))
184
- text = text.slice(0, -1);
185
- }
186
- if (start > row.total && row.kind === "string")
187
- throw new Error("Invalid message continuation offset");
188
- const logical = row.omitted ? {} : row.kind === "string" ? text : fromPostgresLosslessJson(row.structured, row.version);
189
- let payload = { ...metadata };
190
- if (options.view === "tools") {
191
- if (row.kind !== null) payload[output ? "output" : "arguments"] = logical;
192
- } else if (options.view === "results") {
193
- if (event.type === "turn.completed") payload.output = logical;
194
- else payload = logical ?? {};
195
- } else payload.text = logical;
196
- if (row.omitted) payload = { ...payload, sourceOmitted: true };
197
- if (row.kind === "string" || row.omitted)
198
- slices[event.sequence] = {
199
- offset: start,
200
- total: row.total,
201
- unit: row.tagged ? "utf16" : "codepoint",
202
- text,
203
- omitted: row.omitted
204
- };
205
- events.push({ ...event, payload });
206
- if (row.kind !== "string" && Buffer.byteLength(JSON.stringify(payload)) > WINDOW) break;
207
- if (row.kind === "string" && start + (row.tagged ? text.length : Array.from(text).length) < row.total)
208
- break;
209
- }
210
- });
211
- return {
212
- ...page,
213
- events: events.sort((a, b) => a.sequence - b.sequence),
214
- hasMore: page.hasMore || consumed < ordered.length,
215
- coveredSequence: consumed ? {
216
- first: Math.min(ordered[0].sequence, ordered[consumed - 1].sequence),
217
- last: Math.max(ordered[0].sequence, ordered[consumed - 1].sequence)
218
- } : null,
219
- bytes: Buffer.byteLength(JSON.stringify(events), "utf8"),
220
- fullPayloadsExact: !Object.values(slices).some((slice) => slice.omitted),
221
- slices
222
- };
223
- }
224
9
  export {
225
- listSessionEventSlices
10
+ listSessionEventSlices,
11
+ readSessionMessageSliceInScope
226
12
  };
227
13
  //# sourceMappingURL=session-event-slices.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/session-event-slices.ts"],"sourcesContent":["import { and, asc, desc, eq, gt, inArray, lt, notInArray, sql, type SQL } from \"drizzle-orm\";\nimport { resolveSessionEventTypeFilters, type SessionEvent } from \"@opengeni/contracts\";\nimport { rawRows, withWorkspaceRls, type Database } from \"./database\";\ntype ListSessionEventPageOptions = import(\"./index\").ListSessionEventPageOptions;\ntype SessionEventPage = import(\"./index\").SessionEventPage;\nimport { fromPostgresLosslessJson, LOSSLESS_JSON_STRING_PREFIX } from \"./lossless-json\";\nimport * as schema from \"./schema\";\n\nexport type SessionEventSliceOptions = ListSessionEventPageOptions & {\n sourceSequence?: number;\n sourceOffset?: number;\n view?: \"conversation\" | \"results\" | \"tools\";\n includeArguments?: boolean;\n includeOutput?: boolean;\n legacyUtf16?: boolean;\n};\nexport type SessionEventSlice = {\n offset: number;\n total: number;\n unit: \"codepoint\" | \"utf16\";\n text: string;\n omitted: boolean;\n};\nexport type SessionEventSlicePage = SessionEventPage & {\n slices?: Record<number, SessionEventSlice>;\n};\nconst WINDOW = 8192;\nconst STRUCTURED_BYTES = 1024 * 1024;\n\n/** Bounded transfer over retained scalar truth. JSONB extraction/detoasting still\n * costs PostgreSQL work proportional to the individual source value, not history.\n * This is a read projection, not authorization: the MCP caller must authorize the\n * target on every request. Both metadata and scalar reads retain workspace RLS.\n */\nexport async function listSessionEventSlices(\n db: Database,\n workspaceId: string,\n sessionId: string,\n options: SessionEventSliceOptions,\n legacyRead?: (options: ListSessionEventPageOptions) => Promise<SessionEventPage>,\n): Promise<SessionEventSlicePage> {\n // Finish an already-issued UTF-16 cursor using its original bounded reader.\n // New messages use source slices; no cursor offset is silently reinterpreted.\n if (options.legacyUtf16) {\n if (!legacyRead) throw new Error(\"Legacy continuation requires its original bounded reader\");\n return legacyRead({\n ...options,\n limit: 1,\n maxBytes: 1024 * 1024,\n });\n }\n const offset = options.sourceOffset ?? 0;\n if (!Number.isSafeInteger(offset) || offset < 0 || offset > 2_147_483_647)\n throw new Error(\"Invalid message continuation offset\");\n const direction = options.direction ?? (options.before === undefined ? \"after\" : \"before\");\n const limit = options.sourceSequence ? 1 : Math.max(1, Math.min(options.limit ?? 8, 8));\n const filters = resolveSessionEventTypeFilters(options);\n const predicates: SQL[] = [\n eq(schema.sessionEvents.workspaceId, workspaceId),\n eq(schema.sessionEvents.sessionId, sessionId),\n gt(schema.sessionEvents.sequence, Math.min(options.after ?? 0, 2_147_483_647)),\n // Same indexed exclusion as the audit/discovery reader. Do not substitute\n // turn status: terminal-before-claim prompts must remain excluded too.\n sql`(${schema.sessionEvents.type} <> 'user.message' or not exists (\n select 1 from ${schema.sessionTurns} unclaimed_prompt_turn\n where unclaimed_prompt_turn.workspace_id = ${workspaceId}\n and unclaimed_prompt_turn.workspace_id = ${schema.sessionEvents.workspaceId}\n and unclaimed_prompt_turn.session_id = ${schema.sessionEvents.sessionId}\n and unclaimed_prompt_turn.trigger_event_id = ${schema.sessionEvents.id}\n and unclaimed_prompt_turn.source in ('user', 'api')\n and unclaimed_prompt_turn.started_at is null\n ))`,\n ];\n if (options.before !== undefined && options.before <= 2_147_483_647)\n predicates.push(lt(schema.sessionEvents.sequence, options.before));\n if (filters.includeTypes.length)\n predicates.push(inArray(schema.sessionEvents.type, filters.includeTypes));\n if (filters.excludeTypes.length)\n predicates.push(notInArray(schema.sessionEvents.type, filters.excludeTypes));\n // Unlike audit `none` mode, this identity query does not compute a payload\n // projection merely to report its size. Only the selected scalar is extracted.\n const identities = await withWorkspaceRls(db, workspaceId, (tx) =>\n tx\n .select({\n id: schema.sessionEvents.id,\n sequence: schema.sessionEvents.sequence,\n type: sql<string>`case when octet_length(${schema.sessionEvents.type}) <= 256 then ${schema.sessionEvents.type} else 'session.event.envelope_omitted' end`,\n turnId: schema.sessionEvents.turnId,\n turnAssociation: sql<\n string | null\n >`case when ${schema.sessionEvents.turnAssociation} is null then null when ${schema.sessionEvents.turnAssociation} = 'current' then 'current' else 'late_rejected' end`,\n duplicateOfEventId: schema.sessionEvents.duplicateOfEventId,\n })\n .from(schema.sessionEvents)\n .where(and(...predicates))\n .orderBy(\n direction === \"before\"\n ? desc(schema.sessionEvents.sequence)\n : asc(schema.sessionEvents.sequence),\n )\n .limit(limit + 1),\n );\n const ordered = identities.slice(0, limit).map(\n (identity) =>\n ({\n ...identity,\n workspaceId,\n sessionId,\n payload: {},\n occurredAt: \"\",\n }) as SessionEvent,\n );\n const page: SessionEventPage = {\n events: [],\n hasMore: identities.length > limit,\n bytes: 2,\n fullPayloadsExact: true,\n direction,\n coveredSequence: null,\n nextAfter: null,\n nextBefore: null,\n truncatedBy: identities.length > limit ? \"count\" : null,\n };\n const slices: Record<number, SessionEventSlice> = {};\n const events: SessionEvent[] = [];\n let consumed = 0;\n await withWorkspaceRls(db, workspaceId, async (tx) => {\n for (const event of ordered) {\n consumed++;\n if (\n event.duplicateOfEventId ||\n (event.turnAssociation && event.turnAssociation !== \"current\")\n )\n continue;\n const p = schema.sessionEvents.payload;\n const output = event.type === \"agent.toolCall.output\";\n let value: SQL = sql`${p}->'text'`;\n if (options.view === \"tools\")\n value = output\n ? sql`${p}->'output'`\n : sql`coalesce(nullif(${p}->'arguments', 'null'::jsonb), ${p}->'args')`;\n else if (options.view === \"results\")\n value =\n event.type === \"turn.completed\"\n ? sql`coalesce(nullif(${p}->'output', 'null'::jsonb), ${p}->'result')`\n : sql`${p}`;\n const include =\n options.view !== \"tools\" || (output ? options.includeOutput : options.includeArguments);\n if (!include) value = sql`null::jsonb`;\n const start = options.sourceSequence === event.sequence ? offset : 0;\n const prefix = LOSSLESS_JSON_STRING_PREFIX;\n const raw = sql`raw`;\n const encoded = sql`encoded`;\n // Match exactly the JS codec's canonical-base64/even-byte acceptance.\n // A malformed active marker remains literal, just like the shared codec.\n const tagged = sql`case when version = 1\n and left(${raw}, ${prefix.length}) = ${prefix}\n and length(${encoded}) > 0\n and ${encoded} ~ '^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$'\n then (length(${encoded}) / 4 * 3 - case when right(${encoded}, 2) = '==' then 2 when right(${encoded}, 1) = '=' then 1 else 0 end) % 2 = 0\n and encode(decode(right(${encoded}, 4), 'base64'), 'base64') = right(${encoded}, 4)\n else false end`;\n // Aligned base64 windows represent groups of three UTF-16 units. Include\n // one preceding and one following unit to validate/avoid pair splits.\n const group = Math.floor(Math.max(0, start - 1) / 3);\n const safeMetadata = (key: string) =>\n sql`case when octet_length((${p}->${key})::text) <= 4096 then ${p}->${key} else null end`;\n const callId = sql`coalesce(nullif(${p}->'callId', 'null'::jsonb), nullif(${p}->'call_id', 'null'::jsonb), ${p}->'id')`;\n const metadataSql =\n options.view === \"tools\"\n ? sql`jsonb_strip_nulls(jsonb_build_object(\n 'callId', case when octet_length((${callId})::text) <= 4096 then ${callId} else null end,\n 'identityOmitted', case when octet_length((${callId})::text) > 4096 or octet_length((${p}->'name')::text) > 4096 then true else null end,\n 'name', ${safeMetadata(\"name\")}, 'isError', case when ${p}->'isError' = 'true'::jsonb or (${output} and ${p}->'output'->'isError' = 'true'::jsonb) then true else null end,\n 'maintenance', case when ${p} ? 'maintenance' then true else null end,\n 'segmentLimit', case when ${p} ? 'segmentLimit' then true else null end))`\n : options.view === \"results\" && event.type === \"turn.completed\"\n ? sql`jsonb_strip_nulls(jsonb_build_object(\n 'maintenance', case when ${p} ? 'maintenance' then true else null end,\n 'segmentLimit', case when ${p} ? 'segmentLimit' then true else null end))`\n : sql`'{}'::jsonb`;\n const [row] = await rawRows<{\n metadata: unknown;\n version: number | null;\n kind: string | null;\n tagged: boolean;\n total: number;\n window: string | null;\n structured: unknown;\n omitted: boolean;\n }>(\n tx,\n sql`with source as (\n select ${value} as value, ${metadataSql} as metadata,\n ${schema.sessionEvents.payloadCodecVersion} as version\n from ${schema.sessionEvents}\n where ${schema.sessionEvents.workspaceId} = ${workspaceId}\n and ${schema.sessionEvents.sessionId} = ${sessionId}\n and ${schema.sessionEvents.id} = ${event.id}\n and (${schema.sessionEvents.turnAssociation} is null or ${schema.sessionEvents.turnAssociation} = 'current')\n and ${schema.sessionEvents.duplicateOfEventId} is null\n limit 1\n ), scalar as (\n select *, jsonb_typeof(value) as kind,\n case when jsonb_typeof(value) = 'string' then value #>> '{}' else null end as raw,\n case when jsonb_typeof(value) <> 'string' then octet_length(value::text) else 0 end as structured_bytes\n from source offset 0\n ), encoding as (\n select *, case when version = 1 and left(raw, ${prefix.length}) = ${prefix}\n then substring(raw from ${prefix.length + 1}::integer) else null end as encoded\n from scalar offset 0\n ), validated as (\n select *, ${tagged} as tagged from encoding offset 0\n )\n select metadata, version, kind, tagged,\n case when kind = 'string' then\n case when tagged then (length(encoded) / 4 * 3 - case when right(encoded, 2) = '==' then 2 when right(encoded, 1) = '=' then 1 else 0 end) / 2\n else length(raw) end else 0 end as total,\n case when kind = 'string' then\n case when tagged then substring(encoded from ${Math.min(group * 8 + 1, 2_147_483_647)}::integer for ${Math.ceil((WINDOW + 6) / 3) * 8}::integer)\n else substring(raw from ${Math.min(start + 1, 2_147_483_647)}::integer for ${WINDOW}::integer) end else null end as window,\n case when kind <> 'string' and structured_bytes <= ${STRUCTURED_BYTES} then value else null end as structured,\n coalesce(kind <> 'string' and structured_bytes > ${STRUCTURED_BYTES}, false) as omitted\n from validated`,\n );\n if (!row) continue;\n const metadata = fromPostgresLosslessJson(row.metadata, row.version) as Record<\n string,\n unknown\n >;\n // Codec decoding can expand JSON escaping (notably NUL/lone surrogates).\n // Keep identities bounded too, without falling back to a different alias.\n for (const [key, budget] of [\n [\"callId\", 4096],\n [\"name\", 1024],\n ] as const) {\n if (\n metadata[key] !== undefined &&\n Buffer.byteLength(JSON.stringify(metadata[key]), \"utf8\") > budget\n ) {\n delete metadata[key];\n metadata.identityOmitted = true;\n }\n }\n let text = row.window ?? \"\";\n if (row.tagged) {\n // Window lengths are multiples of eight, so each partial block is also\n // a complete canonical encoding accepted by the existing lossless codec.\n text = fromPostgresLosslessJson(prefix + text, 1);\n const local = start - group * 3;\n if (\n local > 0 &&\n /[\\uD800-\\uDBFF]/.test(text[local - 1]!) &&\n /[\\uDC00-\\uDFFF]/.test(text[local] ?? \"\")\n )\n throw new Error(\"Invalid message continuation offset: splits a surrogate pair\");\n text = text.slice(local, local + WINDOW);\n if (start + text.length < row.total && /[\\uD800-\\uDBFF]/.test(text.at(-1)!))\n text = text.slice(0, -1);\n }\n if (start > row.total && row.kind === \"string\")\n throw new Error(\"Invalid message continuation offset\");\n const logical = row.omitted\n ? {}\n : row.kind === \"string\"\n ? text\n : fromPostgresLosslessJson(row.structured, row.version);\n let payload: Record<string, unknown> = { ...metadata };\n if (options.view === \"tools\") {\n if (row.kind !== null) payload[output ? \"output\" : \"arguments\"] = logical;\n } else if (options.view === \"results\") {\n if (event.type === \"turn.completed\") payload.output = logical;\n else payload = (logical as Record<string, unknown>) ?? {};\n } else payload.text = logical;\n if (row.omitted) payload = { ...payload, sourceOmitted: true };\n if (row.kind === \"string\" || row.omitted)\n slices[event.sequence] = {\n offset: start,\n total: row.total,\n unit: row.tagged ? \"utf16\" : \"codepoint\",\n text,\n omitted: row.omitted,\n };\n events.push({ ...event, payload });\n // One large structured value preserves the previous bounded JSON path,\n // without accumulating several megabyte-sized values in one source page.\n if (row.kind !== \"string\" && Buffer.byteLength(JSON.stringify(payload)) > WINDOW) break;\n if (\n row.kind === \"string\" &&\n start + (row.tagged ? text.length : Array.from(text).length) < row.total\n )\n break;\n }\n });\n // Preserve scan advancement even when every identity was excluded above.\n return {\n ...page,\n events: events.sort((a, b) => a.sequence - b.sequence),\n hasMore: page.hasMore || consumed < ordered.length,\n coveredSequence: consumed\n ? {\n first: Math.min(ordered[0]!.sequence, ordered[consumed - 1]!.sequence),\n last: Math.max(ordered[0]!.sequence, ordered[consumed - 1]!.sequence),\n }\n : null,\n bytes: Buffer.byteLength(JSON.stringify(events), \"utf8\"),\n fullPayloadsExact: !Object.values(slices).some((slice) => slice.omitted),\n slices,\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,28 @@
1
+ import type { FileAsset, ResourceRef, SessionAuthorizationActor } from "@opengeni/contracts";
2
+ import { type Database } from "./database.js";
3
+ /** Only call during verified human initial/Send/Steer acceptance, in its transaction. */
4
+ export declare function acceptSessionFileAttachments(db: Database, input: {
5
+ accountId: string;
6
+ workspaceId: string;
7
+ sessionId: string;
8
+ turnId: string;
9
+ subjectId: string;
10
+ resources: ResourceRef[];
11
+ }): Promise<void>;
12
+ export type SessionAttachmentReadAccess = {
13
+ sessionId: string;
14
+ authorityEpoch: number;
15
+ actor: Pick<SessionAuthorizationActor, "kind" | "subjectId"> & Partial<{
16
+ callerSessionId: string;
17
+ turnId: string;
18
+ attemptId: string;
19
+ executionGeneration: number;
20
+ }>;
21
+ };
22
+ /** Core must prove session authorization; workers supply their live own-session attempt. */
23
+ export declare function readSessionFileAttachments(db: Database, input: {
24
+ accountId: string;
25
+ workspaceId: string;
26
+ fileIds: readonly string[];
27
+ access: SessionAttachmentReadAccess;
28
+ }): Promise<FileAsset[]>;