@opengeni/worker-bundle 0.27.3 → 0.28.3-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.
- package/dist/activities/agent-turn/model-usage.d.ts +1 -1
- package/dist/activities/mcp-credentials.d.ts +3 -1
- package/dist/activities/sandbox-lease.d.ts +4 -4
- package/dist/activities/workspace-capture.d.ts +12 -1
- package/dist/{activities-control-WZRFEIJH.js → activities-control-JUBMDBDZ.js} +58 -73
- package/dist/activities-control-JUBMDBDZ.js.map +1 -0
- package/dist/{activities-turn-V7J34ZOF.js → activities-turn-I2ZKGZE6.js} +268 -187
- package/dist/activities-turn-I2ZKGZE6.js.map +1 -0
- package/dist/{chunk-BARTLVBK.js → chunk-A4XQWVZK.js} +25 -25
- package/dist/chunk-A4XQWVZK.js.map +1 -0
- package/dist/{chunk-C54VDT6I.js → chunk-ZNIKZQMN.js} +148 -111
- package/dist/chunk-ZNIKZQMN.js.map +1 -0
- package/dist/index.js +2 -2
- package/dist/observability-metrics.d.ts +12 -4
- package/dist/sandbox-archive-storage.d.ts +15 -3
- package/dist/sandbox-resume.d.ts +1 -1
- package/package.json +17 -17
- package/src/activities/agent-turn/agent-build.ts +30 -1
- package/src/activities/agent-turn/claim.ts +3 -3
- package/src/activities/agent-turn/finalization.ts +62 -41
- package/src/activities/agent-turn/model-usage.ts +10 -1
- package/src/activities/agent-turn/skill-read.ts +2 -21
- package/src/activities/agent-turn/stream-attempt.ts +3 -2
- package/src/activities/agent-turn/tool-environment.ts +52 -10
- package/src/activities/goals.ts +2 -0
- package/src/activities/mcp-credentials.ts +42 -2
- package/src/activities/sandbox-lease.ts +64 -71
- package/src/activities/scheduled-tasks.ts +8 -6
- package/src/activities/workspace-capture.ts +148 -126
- package/src/observability-metrics.ts +28 -24
- package/src/pr-review-credentials.ts +2 -0
- package/src/sandbox-archive-storage.ts +82 -18
- package/src/sandbox-resume.ts +79 -63
- package/dist/activities-control-WZRFEIJH.js.map +0 -1
- package/dist/activities-turn-V7J34ZOF.js.map +0 -1
- package/dist/chunk-BARTLVBK.js.map +0 -1
- package/dist/chunk-C54VDT6I.js.map +0 -1
|
@@ -82,7 +82,10 @@ import {
|
|
|
82
82
|
// box is typed as provider loss. Stale capture reconciliation separately uses
|
|
83
83
|
// establishSandboxSessionFromEnvelope in strict resume-only mode so it can
|
|
84
84
|
// reuse the runtime's provider-ready proof without ever cold-restoring.
|
|
85
|
-
|
|
85
|
+
captureWorkspaceArchiveForStorage,
|
|
86
|
+
disposeWorkspaceArchive,
|
|
87
|
+
type VerifiedWorkspaceArchivePayload,
|
|
88
|
+
type VerifiedHostWorkspaceArchive,
|
|
86
89
|
cancelSelfhostedOp,
|
|
87
90
|
assertConsistentSandboxProviderIdentity,
|
|
88
91
|
createSandboxClientForBackend,
|
|
@@ -160,9 +163,7 @@ import {
|
|
|
160
163
|
} from "../opensandbox-kubernetes-inventory";
|
|
161
164
|
import type { ObjectStorage } from "@opengeni/storage";
|
|
162
165
|
import {
|
|
163
|
-
|
|
164
|
-
deleteUnpublishedWorkspaceArchiveObject,
|
|
165
|
-
deleteWorkspaceArchiveObjectKeys,
|
|
166
|
+
persistWorkspaceArchiveCandidate,
|
|
166
167
|
putVersion1TarArchiveOrInline,
|
|
167
168
|
} from "../sandbox-archive-storage";
|
|
168
169
|
|
|
@@ -210,7 +211,7 @@ type DrainSandboxClient = {
|
|
|
210
211
|
* aborts the terminate before client.delete()).
|
|
211
212
|
*/
|
|
212
213
|
export type PersistArchiveFn = (
|
|
213
|
-
archiveBase64: string | null,
|
|
214
|
+
archiveBase64: string | VerifiedHostWorkspaceArchive | null,
|
|
214
215
|
archiveMetadata?: WorkspaceArchiveDescriptor,
|
|
215
216
|
providerSession?: unknown,
|
|
216
217
|
providerBinding?: Awaited<
|
|
@@ -247,6 +248,7 @@ export type TerminateBoxFn = (
|
|
|
247
248
|
providerCaptureRequestId?: string,
|
|
248
249
|
captureDisposition?: DrainCaptureDisposition,
|
|
249
250
|
capturePolicy?: ProviderWorkspaceCapturePolicy | null,
|
|
251
|
+
diskBackedArchives?: boolean,
|
|
250
252
|
) => Promise<boolean | ProviderTerminationOutcome>;
|
|
251
253
|
|
|
252
254
|
export type SweepModalOrphansFn = (
|
|
@@ -479,6 +481,7 @@ export function createSandboxLeaseActivities(
|
|
|
479
481
|
providerCaptureRequestId,
|
|
480
482
|
captureDisposition,
|
|
481
483
|
capturePolicy,
|
|
484
|
+
diskBackedArchives,
|
|
482
485
|
) =>
|
|
483
486
|
await terminateProviderBox(
|
|
484
487
|
settings,
|
|
@@ -490,6 +493,7 @@ export function createSandboxLeaseActivities(
|
|
|
490
493
|
providerCaptureRequestId,
|
|
491
494
|
captureDisposition,
|
|
492
495
|
capturePolicy,
|
|
496
|
+
diskBackedArchives,
|
|
493
497
|
));
|
|
494
498
|
const sweepModalOrphans: SweepModalOrphansFn =
|
|
495
499
|
options.sweepModalOrphans ?? sweepModalOrphansForConfiguredBackend;
|
|
@@ -2675,7 +2679,7 @@ async function terminateDrainableBox(
|
|
|
2675
2679
|
? (lease.recovery.archive.current?.revision ?? null)
|
|
2676
2680
|
: null;
|
|
2677
2681
|
const persistArchive: PersistArchiveFn = async (
|
|
2678
|
-
archiveBase64: string | null,
|
|
2682
|
+
archiveBase64: string | VerifiedHostWorkspaceArchive | null,
|
|
2679
2683
|
archiveMetadata?: WorkspaceArchiveDescriptor,
|
|
2680
2684
|
_providerSession?: unknown,
|
|
2681
2685
|
providerBinding?: Awaited<
|
|
@@ -2691,6 +2695,7 @@ async function terminateDrainableBox(
|
|
|
2691
2695
|
const archiveMetrics = runtimeMetricsHooksForObservability(observability);
|
|
2692
2696
|
let checkpointArtifactId: string | null = null;
|
|
2693
2697
|
if (
|
|
2698
|
+
typeof archiveBase64 === "string" &&
|
|
2694
2699
|
archiveBase64 &&
|
|
2695
2700
|
archiveMetadata?.version === 2 &&
|
|
2696
2701
|
(archiveMetadata.provider === "modal_snapshot_filesystem" ||
|
|
@@ -2735,59 +2740,33 @@ async function terminateDrainableBox(
|
|
|
2735
2740
|
if (!archiveMetadata) {
|
|
2736
2741
|
throw new Error("Sandbox snapshot publication requires a verified archive descriptor");
|
|
2737
2742
|
}
|
|
2738
|
-
const
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
if (published.workspaceArchiveRef && objectStorage) {
|
|
2766
|
-
if (!result.wrote) {
|
|
2767
|
-
await deleteUnpublishedWorkspaceArchiveObject(
|
|
2768
|
-
objectStorage,
|
|
2769
|
-
published.workspaceArchiveRef,
|
|
2770
|
-
archiveMetrics,
|
|
2771
|
-
);
|
|
2772
|
-
} else {
|
|
2773
|
-
const afterLease = await readLease(db, row.workspaceId, row.sandboxGroupId);
|
|
2774
|
-
const afterKeys = collectWorkspaceArchiveObjectKeys(
|
|
2775
|
-
(afterLease?.resumeState as Record<string, unknown> | null | undefined) ?? null,
|
|
2776
|
-
);
|
|
2777
|
-
await deleteWorkspaceArchiveObjectKeys(
|
|
2778
|
-
objectStorage,
|
|
2779
|
-
[...priorKeys].filter((key) => !afterKeys.has(key)),
|
|
2780
|
-
).catch(() => undefined);
|
|
2781
|
-
}
|
|
2782
|
-
}
|
|
2783
|
-
} catch (error) {
|
|
2784
|
-
await deleteUnpublishedWorkspaceArchiveObject(
|
|
2785
|
-
objectStorage,
|
|
2786
|
-
workspaceArchiveRef,
|
|
2787
|
-
archiveMetrics,
|
|
2788
|
-
);
|
|
2789
|
-
throw error;
|
|
2790
|
-
}
|
|
2743
|
+
const published = await putVersion1TarArchiveOrInline({
|
|
2744
|
+
backend: lease.backend,
|
|
2745
|
+
objectStorage,
|
|
2746
|
+
accountId,
|
|
2747
|
+
workspaceId: row.workspaceId,
|
|
2748
|
+
sandboxGroupId: row.sandboxGroupId,
|
|
2749
|
+
archive:
|
|
2750
|
+
typeof archiveBase64 === "object"
|
|
2751
|
+
? archiveBase64
|
|
2752
|
+
: {
|
|
2753
|
+
bytes: Buffer.from(archiveBase64, "base64"),
|
|
2754
|
+
descriptor: archiveMetadata,
|
|
2755
|
+
base64: archiveBase64,
|
|
2756
|
+
},
|
|
2757
|
+
metrics: archiveMetrics,
|
|
2758
|
+
});
|
|
2759
|
+
result = await persistWorkspaceArchiveCandidate({
|
|
2760
|
+
objectStorage,
|
|
2761
|
+
...(published.workspaceArchiveRef ? { ref: published.workspaceArchiveRef } : {}),
|
|
2762
|
+
persist: () =>
|
|
2763
|
+
persistDrainSnapshot(db, {
|
|
2764
|
+
...baseInput,
|
|
2765
|
+
workspaceArchiveMeta: archiveMetadata,
|
|
2766
|
+
...published,
|
|
2767
|
+
...(checkpointArtifactId ? { checkpointArtifactId } : {}),
|
|
2768
|
+
}),
|
|
2769
|
+
});
|
|
2791
2770
|
}
|
|
2792
2771
|
if (!result.wrote && checkpointArtifactId) {
|
|
2793
2772
|
await markSandboxCheckpointArtifactDeletePending(db, {
|
|
@@ -2823,6 +2802,7 @@ async function terminateDrainableBox(
|
|
|
2823
2802
|
captureClaim?.providerRequestId ?? attempt.operationId,
|
|
2824
2803
|
captureDisposition,
|
|
2825
2804
|
capturePolicy,
|
|
2805
|
+
Boolean(objectStorage),
|
|
2826
2806
|
);
|
|
2827
2807
|
const terminated = typeof termination === "boolean" ? termination : termination.terminated;
|
|
2828
2808
|
if (!terminated) {
|
|
@@ -2955,6 +2935,7 @@ export async function terminateProviderBox(
|
|
|
2955
2935
|
providerCaptureRequestId?: string,
|
|
2956
2936
|
captureDisposition: DrainCaptureDisposition = "capture_required",
|
|
2957
2937
|
claimedCapturePolicy?: ProviderWorkspaceCapturePolicy | null,
|
|
2938
|
+
diskBackedArchives = false,
|
|
2958
2939
|
): Promise<ProviderTerminationOutcome> {
|
|
2959
2940
|
const durableBackendId = (lease.resumeBackendId ?? lease.backend) as string;
|
|
2960
2941
|
const backend = sandboxBackendForSdkBackendId(durableBackendId) ?? durableBackendId;
|
|
@@ -3147,7 +3128,7 @@ export async function terminateProviderBox(
|
|
|
3147
3128
|
// snapshot must re-throw BEFORE any terminate so files are never lost — the next
|
|
3148
3129
|
// sweep retries, the provider idle-timeout is the backstop. A NotFound here (the
|
|
3149
3130
|
// box raced gone between resume and persist) is success: nothing to persist.
|
|
3150
|
-
let verifiedArchive:
|
|
3131
|
+
let verifiedArchive: VerifiedWorkspaceArchivePayload | undefined;
|
|
3151
3132
|
const sessionWorkspacePersistence = (
|
|
3152
3133
|
session as { state?: { workspacePersistence?: unknown } } | undefined
|
|
3153
3134
|
)?.state?.workspacePersistence;
|
|
@@ -3162,10 +3143,15 @@ export async function terminateProviderBox(
|
|
|
3162
3143
|
: null;
|
|
3163
3144
|
try {
|
|
3164
3145
|
if (captureDisposition !== "archive_published" && session?.persistWorkspace) {
|
|
3165
|
-
const capture =
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3146
|
+
const capture = captureWorkspaceArchiveForStorage(
|
|
3147
|
+
session,
|
|
3148
|
+
Date.now(),
|
|
3149
|
+
{
|
|
3150
|
+
requestId: providerCaptureRequestId ?? randomUUID(),
|
|
3151
|
+
strategy: liveCapturePolicy.strategy,
|
|
3152
|
+
},
|
|
3153
|
+
diskBackedArchives,
|
|
3154
|
+
);
|
|
3169
3155
|
verifiedArchive = await awaitProviderCaptureWithLatePublication({
|
|
3170
3156
|
capture,
|
|
3171
3157
|
timeoutMs: settings.sandboxSnapshotTimeoutMs,
|
|
@@ -3179,7 +3165,7 @@ export async function terminateProviderBox(
|
|
|
3179
3165
|
publishLate: async (archive) => {
|
|
3180
3166
|
try {
|
|
3181
3167
|
const result = await persistArchive(
|
|
3182
|
-
archive.base64,
|
|
3168
|
+
archive.kind === "host_spool" ? archive : archive.base64,
|
|
3183
3169
|
archive.descriptor,
|
|
3184
3170
|
session,
|
|
3185
3171
|
checkpointBinding,
|
|
@@ -3197,6 +3183,8 @@ export async function terminateProviderBox(
|
|
|
3197
3183
|
...logIdentity,
|
|
3198
3184
|
error: error instanceof Error ? error.message : String(error),
|
|
3199
3185
|
});
|
|
3186
|
+
} finally {
|
|
3187
|
+
await disposeWorkspaceArchive(archive);
|
|
3200
3188
|
}
|
|
3201
3189
|
},
|
|
3202
3190
|
observeLateFailure: (error) => {
|
|
@@ -3237,12 +3225,17 @@ export async function terminateProviderBox(
|
|
|
3237
3225
|
...logIdentity,
|
|
3238
3226
|
});
|
|
3239
3227
|
} else if (verifiedArchive) {
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3228
|
+
let wrote: boolean;
|
|
3229
|
+
try {
|
|
3230
|
+
({ wrote } = await persistArchive(
|
|
3231
|
+
verifiedArchive.kind === "host_spool" ? verifiedArchive : verifiedArchive.base64,
|
|
3232
|
+
verifiedArchive.descriptor,
|
|
3233
|
+
session,
|
|
3234
|
+
checkpointBinding,
|
|
3235
|
+
));
|
|
3236
|
+
} finally {
|
|
3237
|
+
await disposeWorkspaceArchive(verifiedArchive);
|
|
3238
|
+
}
|
|
3246
3239
|
if (!wrote) {
|
|
3247
3240
|
observability.info(
|
|
3248
3241
|
"sandbox reaper: lease re-armed during persist — leaving box RUNNING (no terminate)",
|
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
SCHEDULED_TASK_OCCURRENCE_PAYLOAD_MAX_BYTES,
|
|
9
9
|
ScheduledTaskRunAcceptedExecution,
|
|
10
10
|
SessionAgentAccess,
|
|
11
|
-
SessionEndUser,
|
|
12
11
|
SessionMemoryScope,
|
|
13
12
|
normalizeAutomaticSessionTitle,
|
|
14
13
|
scheduledOccurrencePayloadUtf8Bytes,
|
|
@@ -2578,26 +2577,29 @@ async function replayScheduledTaskDispatch(input: {
|
|
|
2578
2577
|
* facts the creating session projection exposed at task creation are set;
|
|
2579
2578
|
* a null (or no longer valid) key leaves the generated session on its own
|
|
2580
2579
|
* default. The field names are the session access-scope contract
|
|
2581
|
-
* (`agentAccess`, `
|
|
2580
|
+
* (`agentAccess`, `scopeSubjectId`, `memoryScope`) consumed by session create.
|
|
2582
2581
|
*/
|
|
2583
2582
|
function scheduledCreatorSessionPolicyInput(
|
|
2584
2583
|
policy: {
|
|
2585
2584
|
agentAccess: string | null;
|
|
2586
|
-
|
|
2585
|
+
scopeSubjectId: string | null;
|
|
2587
2586
|
memoryScope: string | null;
|
|
2588
2587
|
} | null,
|
|
2589
2588
|
): {
|
|
2590
2589
|
agentAccess?: SessionAgentAccess;
|
|
2591
|
-
|
|
2590
|
+
scopeSubjectId?: string;
|
|
2592
2591
|
memoryScope?: SessionMemoryScope;
|
|
2593
2592
|
} {
|
|
2594
2593
|
if (!policy) return {};
|
|
2595
2594
|
const agentAccess = SessionAgentAccess.safeParse(policy.agentAccess);
|
|
2596
|
-
const endUser = SessionEndUser.safeParse(policy.endUser);
|
|
2597
2595
|
const memoryScope = SessionMemoryScope.safeParse(policy.memoryScope);
|
|
2598
2596
|
return {
|
|
2599
2597
|
...(agentAccess.success ? { agentAccess: agentAccess.data } : {}),
|
|
2600
|
-
|
|
2598
|
+
// This is a trusted DB admission input, not the public create payload.
|
|
2599
|
+
// Preserve the immutable creator policy through scheduled materialization.
|
|
2600
|
+
...(policy.scopeSubjectId && /^(?:user:|external_user:).+/u.test(policy.scopeSubjectId)
|
|
2601
|
+
? { scopeSubjectId: policy.scopeSubjectId }
|
|
2602
|
+
: {}),
|
|
2601
2603
|
...(memoryScope.success ? { memoryScope: memoryScope.data } : {}),
|
|
2602
2604
|
};
|
|
2603
2605
|
}
|