@opengeni/worker-bundle 0.28.3 → 0.28.4-canary.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dist/activities/agent-turn/mcp-operation-read-tool.d.ts +16 -0
  2. package/dist/activities/mcp-operation-authority.d.ts +16 -0
  3. package/dist/activities/mcp-operation-observer.d.ts +14 -0
  4. package/dist/activities/mcp-operation-reader.d.ts +45 -0
  5. package/dist/activities/mcp-operation-store.d.ts +6 -0
  6. package/dist/activities/sandbox-lease.d.ts +4 -4
  7. package/dist/{activities-control-UXGPMDL3.js → activities-control-J5QNRWVH.js} +56 -70
  8. package/dist/activities-control-J5QNRWVH.js.map +1 -0
  9. package/dist/{activities-turn-NOYDE7PX.js → activities-turn-ZJBY3W5D.js} +15692 -799
  10. package/dist/activities-turn-ZJBY3W5D.js.map +1 -0
  11. package/dist/artifact-materializer-entry.js +2 -0
  12. package/dist/artifact-materializer-entry.js.map +1 -1
  13. package/dist/artifact-outbox-entry.js +2 -0
  14. package/dist/artifact-outbox-entry.js.map +1 -1
  15. package/dist/{chunk-BARTLVBK.js → chunk-A4XQWVZK.js} +25 -25
  16. package/dist/chunk-A4XQWVZK.js.map +1 -0
  17. package/dist/chunk-PZ5AY32C.js +10 -0
  18. package/dist/chunk-PZ5AY32C.js.map +1 -0
  19. package/dist/{chunk-NNXLW6V7.js → chunk-ZNIKZQMN.js} +144 -111
  20. package/dist/chunk-ZNIKZQMN.js.map +1 -0
  21. package/dist/host-export.js +1 -0
  22. package/dist/index.js +3 -2
  23. package/dist/index.js.map +1 -1
  24. package/dist/observability-metrics.d.ts +12 -4
  25. package/dist/sandbox-archive-storage.d.ts +15 -3
  26. package/dist/sandbox-resume.d.ts +1 -1
  27. package/package.json +18 -17
  28. package/src/activities/agent-turn/claim.ts +3 -3
  29. package/src/activities/agent-turn/finalization.ts +10 -5
  30. package/src/activities/agent-turn/mcp-operation-read-tool.ts +61 -0
  31. package/src/activities/agent-turn/stream-attempt.ts +1 -1
  32. package/src/activities/agent-turn/tool-environment.ts +65 -0
  33. package/src/activities/mcp-credentials.ts +94 -40
  34. package/src/activities/mcp-operation-authority.ts +76 -0
  35. package/src/activities/mcp-operation-observer.ts +86 -0
  36. package/src/activities/mcp-operation-reader.ts +108 -0
  37. package/src/activities/mcp-operation-store.ts +98 -0
  38. package/src/activities/sandbox-lease.ts +64 -71
  39. package/src/observability-metrics.ts +28 -24
  40. package/src/sandbox-archive-storage.ts +82 -18
  41. package/src/sandbox-resume.ts +79 -63
  42. package/dist/activities-control-UXGPMDL3.js.map +0 -1
  43. package/dist/activities-turn-NOYDE7PX.js.map +0 -1
  44. package/dist/chunk-BARTLVBK.js.map +0 -1
  45. package/dist/chunk-NNXLW6V7.js.map +0 -1
@@ -0,0 +1,16 @@
1
+ import type { AttemptToolDefinition } from "@opengeni/codemode";
2
+ import { z } from "zod";
3
+ declare const selectorSchema: z.ZodUnion<readonly [z.ZodObject<{
4
+ operationId: z.ZodString;
5
+ }, z.core.$strict>, z.ZodObject<{
6
+ sourceTurnId: z.ZodString;
7
+ sourceCallId: z.ZodString;
8
+ }, z.core.$strict>]>;
9
+ export type McpOperationReadSelector = z.infer<typeof selectorSchema>;
10
+ /** Attempt-local adapter. The supplied read closure owns canonical session
11
+ * access, current provider authority, immutable binding checks and settlement.
12
+ * No caller-controlled provider parameters cross this tool boundary. */
13
+ export declare function createOperationReadAttemptToolDefinition(input: {
14
+ read: (selector: McpOperationReadSelector) => Promise<Record<string, unknown>>;
15
+ }): AttemptToolDefinition;
16
+ export {};
@@ -0,0 +1,16 @@
1
+ import type { ConnectionUseAttribution } from "@opengeni/contracts/connection-authority";
2
+ import type { HostMcpAcceptedAuthority } from "@opengeni/contracts/host-mcp-bindings";
3
+ import type { ResolveConnectionCredentialInput } from "@opengeni/db";
4
+ /** Metadata only. Callers must obtain authority from a current live fence.
5
+ * This equality key is never authorization and never replaces physical-use checks. */
6
+ export declare function mcpOperationAuthorityDigest(request: ResolveConnectionCredentialInput, authority: {
7
+ native: ConnectionUseAttribution;
8
+ host?: never;
9
+ principal?: {
10
+ kind: string;
11
+ subjectId?: string;
12
+ };
13
+ } | {
14
+ host: HostMcpAcceptedAuthority;
15
+ native?: never;
16
+ }): string;
@@ -0,0 +1,14 @@
1
+ import type { Settings } from "@opengeni/config";
2
+ import type { AttemptToolEnvironment } from "@opengeni/codemode";
3
+ import { type ResolveConnectionCredentialInput, type ResolveConnectionCredentialResult } from "@opengeni/runtime";
4
+ import type { McpOperationReaderDependencies } from "./mcp-operation-reader.js";
5
+ /** Current-attempt adapter: no credential renewal authority survives this
6
+ * closure. The stored digest constrains fresh authority, never establishes it. */
7
+ export declare function createMcpOperationObserverResolver(input: {
8
+ settings: Pick<Settings, "mcpServers">;
9
+ workspaceId: string;
10
+ credentialSubjectId?: string;
11
+ assertAttempt: () => Promise<void>;
12
+ resolveCredential: (request: ResolveConnectionCredentialInput) => Promise<ResolveConnectionCredentialResult>;
13
+ getEnvironment: () => Promise<AttemptToolEnvironment | null>;
14
+ }): McpOperationReaderDependencies["resolveObserver"];
@@ -0,0 +1,45 @@
1
+ import type { AttemptToolResult } from "@opengeni/contracts";
2
+ import { type McpObservationReceipt } from "@opengeni/runtime";
3
+ import type { McpOperationReadSelector } from "./agent-turn/mcp-operation-read-tool.js";
4
+ type TerminalReceipt = Extract<McpObservationReceipt, {
5
+ status: "completed";
6
+ }>;
7
+ /** Internal, credential-free projection loaded through canonical current
8
+ * attempt/session authorization. Never return this object directly to tools. */
9
+ export type McpOperationReadRecord = {
10
+ operationId: string;
11
+ sourceTurnId: string;
12
+ sourceCallId: string | null;
13
+ serverId: string;
14
+ originalTool: string;
15
+ observerTool: string;
16
+ argumentDigest: string;
17
+ destinationDigest: string;
18
+ authorityDigest: string;
19
+ originalOutcome: "captured" | "completed" | "outcome_unknown";
20
+ originalResult: AttemptToolResult | null;
21
+ receipt: TerminalReceipt | null;
22
+ };
23
+ type ObserverResolution = {
24
+ status: "unsupported" | "auth_needed" | "binding_changed";
25
+ } | {
26
+ status: "ready";
27
+ authorize: (phase: "before_request" | "before_delivery") => Promise<boolean>;
28
+ callObserver: (tool: string, args: Record<string, unknown>) => Promise<unknown>;
29
+ };
30
+ export type McpOperationReaderDependencies = {
31
+ /** Includes live attempt and original-principal/session disclosure checks. */
32
+ load: (selector: McpOperationReadSelector) => Promise<McpOperationReadRecord | null>;
33
+ claim: (operationId: string) => Promise<string | null>;
34
+ release: (operationId: string, claimId: string) => Promise<void>;
35
+ /** Claim-fenced transaction storing one immutable receipt. Must recheck
36
+ * canonical current authority and never rewrite the original outcome.
37
+ * Delivery uses the ordinary operation_read tool-result lifecycle. */
38
+ settle: (operationId: string, claimId: string, receipt: TerminalReceipt) => Promise<McpOperationReadRecord>;
39
+ /** Binds the current trusted config/connection to the persisted original
40
+ * digests. Model arguments may not supply or replace any of that authority. */
41
+ resolveObserver: (operation: McpOperationReadRecord) => Promise<ObserverResolution>;
42
+ };
43
+ /** One explicit read; no timer, inference wake, or mutation replay. */
44
+ export declare function readMcpOperation(selector: McpOperationReadSelector, dependencies: McpOperationReaderDependencies): Promise<Record<string, unknown>>;
45
+ export {};
@@ -0,0 +1,6 @@
1
+ import type { Database } from "@opengeni/db";
2
+ import { type McpOperationAttempt } from "@opengeni/db/mcp-operations";
3
+ import type { McpOperationReaderDependencies } from "./mcp-operation-reader.js";
4
+ /** All DB calls remain bound to the actual accepted worker attempt. Locators
5
+ * supplied to operation_read cannot replace this scope or its principal. */
6
+ export declare function createMcpOperationReadStore(db: Database, attempt: McpOperationAttempt): Pick<McpOperationReaderDependencies, "load" | "claim" | "release" | "settle">;
@@ -2,7 +2,7 @@ import type { ProviderCommandPersistence } from "@opengeni/runtime";
2
2
  import { type OpStatus } from "@opengeni/agent-proto";
3
3
  import { listLiveModalSandboxLeaseAttributions, readLease, type ReapDrainable, type RetainedProcessProviderProof, type SandboxRetainedProcess, type LeaseSnapshot } from "@opengeni/db";
4
4
  import { type ConnectedMachineBackgroundCommandClaim, type ConnectedMachineBackgroundCommandProof } from "@opengeni/db/session-background-commands";
5
- import { createSandboxClientForBackend, inspectModalSandboxLifecycle, resolveModalCheckpointProviderBindingForSession, terminateModalSandboxById, type ModalOrphanSweepTermination, type ModalCheckpointProviderBinding, type ProviderWorkspaceCapturePolicy, type WorkspaceArchiveDescriptor, type ControlRpc } from "@opengeni/runtime/sandbox";
5
+ import { type VerifiedHostWorkspaceArchive, createSandboxClientForBackend, inspectModalSandboxLifecycle, resolveModalCheckpointProviderBindingForSession, terminateModalSandboxById, type ModalOrphanSweepTermination, type ModalCheckpointProviderBinding, type ProviderWorkspaceCapturePolicy, type WorkspaceArchiveDescriptor, type ControlRpc } from "@opengeni/runtime/sandbox";
6
6
  import { type SandboxDrainActivityInput, type SandboxLeaseSweepMaintenanceInput } from "../sandbox-reaper-contract.js";
7
7
  import type { ControlActivityServices as ActivityServices } from "./types.js";
8
8
  import { type RetainedProcessReconciliationOutcome } from "../observability-metrics.js";
@@ -40,7 +40,7 @@ type CreateSandboxClientForBackendFn = typeof createSandboxClientForBackend;
40
40
  * backends with no persistWorkspace — ensures a re-arm during the snapshot window
41
41
  * aborts the terminate before client.delete()).
42
42
  */
43
- export type PersistArchiveFn = (archiveBase64: string | null, archiveMetadata?: WorkspaceArchiveDescriptor, providerSession?: unknown, providerBinding?: Awaited<ReturnType<typeof resolveModalCheckpointProviderBindingForSession>> | null) => Promise<{
43
+ export type PersistArchiveFn = (archiveBase64: string | VerifiedHostWorkspaceArchive | null, archiveMetadata?: WorkspaceArchiveDescriptor, providerSession?: unknown, providerBinding?: Awaited<ReturnType<typeof resolveModalCheckpointProviderBindingForSession>> | null) => Promise<{
44
44
  wrote: boolean;
45
45
  archiveRevision?: string | null;
46
46
  }>;
@@ -60,7 +60,7 @@ export type DrainCaptureDisposition = "capture_required" | "archive_published";
60
60
  * Test seams may return the legacy boolean shorthand. Production returns the
61
61
  * typed outcome so the cold commit can distinguish a clean stop from definitive
62
62
  * provider disappearance before capture. */
63
- export type TerminateBoxFn = (settings: ActivityServices["settings"], lease: NonNullable<Awaited<ReturnType<typeof readLease>>>, observability: ActivityServices["observability"], persistArchive: PersistArchiveFn, providerCaptureRequestId?: string, captureDisposition?: DrainCaptureDisposition, capturePolicy?: ProviderWorkspaceCapturePolicy | null) => Promise<boolean | ProviderTerminationOutcome>;
63
+ export type TerminateBoxFn = (settings: ActivityServices["settings"], lease: NonNullable<Awaited<ReturnType<typeof readLease>>>, observability: ActivityServices["observability"], persistArchive: PersistArchiveFn, providerCaptureRequestId?: string, captureDisposition?: DrainCaptureDisposition, capturePolicy?: ProviderWorkspaceCapturePolicy | null, diskBackedArchives?: boolean) => Promise<boolean | ProviderTerminationOutcome>;
64
64
  export type SweepModalOrphansFn = (settings: ActivityServices["settings"], db: ActivityServices["db"], observability: ActivityServices["observability"]) => Promise<number>;
65
65
  export type InspectOpenSandboxKubernetesInventoryFn = (input: {
66
66
  namespace: string;
@@ -199,4 +199,4 @@ export declare function sandboxDrainReason(lease: Pick<LeaseSnapshot, "rotationR
199
199
  * draining until its adapter can prove termination. A truly instance-less or
200
200
  * `none`-backed row is a no-op.
201
201
  */
202
- export declare function terminateProviderBox(settings: ActivityServices["settings"], lease: NonNullable<Awaited<ReturnType<typeof readLease>>>, observability: ActivityServices["observability"], persistArchive: PersistArchiveFn, createClientForBackend?: CreateSandboxClientForBackendFn, terminateModalById?: typeof terminateModalSandboxById, providerCaptureRequestId?: string, captureDisposition?: DrainCaptureDisposition, claimedCapturePolicy?: ProviderWorkspaceCapturePolicy | null): Promise<ProviderTerminationOutcome>;
202
+ export declare function terminateProviderBox(settings: ActivityServices["settings"], lease: NonNullable<Awaited<ReturnType<typeof readLease>>>, observability: ActivityServices["observability"], persistArchive: PersistArchiveFn, createClientForBackend?: CreateSandboxClientForBackendFn, terminateModalById?: typeof terminateModalSandboxById, providerCaptureRequestId?: string, captureDisposition?: DrainCaptureDisposition, claimedCapturePolicy?: ProviderWorkspaceCapturePolicy | null, diskBackedArchives?: boolean): Promise<ProviderTerminationOutcome>;
@@ -10,18 +10,16 @@ import {
10
10
  MAX_AUTOMATIC_PROVIDER_RECOVERIES,
11
11
  assertReusableSessionRevivable,
12
12
  captureConnectedCommandOutput,
13
- collectWorkspaceArchiveObjectKeys,
14
13
  createCodexCapacityActivities,
15
14
  createGoalActivities,
16
15
  createSharedActivityServices,
17
16
  currentActivityContext,
18
- deleteUnpublishedWorkspaceArchiveObject,
19
- deleteWorkspaceArchiveObjectKeys,
20
17
  deliverFailedChildTurnToParent,
21
18
  evaluateIncidentTelemetryPreflight,
22
19
  incidentTelemetryAuthorityFence,
23
20
  incidentTelemetryPreflightDeclaration,
24
21
  notifyParentOfChildIdle,
22
+ persistWorkspaceArchiveCandidate,
25
23
  providerRecoveryCountFromMetadata,
26
24
  putVersion1TarArchiveOrInline,
27
25
  reconcileAutomaticSessionTitleFanout,
@@ -33,7 +31,7 @@ import {
33
31
  scheduledUserMessagePayload,
34
32
  withFirstPartyTools,
35
33
  workflowIdForSession
36
- } from "./chunk-NNXLW6V7.js";
34
+ } from "./chunk-ZNIKZQMN.js";
37
35
  import {
38
36
  inspectOpenSandboxKubernetesInventory,
39
37
  recordCreditBalanceGauges,
@@ -53,7 +51,8 @@ import {
53
51
  recordTurnsQueuedGauge,
54
52
  recordWorkerDeathRecoveryMetrics,
55
53
  runtimeMetricsHooksForObservability
56
- } from "./chunk-BARTLVBK.js";
54
+ } from "./chunk-A4XQWVZK.js";
55
+ import "./chunk-PZ5AY32C.js";
57
56
 
58
57
  // src/activities/browser-state-artifact-reaper.ts
59
58
  import {
@@ -5243,7 +5242,8 @@ import { sandboxWarmRateMicrosPerSecond } from "@opengeni/config";
5243
5242
  import { appendSessionCommandOutput } from "@opengeni/db/session-command-output";
5244
5243
  import { sandboxLeaseTelemetryKey } from "@opengeni/observability";
5245
5244
  import {
5246
- captureVerifiedWorkspaceArchive,
5245
+ captureWorkspaceArchiveForStorage,
5246
+ disposeWorkspaceArchive,
5247
5247
  cancelSelfhostedOp,
5248
5248
  assertConsistentSandboxProviderIdentity,
5249
5249
  createSandboxClientForBackend,
@@ -5362,7 +5362,7 @@ function sandboxDrainActivityAttempt() {
5362
5362
  }
5363
5363
  }
5364
5364
  function createSandboxLeaseActivities(services, options = {}) {
5365
- const terminateBox = options.terminateBox ?? (async (settings, lease, observability, persistArchive, providerCaptureRequestId, captureDisposition, capturePolicy) => await terminateProviderBox(
5365
+ const terminateBox = options.terminateBox ?? (async (settings, lease, observability, persistArchive, providerCaptureRequestId, captureDisposition, capturePolicy, diskBackedArchives) => await terminateProviderBox(
5366
5366
  settings,
5367
5367
  lease,
5368
5368
  observability,
@@ -5371,7 +5371,8 @@ function createSandboxLeaseActivities(services, options = {}) {
5371
5371
  terminateModalSandboxById,
5372
5372
  providerCaptureRequestId,
5373
5373
  captureDisposition,
5374
- capturePolicy
5374
+ capturePolicy,
5375
+ diskBackedArchives
5375
5376
  ));
5376
5377
  const sweepModalOrphans = options.sweepModalOrphans ?? sweepModalOrphansForConfiguredBackend;
5377
5378
  const inspectOpenSandboxInventory = options.inspectOpenSandboxKubernetesInventory ?? inspectOpenSandboxKubernetesInventory;
@@ -7044,7 +7045,7 @@ async function terminateDrainableBox(db, settings, row, observability, terminate
7044
7045
  }
7045
7046
  const archiveMetrics = runtimeMetricsHooksForObservability(observability);
7046
7047
  let checkpointArtifactId = null;
7047
- if (archiveBase64 && archiveMetadata?.version === 2 && (archiveMetadata.provider === "modal_snapshot_filesystem" || archiveMetadata.provider === "modal_snapshot_directory")) {
7048
+ if (typeof archiveBase64 === "string" && archiveBase64 && archiveMetadata?.version === 2 && (archiveMetadata.provider === "modal_snapshot_filesystem" || archiveMetadata.provider === "modal_snapshot_directory")) {
7048
7049
  if (!providerBinding) {
7049
7050
  throw new Error("Modal native snapshot has no exact session provider identity");
7050
7051
  }
@@ -7084,57 +7085,29 @@ async function terminateDrainableBox(db, settings, row, observability, terminate
7084
7085
  if (!archiveMetadata) {
7085
7086
  throw new Error("Sandbox snapshot publication requires a verified archive descriptor");
7086
7087
  }
7087
- const priorKeys = collectWorkspaceArchiveObjectKeys(
7088
- lease.resumeState ?? null
7089
- );
7090
- let workspaceArchiveRef;
7091
- try {
7092
- const published = await putVersion1TarArchiveOrInline({
7093
- backend: lease.backend,
7094
- objectStorage,
7095
- accountId,
7096
- workspaceId: row.workspaceId,
7097
- sandboxGroupId: row.sandboxGroupId,
7098
- archive: {
7099
- bytes: Buffer.from(archiveBase64, "base64"),
7100
- descriptor: archiveMetadata,
7101
- base64: archiveBase64
7102
- },
7103
- metrics: archiveMetrics
7104
- });
7105
- workspaceArchiveRef = published.workspaceArchiveRef;
7106
- result = await persistDrainSnapshot(db, {
7088
+ const published = await putVersion1TarArchiveOrInline({
7089
+ backend: lease.backend,
7090
+ objectStorage,
7091
+ accountId,
7092
+ workspaceId: row.workspaceId,
7093
+ sandboxGroupId: row.sandboxGroupId,
7094
+ archive: typeof archiveBase64 === "object" ? archiveBase64 : {
7095
+ bytes: Buffer.from(archiveBase64, "base64"),
7096
+ descriptor: archiveMetadata,
7097
+ base64: archiveBase64
7098
+ },
7099
+ metrics: archiveMetrics
7100
+ });
7101
+ result = await persistWorkspaceArchiveCandidate({
7102
+ objectStorage,
7103
+ ...published.workspaceArchiveRef ? { ref: published.workspaceArchiveRef } : {},
7104
+ persist: () => persistDrainSnapshot(db, {
7107
7105
  ...baseInput,
7108
7106
  workspaceArchiveMeta: archiveMetadata,
7109
7107
  ...published,
7110
7108
  ...checkpointArtifactId ? { checkpointArtifactId } : {}
7111
- });
7112
- if (published.workspaceArchiveRef && objectStorage) {
7113
- if (!result.wrote) {
7114
- await deleteUnpublishedWorkspaceArchiveObject(
7115
- objectStorage,
7116
- published.workspaceArchiveRef,
7117
- archiveMetrics
7118
- );
7119
- } else {
7120
- const afterLease = await readLease(db, row.workspaceId, row.sandboxGroupId);
7121
- const afterKeys = collectWorkspaceArchiveObjectKeys(
7122
- afterLease?.resumeState ?? null
7123
- );
7124
- await deleteWorkspaceArchiveObjectKeys(
7125
- objectStorage,
7126
- [...priorKeys].filter((key) => !afterKeys.has(key))
7127
- ).catch(() => void 0);
7128
- }
7129
- }
7130
- } catch (error) {
7131
- await deleteUnpublishedWorkspaceArchiveObject(
7132
- objectStorage,
7133
- workspaceArchiveRef,
7134
- archiveMetrics
7135
- );
7136
- throw error;
7137
- }
7109
+ })
7110
+ });
7138
7111
  }
7139
7112
  if (!result.wrote && checkpointArtifactId) {
7140
7113
  await markSandboxCheckpointArtifactDeletePending2(db, {
@@ -7157,7 +7130,8 @@ async function terminateDrainableBox(db, settings, row, observability, terminate
7157
7130
  persistArchive,
7158
7131
  captureClaim?.providerRequestId ?? attempt.operationId,
7159
7132
  captureDisposition,
7160
- capturePolicy
7133
+ capturePolicy,
7134
+ Boolean(objectStorage)
7161
7135
  );
7162
7136
  const terminated = typeof termination === "boolean" ? termination : termination.terminated;
7163
7137
  if (!terminated) {
@@ -7213,7 +7187,7 @@ function providerDrainLogIdentity(lease, backend) {
7213
7187
  instanceId: lease.instanceId
7214
7188
  };
7215
7189
  }
7216
- async function terminateProviderBox(settings, lease, observability, persistArchive, createClientForBackend = createSandboxClientForBackend, terminateModalById = terminateModalSandboxById, providerCaptureRequestId, captureDisposition = "capture_required", claimedCapturePolicy) {
7190
+ async function terminateProviderBox(settings, lease, observability, persistArchive, createClientForBackend = createSandboxClientForBackend, terminateModalById = terminateModalSandboxById, providerCaptureRequestId, captureDisposition = "capture_required", claimedCapturePolicy, diskBackedArchives = false) {
7217
7191
  const durableBackendId = lease.resumeBackendId ?? lease.backend;
7218
7192
  const backend = sandboxBackendForSdkBackendId(durableBackendId) ?? durableBackendId;
7219
7193
  const logIdentity = providerDrainLogIdentity(lease, backend);
@@ -7335,10 +7309,15 @@ async function terminateProviderBox(settings, lease, observability, persistArchi
7335
7309
  ) : null;
7336
7310
  try {
7337
7311
  if (captureDisposition !== "archive_published" && session?.persistWorkspace) {
7338
- const capture = captureVerifiedWorkspaceArchive(session, Date.now(), {
7339
- requestId: providerCaptureRequestId ?? randomUUID2(),
7340
- strategy: liveCapturePolicy.strategy
7341
- });
7312
+ const capture = captureWorkspaceArchiveForStorage(
7313
+ session,
7314
+ Date.now(),
7315
+ {
7316
+ requestId: providerCaptureRequestId ?? randomUUID2(),
7317
+ strategy: liveCapturePolicy.strategy
7318
+ },
7319
+ diskBackedArchives
7320
+ );
7342
7321
  verifiedArchive = await awaitProviderCaptureWithLatePublication({
7343
7322
  capture,
7344
7323
  timeoutMs: settings.sandboxSnapshotTimeoutMs,
@@ -7352,7 +7331,7 @@ async function terminateProviderBox(settings, lease, observability, persistArchi
7352
7331
  publishLate: async (archive) => {
7353
7332
  try {
7354
7333
  const result = await persistArchive(
7355
- archive.base64,
7334
+ archive.kind === "host_spool" ? archive : archive.base64,
7356
7335
  archive.descriptor,
7357
7336
  session,
7358
7337
  checkpointBinding
@@ -7368,6 +7347,8 @@ async function terminateProviderBox(settings, lease, observability, persistArchi
7368
7347
  ...logIdentity,
7369
7348
  error: error instanceof Error ? error.message : String(error)
7370
7349
  });
7350
+ } finally {
7351
+ await disposeWorkspaceArchive(archive);
7371
7352
  }
7372
7353
  },
7373
7354
  observeLateFailure: (error) => {
@@ -7399,12 +7380,17 @@ async function terminateProviderBox(settings, lease, observability, persistArchi
7399
7380
  ...logIdentity
7400
7381
  });
7401
7382
  } else if (verifiedArchive) {
7402
- const { wrote } = await persistArchive(
7403
- verifiedArchive.base64,
7404
- verifiedArchive.descriptor,
7405
- session,
7406
- checkpointBinding
7407
- );
7383
+ let wrote;
7384
+ try {
7385
+ ({ wrote } = await persistArchive(
7386
+ verifiedArchive.kind === "host_spool" ? verifiedArchive : verifiedArchive.base64,
7387
+ verifiedArchive.descriptor,
7388
+ session,
7389
+ checkpointBinding
7390
+ ));
7391
+ } finally {
7392
+ await disposeWorkspaceArchive(verifiedArchive);
7393
+ }
7408
7394
  if (!wrote) {
7409
7395
  observability.info(
7410
7396
  "sandbox reaper: lease re-armed during persist \u2014 leaving box RUNNING (no terminate)",
@@ -10350,4 +10336,4 @@ export {
10350
10336
  createControlActivities,
10351
10337
  createControlActivitiesFromServices
10352
10338
  };
10353
- //# sourceMappingURL=activities-control-UXGPMDL3.js.map
10339
+ //# sourceMappingURL=activities-control-J5QNRWVH.js.map