@opengeni/worker-bundle 1.0.1 → 2.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 (122) hide show
  1. package/dist/activities/agent-turn/codex.d.ts +1 -1
  2. package/dist/activities/agent-turn/compaction-prep.d.ts +1 -5
  3. package/dist/activities/agent-turn/errors.d.ts +31 -5
  4. package/dist/activities/agent-turn/finalization-monitor.d.ts +17 -0
  5. package/dist/activities/agent-turn/finalization.d.ts +1 -1
  6. package/dist/activities/agent-turn/governance-model.d.ts +0 -2
  7. package/dist/activities/agent-turn/quiescence.d.ts +1 -0
  8. package/dist/activities/agent-turn/recovery-warning.d.ts +8 -0
  9. package/dist/activities/agent-turn/run-credentials.d.ts +0 -1
  10. package/dist/activities/agent-turn/sandbox-establish.d.ts +1 -1
  11. package/dist/activities/agent-turn/sandbox-route.d.ts +0 -20
  12. package/dist/activities/agent-turn/sandbox-runtime.d.ts +1 -1
  13. package/dist/activities/agent-turn/skill-remove.d.ts +14 -0
  14. package/dist/activities/agent-turn/skill-search.d.ts +1 -1
  15. package/dist/activities/agent-turn/stream-attempt.d.ts +1 -0
  16. package/dist/activities/agent-turn/tool-environment.d.ts +0 -4
  17. package/dist/activities/agent-turn/turn-context.d.ts +2 -0
  18. package/dist/activities/agent-turn/turn-sandbox-access.d.ts +3 -0
  19. package/dist/activities/codex-capacity.d.ts +6 -1
  20. package/dist/activities/codex-rotation.d.ts +1 -1
  21. package/dist/activities/context-compaction.d.ts +7 -1
  22. package/dist/activities/mcp-account-routes.d.ts +22 -0
  23. package/dist/activities/mcp-credentials.d.ts +12 -13
  24. package/dist/activities/mcp-operation-authority.d.ts +0 -5
  25. package/dist/activities/rig-verification.d.ts +2 -3
  26. package/dist/activities/sandbox-images.d.ts +1 -1
  27. package/dist/activities/sandbox-lease.d.ts +4 -3
  28. package/dist/activities/session-state.d.ts +57 -2
  29. package/dist/activities/types.d.ts +12 -3
  30. package/dist/{activities-control-HMFGSKC5.js → activities-control-BOLIY3H4.js} +366 -187
  31. package/dist/activities-control-BOLIY3H4.js.map +1 -0
  32. package/dist/activities-control.d.ts +110 -2
  33. package/dist/{activities-turn-AP67JADS.js → activities-turn-2B3WMHBB.js} +767 -471
  34. package/dist/activities-turn-2B3WMHBB.js.map +1 -0
  35. package/dist/activities.d.ts +110 -2
  36. package/dist/artifact-materializer-entry.js +5 -2
  37. package/dist/artifact-materializer-entry.js.map +1 -1
  38. package/dist/artifact-outbox-entry.js +2 -2
  39. package/dist/artifact-outbox-entry.js.map +1 -1
  40. package/dist/{chunk-A4XQWVZK.js → chunk-I7HKKMUJ.js} +77 -1
  41. package/dist/chunk-I7HKKMUJ.js.map +1 -0
  42. package/dist/{chunk-CYITU5UH.js → chunk-TVEE2UUC.js} +275 -146
  43. package/dist/chunk-TVEE2UUC.js.map +1 -0
  44. package/dist/editable-artifact-materializer-service.d.ts +2 -2
  45. package/dist/editable-artifact-outbox-service.d.ts +2 -2
  46. package/dist/index.d.ts +55 -1
  47. package/dist/index.js +4 -3
  48. package/dist/index.js.map +1 -1
  49. package/dist/observability-metrics.d.ts +11 -3
  50. package/dist/retained-process-diagnostics.d.ts +4 -0
  51. package/dist/sandbox-resume.d.ts +2 -12
  52. package/dist/sandbox-routing.d.ts +5 -3
  53. package/dist/sandbox-snapshot-diagnostics.d.ts +20 -0
  54. package/dist/warm-capture-holder.d.ts +3 -0
  55. package/dist/workflow-bundle.js +51 -11
  56. package/package.json +15 -15
  57. package/src/activities/agent-turn/agent-build.ts +42 -5
  58. package/src/activities/agent-turn/claim.ts +12 -0
  59. package/src/activities/agent-turn/codex-capacity.ts +26 -4
  60. package/src/activities/agent-turn/codex.ts +6 -2
  61. package/src/activities/agent-turn/compaction-prep.ts +53 -72
  62. package/src/activities/agent-turn/errors.ts +98 -10
  63. package/src/activities/agent-turn/failure-settlement.ts +49 -28
  64. package/src/activities/agent-turn/finalization-monitor.ts +121 -0
  65. package/src/activities/agent-turn/finalization.ts +79 -21
  66. package/src/activities/agent-turn/governance-model.ts +15 -19
  67. package/src/activities/agent-turn/history.ts +24 -10
  68. package/src/activities/agent-turn/quiescence.ts +3 -0
  69. package/src/activities/agent-turn/recovery-warning.ts +18 -0
  70. package/src/activities/agent-turn/run-credentials.ts +3 -7
  71. package/src/activities/agent-turn/run.ts +68 -52
  72. package/src/activities/agent-turn/sandbox-establish.ts +10 -2
  73. package/src/activities/agent-turn/sandbox-route.ts +0 -20
  74. package/src/activities/agent-turn/sandbox-runtime.ts +40 -7
  75. package/src/activities/agent-turn/skill-remove.ts +46 -0
  76. package/src/activities/agent-turn/skill-save.ts +1 -1
  77. package/src/activities/agent-turn/skill-search.ts +1 -1
  78. package/src/activities/agent-turn/skill-selection.ts +2 -0
  79. package/src/activities/agent-turn/skill-tools.ts +10 -5
  80. package/src/activities/agent-turn/stream-attempt.ts +38 -15
  81. package/src/activities/agent-turn/tool-environment.ts +44 -29
  82. package/src/activities/agent-turn/turn-context.ts +3 -0
  83. package/src/activities/agent-turn/turn-sandbox-access.ts +7 -1
  84. package/src/activities/capabilities.ts +17 -2
  85. package/src/activities/codex-capacity.ts +38 -9
  86. package/src/activities/codex-rotation.ts +18 -5
  87. package/src/activities/context-compaction.ts +26 -4
  88. package/src/activities/goals.ts +1 -0
  89. package/src/activities/google-drive-publication.ts +1 -3
  90. package/src/activities/mcp-account-routes.ts +139 -0
  91. package/src/activities/mcp-credentials.ts +83 -194
  92. package/src/activities/mcp-operation-authority.ts +16 -41
  93. package/src/activities/parent-wake.ts +8 -0
  94. package/src/activities/rig-verification.ts +38 -37
  95. package/src/activities/run-input.ts +25 -16
  96. package/src/activities/sandbox-images.ts +0 -1
  97. package/src/activities/sandbox-lease.ts +177 -44
  98. package/src/activities/scheduled-tasks.ts +118 -93
  99. package/src/activities/session-state.ts +83 -3
  100. package/src/activities/types.ts +18 -2
  101. package/src/activities/workflow-wake.ts +2 -17
  102. package/src/editable-artifact-materializer-service.ts +7 -3
  103. package/src/editable-artifact-outbox-service.ts +4 -4
  104. package/src/github-rest-mcp.ts +0 -1
  105. package/src/index.ts +2 -1
  106. package/src/observability-metrics.ts +105 -2
  107. package/src/personal-github-git-credentials.ts +0 -1
  108. package/src/pr-review-credentials.ts +0 -2
  109. package/src/retained-process-diagnostics.ts +50 -0
  110. package/src/sandbox-resume.ts +58 -73
  111. package/src/sandbox-routing.ts +44 -19
  112. package/src/sandbox-snapshot-diagnostics.ts +112 -0
  113. package/src/warm-capture-holder.ts +15 -0
  114. package/src/workflows/session.ts +64 -2
  115. package/dist/activities/agent-turn/knowledge-sources.d.ts +0 -20
  116. package/dist/activities/packs.d.ts +0 -55
  117. package/dist/activities-control-HMFGSKC5.js.map +0 -1
  118. package/dist/activities-turn-AP67JADS.js.map +0 -1
  119. package/dist/chunk-A4XQWVZK.js.map +0 -1
  120. package/dist/chunk-CYITU5UH.js.map +0 -1
  121. package/src/activities/agent-turn/knowledge-sources.ts +0 -86
  122. package/src/activities/packs.ts +0 -166
@@ -1,23 +1,18 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import { stableJson } from "@opengeni/contracts";
3
3
  import type { ConnectionUseAttribution } from "@opengeni/contracts/connection-authority";
4
- import type { HostMcpAcceptedAuthority } from "@opengeni/contracts/host-mcp-bindings";
5
4
  import type { ResolveConnectionCredentialInput } from "@opengeni/db";
6
5
 
7
6
  /** Metadata only. Callers must obtain authority from a current live fence.
8
7
  * This equality key is never authorization and never replaces physical-use checks. */
9
8
  export function mcpOperationAuthorityDigest(
10
9
  request: ResolveConnectionCredentialInput,
11
- authority:
12
- | {
13
- native: ConnectionUseAttribution;
14
- host?: never;
15
- principal?: { kind: string; subjectId?: string };
16
- }
17
- | { host: HostMcpAcceptedAuthority; native?: never },
10
+ authority: {
11
+ native: ConnectionUseAttribution;
12
+ principal?: { kind: string; subjectId?: string };
13
+ },
18
14
  ): string {
19
15
  const n = authority.native;
20
- const h = authority.host;
21
16
  const ref = request.connectionRef;
22
17
  const metadata = {
23
18
  version: 1,
@@ -31,7 +26,6 @@ export function mcpOperationAuthorityDigest(
31
26
  providerDomain: ref.providerDomain,
32
27
  kind: ref.kind,
33
28
  subjectScope: ref.subjectScope,
34
- hostBinding: ref.hostBinding,
35
29
  scopes: ref.scopes ? [...ref.scopes].sort() : undefined,
36
30
  resource: ref.resource,
37
31
  selectedResources: ref.selectedResources
@@ -40,37 +34,18 @@ export function mcpOperationAuthorityDigest(
40
34
  )
41
35
  : undefined,
42
36
  },
43
- native: n
44
- ? {
45
- organizationId: n.organizationId,
46
- workspaceId: n.workspaceId,
47
- sessionId: n.sessionId,
48
- connectionId: n.connectionId,
49
- connectionGeneration: n.connectionGeneration,
50
- scope: n.scope,
51
- ownerSubjectId: n.ownerSubjectId,
52
- authorityId: n.authorityId,
53
- grantId: n.grantId,
54
- principal: "principal" in authority ? authority.principal : undefined,
55
- }
56
- : undefined,
57
- host: h
58
- ? {
59
- accountId: h.accountId,
60
- workspaceId: h.workspaceId,
61
- targetSessionId: h.targetSessionId,
62
- targetSessionVisibility: h.targetSessionVisibility,
63
- targetSessionAuthorityEpoch: h.targetSessionAuthorityEpoch,
64
- ownerSubjectId: h.ownerSubjectId,
65
- ownerOrganizationMembershipId: h.ownerOrganizationMembershipId,
66
- ownerMembershipAuthorizationRevision: h.ownerMembershipAuthorizationRevision,
67
- bindingId: h.bindingId,
68
- bindingGeneration: h.bindingGeneration,
69
- definition: h.definition,
70
- delegationId: h.delegationId,
71
- delegationGeneration: h.delegationGeneration,
72
- }
73
- : undefined,
37
+ native: {
38
+ organizationId: n.organizationId,
39
+ workspaceId: n.workspaceId,
40
+ sessionId: n.sessionId,
41
+ connectionId: n.connectionId,
42
+ connectionGeneration: n.connectionGeneration,
43
+ scope: n.scope,
44
+ ownerSubjectId: n.ownerSubjectId,
45
+ authorityId: n.authorityId,
46
+ grantId: n.grantId,
47
+ principal: authority.principal,
48
+ },
74
49
  };
75
50
  return createHash("sha256").update(stableJson(metadata)).digest("hex");
76
51
  }
@@ -4,6 +4,7 @@ import {
4
4
  getSession,
5
5
  getSessionGoal,
6
6
  getSessionParentPersonalConnectionDelegations,
7
+ getSessionParentMcpAccountBindings,
7
8
  getSessionParentXaiProviderAccountAuthority,
8
9
  addSessionSystemUpdateWithSourceMutation,
9
10
  claimPendingSessionSystemUpdateOutbox,
@@ -75,6 +76,11 @@ export async function notifyParentOfChildIdle(
75
76
  workspaceId,
76
77
  childSessionId,
77
78
  );
79
+ const mcpAccountBindings = await getSessionParentMcpAccountBindings(
80
+ svc.db,
81
+ workspaceId,
82
+ childSessionId,
83
+ );
78
84
  const xaiAuthority = await getSessionParentXaiProviderAccountAuthority(
79
85
  svc.db,
80
86
  workspaceId,
@@ -97,6 +103,7 @@ export async function notifyParentOfChildIdle(
97
103
  ...(xaiAuthority.subjectId ? { xaiAuthoritySubjectId: xaiAuthority.subjectId } : {}),
98
104
  },
99
105
  personalConnectionDelegations,
106
+ mcpAccountBindings,
100
107
  xaiProviderAccountAuthoritySnapshot: xaiAuthority.snapshot,
101
108
  });
102
109
  if (outbox.status === "delivered") {
@@ -214,6 +221,7 @@ async function deliverParentSystemUpdateOutbox(
214
221
  summary: outbox.summary,
215
222
  lineage: outbox.lineage,
216
223
  personalConnectionDelegations: outbox.personalConnectionDelegations,
224
+ mcpAccountBindings: outbox.mcpAccountBindings,
217
225
  xaiProviderAccountAuthoritySnapshot: outbox.xaiProviderAccountAuthoritySnapshot,
218
226
  },
219
227
  async (tx) => {
@@ -60,7 +60,6 @@ import {
60
60
  import type { Context } from "@temporalio/activity";
61
61
  import type { ControlActivityServices } from "./types";
62
62
  import { rigProviderImageSourceImage } from "./sandbox-images";
63
- import { resolveWorkspacePackRuntime, type WorkspacePackRuntime } from "./packs";
64
63
  import { currentActivityContext } from "./streaming";
65
64
 
66
65
  type RigSetupHook = typeof import("@opengeni/runtime").runRigSetupHook;
@@ -175,7 +174,7 @@ const RIG_VERIFICATION_HEARTBEAT_MIN_INTERVAL_MS = 250;
175
174
  // lease-holder fiction or manual recovery.
176
175
  export const RIG_VERIFICATION_OWNER_TTL_MS = 20 * 60_000;
177
176
  export const RIG_VERIFICATION_OWNERS_DISABLED_MESSAGE =
178
- "Rig verification lease ownership is disabled; refusing to create an unowned verifier sandbox";
177
+ "Sandbox Environment verification lease ownership is disabled; refusing to create an unowned verifier sandbox";
179
178
  const RIG_VERIFICATION_HOLDER_TOUCH_INTERVAL_MS = 10_000;
180
179
  const RIG_VERIFICATION_RELEASE_GRACE_MS = 1;
181
180
 
@@ -187,7 +186,7 @@ export class RigVerificationActivityDeadlineError extends Error {
187
186
  readonly cleanupReserveMs: number,
188
187
  ) {
189
188
  super(
190
- `Rig verification activity-local deadline reached with ${cleanupReserveMs}ms reserved for cleanup before the ${startToCloseTimeoutMs}ms Temporal start-to-close timeout`,
189
+ `Sandbox Environment verification activity-local deadline reached with ${cleanupReserveMs}ms reserved for cleanup before the ${startToCloseTimeoutMs}ms Temporal start-to-close timeout`,
191
190
  );
192
191
  }
193
192
  }
@@ -223,7 +222,9 @@ export function createRigVerificationActivityLifecycle(
223
222
  const temporalSignal = context?.cancellationSignal;
224
223
  const forwardTemporalCancellation = (): void => {
225
224
  if (!controller.signal.aborted) {
226
- controller.abort(temporalSignal?.reason ?? new Error("Rig verification cancelled"));
225
+ controller.abort(
226
+ temporalSignal?.reason ?? new Error("Sandbox Environment verification cancelled"),
227
+ );
227
228
  }
228
229
  };
229
230
  if (temporalSignal?.aborted) {
@@ -308,7 +309,7 @@ export function createRigVerificationActivityLifecycle(
308
309
  }
309
310
 
310
311
  function abortReason(signal: AbortSignal): unknown {
311
- return signal.reason ?? new Error("Rig verification cancelled");
312
+ return signal.reason ?? new Error("Sandbox Environment verification cancelled");
312
313
  }
313
314
 
314
315
  function throwIfAborted(signal: AbortSignal): void {
@@ -433,7 +434,9 @@ export class RigVerificationLeaseUnavailableError extends Error {
433
434
  readonly sandboxGroupId: string,
434
435
  readonly role: "attached" | "blocked" | "rearmed" | "fenced",
435
436
  ) {
436
- super(`Rig verification requires a new clean sandbox, but lease ${sandboxGroupId} was ${role}`);
437
+ super(
438
+ `Sandbox Environment verification requires a new clean sandbox, but lease ${sandboxGroupId} was ${role}`,
439
+ );
437
440
  }
438
441
  }
439
442
 
@@ -490,7 +493,7 @@ export async function runWithOwnedRigVerificationSandbox<T>(
490
493
  let establishmentPromise: Promise<EstablishedSandboxSession> | null = null;
491
494
 
492
495
  const warnCleanupTimeout = (operation: string, instanceId: string | null): void => {
493
- input.observability.warn("rig verifier: ownership cleanup timed out", {
496
+ input.observability.warn("sandbox environment verifier: ownership cleanup timed out", {
494
497
  holderId,
495
498
  instanceId,
496
499
  operation,
@@ -504,7 +507,7 @@ export async function runWithOwnedRigVerificationSandbox<T>(
504
507
  instanceId: string | null,
505
508
  error: unknown,
506
509
  ): void => {
507
- input.observability.warn("rig verifier: ownership cleanup failed", {
510
+ input.observability.warn("sandbox environment verifier: ownership cleanup failed", {
508
511
  holderId,
509
512
  instanceId,
510
513
  operation,
@@ -643,11 +646,14 @@ export async function runWithOwnedRigVerificationSandbox<T>(
643
646
  );
644
647
  } catch (error) {
645
648
  if (!signal.aborted) {
646
- input.observability.warn("rig verifier: Modal ownership tag failed", {
647
- holderId,
648
- instanceId: created.instanceId,
649
- error: error instanceof Error ? error.message : String(error),
650
- });
649
+ input.observability.warn(
650
+ "sandbox environment verifier: Modal ownership tag failed",
651
+ {
652
+ holderId,
653
+ instanceId: created.instanceId,
654
+ error: error instanceof Error ? error.message : String(error),
655
+ },
656
+ );
651
657
  }
652
658
  }
653
659
  }
@@ -913,10 +919,12 @@ function rigProviderImageContentMarker(
913
919
  markerRoot = "/var/opengeni",
914
920
  ): { marker: string; normalizedRoot: string } {
915
921
  if (!/^sha256:[0-9a-f]{64}$/u.test(contentHash)) {
916
- throw new Error("Rig provider image content marker requires a canonical SHA-256 value");
922
+ throw new Error(
923
+ "Sandbox Environment provider image content marker requires a canonical SHA-256 value",
924
+ );
917
925
  }
918
926
  if (!/^\/[A-Za-z0-9._/-]+$/u.test(markerRoot)) {
919
- throw new Error("Rig provider image marker root must be a safe absolute path");
927
+ throw new Error("Sandbox Environment provider image marker root must be a safe absolute path");
920
928
  }
921
929
  const normalizedRoot = markerRoot.replace(/\/+$/u, "") || "/";
922
930
  const marker = `${normalizedRoot === "/" ? "" : normalizedRoot}/rig-setup-content-${contentHash.slice("sha256:".length)}.done`;
@@ -978,7 +986,9 @@ export async function verifyRigProviderImageColdBoot(
978
986
  runContext.commandRunner,
979
987
  );
980
988
  if (markerResult.exitCode !== 0) {
981
- throw new Error("built provider image is missing its exact rig-content marker");
989
+ throw new Error(
990
+ "built provider image is missing its exact sandbox environment-content marker",
991
+ );
982
992
  }
983
993
  for (const check of rigPlatformChecksForSettings(input.settings)) {
984
994
  const result = await runCommand(
@@ -1083,7 +1093,7 @@ export async function buildVerifiedRigProviderImage(input: {
1083
1093
  error: {
1084
1094
  code: "provider_image_content_conflict",
1085
1095
  message:
1086
- "this exact rig version already records a provider image for different effective content; mint and verify a new version",
1096
+ "this exact sandbox environment version already records a provider image for different effective content; mint and verify a new version",
1087
1097
  retryable: false,
1088
1098
  },
1089
1099
  };
@@ -1276,13 +1286,10 @@ export async function buildVerifiedRigProviderImage(input: {
1276
1286
 
1277
1287
  export function settingsForRigVerification(
1278
1288
  settings: ControlActivityServices["settings"],
1279
- packRuntime: WorkspacePackRuntime,
1280
1289
  rigImage: string | null,
1281
1290
  ): ControlActivityServices["settings"] {
1282
1291
  // Rig verification must prove setup and provider-image materialization on
1283
- // the deployment-owned platform base. Legacy Pack and historical Rig image
1284
- // values are intentionally ignored here.
1285
- void packRuntime;
1292
+ // the deployment-owned platform base. Historical Rig image values are ignored.
1286
1293
  void rigImage;
1287
1294
  return settings;
1288
1295
  }
@@ -1294,18 +1301,18 @@ async function loadChangeTarget(
1294
1301
  ): Promise<{ rig: Rig; baseVersion: RigVersion; change: RigChange }> {
1295
1302
  const change = await getRigChange(db, workspaceId, changeId);
1296
1303
  if (!change) {
1297
- throw new Error(`Rig change not found: ${changeId}`);
1304
+ throw new Error(`Sandbox Environment change not found: ${changeId}`);
1298
1305
  }
1299
1306
  const rig = await getRig(db, workspaceId, change.rigId);
1300
1307
  if (!rig) {
1301
- throw new Error(`Rig not found for change: ${change.rigId}`);
1308
+ throw new Error(`Sandbox Environment not found for change: ${change.rigId}`);
1302
1309
  }
1303
1310
  if (!change.baseVersionId) {
1304
- throw new Error(`Rig change ${change.id} has no base version`);
1311
+ throw new Error(`Sandbox Environment change ${change.id} has no base version`);
1305
1312
  }
1306
1313
  const baseVersion = await getRigVersionById(db, workspaceId, change.baseVersionId);
1307
1314
  if (!baseVersion || baseVersion.rigId !== rig.id) {
1308
- throw new Error(`Base rig version not found: ${change.baseVersionId}`);
1315
+ throw new Error(`Base sandbox environment version not found: ${change.baseVersionId}`);
1309
1316
  }
1310
1317
  return { rig, baseVersion, change };
1311
1318
  }
@@ -1317,11 +1324,11 @@ async function loadVersionTarget(
1317
1324
  ): Promise<{ rig: Rig; version: RigVersion }> {
1318
1325
  const version = await getRigVersionById(db, workspaceId, versionId);
1319
1326
  if (!version) {
1320
- throw new Error(`Rig version not found: ${versionId}`);
1327
+ throw new Error(`Sandbox Environment version not found: ${versionId}`);
1321
1328
  }
1322
1329
  const rig = await getRig(db, workspaceId, version.rigId);
1323
1330
  if (!rig) {
1324
- throw new Error(`Rig not found for version: ${version.rigId}`);
1331
+ throw new Error(`Sandbox Environment not found for version: ${version.rigId}`);
1325
1332
  }
1326
1333
  return { rig, version };
1327
1334
  }
@@ -1373,12 +1380,7 @@ export function createRigVerificationActivities(services: () => Promise<ControlA
1373
1380
  change,
1374
1381
  candidateVersion,
1375
1382
  );
1376
- const packRuntime = await resolveWorkspacePackRuntime(db, input.workspaceId);
1377
- const runSettings = settingsForRigVerification(
1378
- settings,
1379
- packRuntime,
1380
- candidateVersion.image,
1381
- );
1383
+ const runSettings = settingsForRigVerification(settings, candidateVersion.image);
1382
1384
  const providerImageContentHash = rigProviderImageContentHash({
1383
1385
  backend: runSettings.sandboxBackend,
1384
1386
  sourceImage: rigProviderImageSourceImage(runSettings, runSettings.sandboxBackend),
@@ -1452,7 +1454,7 @@ export function createRigVerificationActivities(services: () => Promise<ControlA
1452
1454
  );
1453
1455
  if (markerResult.exitCode !== 0) {
1454
1456
  throw new Error(
1455
- `Failed to seal rig provider image content marker: ${markerResult.output.slice(-2000)}`,
1457
+ `Failed to seal sandbox environment provider image content marker: ${markerResult.output.slice(-2000)}`,
1456
1458
  );
1457
1459
  }
1458
1460
  const platformCheckResults = await runRigChecks(
@@ -1572,8 +1574,7 @@ export function createRigVerificationActivities(services: () => Promise<ControlA
1572
1574
  metadata: { versionId: version.id },
1573
1575
  });
1574
1576
  try {
1575
- const packRuntime = await resolveWorkspacePackRuntime(db, input.workspaceId);
1576
- const runSettings = settingsForRigVerification(settings, packRuntime, version.image);
1577
+ const runSettings = settingsForRigVerification(settings, version.image);
1577
1578
  const providerImageContentHash = rigProviderImageContentHash({
1578
1579
  backend: runSettings.sandboxBackend,
1579
1580
  sourceImage: rigProviderImageSourceImage(runSettings, runSettings.sandboxBackend),
@@ -1615,7 +1616,7 @@ export function createRigVerificationActivities(services: () => Promise<ControlA
1615
1616
  );
1616
1617
  if (markerResult.exitCode !== 0) {
1617
1618
  throw new Error(
1618
- `Failed to seal rig provider image content marker: ${markerResult.output.slice(-2000)}`,
1619
+ `Failed to seal sandbox environment provider image content marker: ${markerResult.output.slice(-2000)}`,
1619
1620
  );
1620
1621
  }
1621
1622
  const platformCheckResults = await runRigChecks(
@@ -304,19 +304,13 @@ function attachmentRefsFromItem(item: Record<string, unknown>): FileResourceRef[
304
304
  return refs;
305
305
  }
306
306
 
307
- function attachmentReceiptText(ref: FileResourceRef, file: FileAsset | undefined): string {
308
- if (!file) {
309
- return (
310
- `[Earlier attachment: fileId=${ref.fileId}; mountDirectory=${resourceMountPath(ref)}. ` +
311
- `Use the existing file there, or call files__files_get_download_url with this fileId and ` +
312
- `download it with the shell.]`
313
- );
314
- }
315
- const path = sandboxFilePath(ref, file);
307
+ function attachmentReceiptText(ref: FileResourceRef): string {
308
+ // The durable reference is immutable; live metadata/authority must not rewrite
309
+ // old receipt text. Pixel delivery remains subject to current file authority.
316
310
  return (
317
- `[Attachment: ${file.safeFilename}; fileId=${file.id}; type=${file.contentType}; ` +
318
- `bytes=${file.sizeBytes}; path=${path}. If the local path is absent, call ` +
319
- `files__files_get_download_url with this fileId and download it with the shell.]`
311
+ `[Attachment: fileId=${ref.fileId}; mountDirectory=${resourceMountPath(ref)}. ` +
312
+ `Use the existing file there, or call files__files_get_download_url with this fileId and ` +
313
+ `download it with the shell.]`
320
314
  );
321
315
  }
322
316
 
@@ -434,7 +428,7 @@ export function createModelHistoryAttachmentProjector(
434
428
  const attachment = currentFile ? contentById.get(ref.fileId) : undefined;
435
429
  const receipt = {
436
430
  type: "input_text",
437
- text: attachmentReceiptText(ref, currentFile),
431
+ text: attachmentReceiptText(ref),
438
432
  };
439
433
  if (!attachment || attachment.kind !== "image") {
440
434
  return [receipt];
@@ -458,12 +452,21 @@ export function withCurrentUserAttachmentRefs(
458
452
  refs: FileResourceRef[],
459
453
  ): Array<Record<string, unknown>> {
460
454
  if (refs.length === 0) return historyItems;
455
+ // Compaction can put a catalog after the triggering user message. A ref
456
+ // already retained anywhere in canonical history must not be copied onto
457
+ // that older catalog (and then disappear when the next turn replays it).
458
+ const retainedIds = new Set(
459
+ historyItems.flatMap((item) => attachmentRefsFromItem(item).map((ref) => ref.fileId)),
460
+ );
461
+ const missing = refs.filter((ref) => !retainedIds.has(ref.fileId));
462
+ if (missing.length === 0) return historyItems;
461
463
  for (let index = historyItems.length - 1; index >= 0; index -= 1) {
462
464
  const item = historyItems[index]!;
465
+ if (item[MODEL_ATTACHMENT_CATALOG_MARKER] === true) continue;
463
466
  if (item.type !== "message" || item.role !== "user") continue;
464
467
  const existing = attachmentRefsFromItem(item);
465
468
  const existingIds = new Set(existing.map((ref) => ref.fileId));
466
- const additions = refs.filter((ref) => !existingIds.has(ref.fileId));
469
+ const additions = missing.filter((ref) => !existingIds.has(ref.fileId));
467
470
  if (additions.length === 0) return historyItems;
468
471
  const projected = [...historyItems];
469
472
  projected[index] = { ...item, [MODEL_ATTACHMENT_REFS_FIELD]: [...existing, ...additions] };
@@ -552,8 +555,14 @@ export async function turnInput(
552
555
  options,
553
556
  );
554
557
  }
555
- if (trigger.type === "system.update.delivered") {
556
- if (updates.length === 0) {
558
+ // Maintenance has no user message or delivered-update batch. It still needs
559
+ // the ordinary history/projection path so SDK preparation can capture the
560
+ // same model request prefix before the queued compaction stops inference.
561
+ if (
562
+ trigger.type === "system.update.delivered" ||
563
+ trigger.type === "session.context.compaction.requested"
564
+ ) {
565
+ if (trigger.type === "system.update.delivered" && updates.length === 0) {
557
566
  throw new Error("Internal update inference has no delivered updates");
558
567
  }
559
568
  return await messageInput(
@@ -1,7 +1,6 @@
1
1
  export {
2
2
  resolveRigProviderImageSelection,
3
3
  rigProviderImageSourceImage,
4
- settingsWithPackSandboxImage,
5
4
  settingsWithRigImage,
6
5
  settingsWithRigProviderImage,
7
6
  type RigProviderImageSelectionReason,