@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.
- package/dist/activities/agent-turn/codex.d.ts +1 -1
- package/dist/activities/agent-turn/compaction-prep.d.ts +1 -5
- package/dist/activities/agent-turn/errors.d.ts +31 -5
- package/dist/activities/agent-turn/finalization-monitor.d.ts +17 -0
- package/dist/activities/agent-turn/finalization.d.ts +1 -1
- package/dist/activities/agent-turn/governance-model.d.ts +0 -2
- package/dist/activities/agent-turn/quiescence.d.ts +1 -0
- package/dist/activities/agent-turn/recovery-warning.d.ts +8 -0
- package/dist/activities/agent-turn/run-credentials.d.ts +0 -1
- package/dist/activities/agent-turn/sandbox-establish.d.ts +1 -1
- package/dist/activities/agent-turn/sandbox-route.d.ts +0 -20
- package/dist/activities/agent-turn/sandbox-runtime.d.ts +1 -1
- package/dist/activities/agent-turn/skill-remove.d.ts +14 -0
- package/dist/activities/agent-turn/skill-search.d.ts +1 -1
- package/dist/activities/agent-turn/stream-attempt.d.ts +1 -0
- package/dist/activities/agent-turn/tool-environment.d.ts +0 -4
- package/dist/activities/agent-turn/turn-context.d.ts +2 -0
- package/dist/activities/agent-turn/turn-sandbox-access.d.ts +3 -0
- package/dist/activities/codex-capacity.d.ts +6 -1
- package/dist/activities/codex-rotation.d.ts +1 -1
- package/dist/activities/context-compaction.d.ts +7 -1
- package/dist/activities/mcp-account-routes.d.ts +22 -0
- package/dist/activities/mcp-credentials.d.ts +12 -13
- package/dist/activities/mcp-operation-authority.d.ts +0 -5
- package/dist/activities/rig-verification.d.ts +2 -3
- package/dist/activities/sandbox-images.d.ts +1 -1
- package/dist/activities/sandbox-lease.d.ts +4 -3
- package/dist/activities/session-state.d.ts +57 -2
- package/dist/activities/types.d.ts +12 -3
- package/dist/{activities-control-HMFGSKC5.js → activities-control-BOLIY3H4.js} +366 -187
- package/dist/activities-control-BOLIY3H4.js.map +1 -0
- package/dist/activities-control.d.ts +110 -2
- package/dist/{activities-turn-AP67JADS.js → activities-turn-2B3WMHBB.js} +767 -471
- package/dist/activities-turn-2B3WMHBB.js.map +1 -0
- package/dist/activities.d.ts +110 -2
- package/dist/artifact-materializer-entry.js +5 -2
- package/dist/artifact-materializer-entry.js.map +1 -1
- package/dist/artifact-outbox-entry.js +2 -2
- package/dist/artifact-outbox-entry.js.map +1 -1
- package/dist/{chunk-A4XQWVZK.js → chunk-I7HKKMUJ.js} +77 -1
- package/dist/chunk-I7HKKMUJ.js.map +1 -0
- package/dist/{chunk-CYITU5UH.js → chunk-TVEE2UUC.js} +275 -146
- package/dist/chunk-TVEE2UUC.js.map +1 -0
- package/dist/editable-artifact-materializer-service.d.ts +2 -2
- package/dist/editable-artifact-outbox-service.d.ts +2 -2
- package/dist/index.d.ts +55 -1
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/observability-metrics.d.ts +11 -3
- package/dist/retained-process-diagnostics.d.ts +4 -0
- package/dist/sandbox-resume.d.ts +2 -12
- package/dist/sandbox-routing.d.ts +5 -3
- package/dist/sandbox-snapshot-diagnostics.d.ts +20 -0
- package/dist/warm-capture-holder.d.ts +3 -0
- package/dist/workflow-bundle.js +51 -11
- package/package.json +15 -15
- package/src/activities/agent-turn/agent-build.ts +42 -5
- package/src/activities/agent-turn/claim.ts +12 -0
- package/src/activities/agent-turn/codex-capacity.ts +26 -4
- package/src/activities/agent-turn/codex.ts +6 -2
- package/src/activities/agent-turn/compaction-prep.ts +53 -72
- package/src/activities/agent-turn/errors.ts +98 -10
- package/src/activities/agent-turn/failure-settlement.ts +49 -28
- package/src/activities/agent-turn/finalization-monitor.ts +121 -0
- package/src/activities/agent-turn/finalization.ts +79 -21
- package/src/activities/agent-turn/governance-model.ts +15 -19
- package/src/activities/agent-turn/history.ts +24 -10
- package/src/activities/agent-turn/quiescence.ts +3 -0
- package/src/activities/agent-turn/recovery-warning.ts +18 -0
- package/src/activities/agent-turn/run-credentials.ts +3 -7
- package/src/activities/agent-turn/run.ts +68 -52
- package/src/activities/agent-turn/sandbox-establish.ts +10 -2
- package/src/activities/agent-turn/sandbox-route.ts +0 -20
- package/src/activities/agent-turn/sandbox-runtime.ts +40 -7
- package/src/activities/agent-turn/skill-remove.ts +46 -0
- package/src/activities/agent-turn/skill-save.ts +1 -1
- package/src/activities/agent-turn/skill-search.ts +1 -1
- package/src/activities/agent-turn/skill-selection.ts +2 -0
- package/src/activities/agent-turn/skill-tools.ts +10 -5
- package/src/activities/agent-turn/stream-attempt.ts +38 -15
- package/src/activities/agent-turn/tool-environment.ts +44 -29
- package/src/activities/agent-turn/turn-context.ts +3 -0
- package/src/activities/agent-turn/turn-sandbox-access.ts +7 -1
- package/src/activities/capabilities.ts +17 -2
- package/src/activities/codex-capacity.ts +38 -9
- package/src/activities/codex-rotation.ts +18 -5
- package/src/activities/context-compaction.ts +26 -4
- package/src/activities/goals.ts +1 -0
- package/src/activities/google-drive-publication.ts +1 -3
- package/src/activities/mcp-account-routes.ts +139 -0
- package/src/activities/mcp-credentials.ts +83 -194
- package/src/activities/mcp-operation-authority.ts +16 -41
- package/src/activities/parent-wake.ts +8 -0
- package/src/activities/rig-verification.ts +38 -37
- package/src/activities/run-input.ts +25 -16
- package/src/activities/sandbox-images.ts +0 -1
- package/src/activities/sandbox-lease.ts +177 -44
- package/src/activities/scheduled-tasks.ts +118 -93
- package/src/activities/session-state.ts +83 -3
- package/src/activities/types.ts +18 -2
- package/src/activities/workflow-wake.ts +2 -17
- package/src/editable-artifact-materializer-service.ts +7 -3
- package/src/editable-artifact-outbox-service.ts +4 -4
- package/src/github-rest-mcp.ts +0 -1
- package/src/index.ts +2 -1
- package/src/observability-metrics.ts +105 -2
- package/src/personal-github-git-credentials.ts +0 -1
- package/src/pr-review-credentials.ts +0 -2
- package/src/retained-process-diagnostics.ts +50 -0
- package/src/sandbox-resume.ts +58 -73
- package/src/sandbox-routing.ts +44 -19
- package/src/sandbox-snapshot-diagnostics.ts +112 -0
- package/src/warm-capture-holder.ts +15 -0
- package/src/workflows/session.ts +64 -2
- package/dist/activities/agent-turn/knowledge-sources.d.ts +0 -20
- package/dist/activities/packs.d.ts +0 -55
- package/dist/activities-control-HMFGSKC5.js.map +0 -1
- package/dist/activities-turn-AP67JADS.js.map +0 -1
- package/dist/chunk-A4XQWVZK.js.map +0 -1
- package/dist/chunk-CYITU5UH.js.map +0 -1
- package/src/activities/agent-turn/knowledge-sources.ts +0 -86
- package/src/activities/packs.ts +0 -166
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
observabilityEventLogger
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-I7HKKMUJ.js";
|
|
4
4
|
|
|
5
5
|
// src/activity-services.ts
|
|
6
6
|
import { dbSearchPath, getSettings, resolveNatsControlPlaneAuth } from "@opengeni/config";
|
|
@@ -220,7 +220,7 @@ function exactPersonalGitHubDelegation(delegations, credentialBindingId) {
|
|
|
220
220
|
(delegation2) => delegation2.serverId === PERSONAL_GITHUB_SERVER_ID && delegation2.connectionType === "github_personal" && delegation2.personalGitHubRepositorySelection?.credentialBindingId === credentialBindingId
|
|
221
221
|
);
|
|
222
222
|
const delegation = matches[0];
|
|
223
|
-
if (matches.length !== 1 || !delegation || delegation.providerDomain !== "github.com" || delegation.kind !== "oauth2" || !delegation.originWorkspaceId || !delegation.
|
|
223
|
+
if (matches.length !== 1 || !delegation || delegation.providerDomain !== "github.com" || delegation.kind !== "oauth2" || !delegation.originWorkspaceId || !delegation.personalGitHubRepositorySelection) {
|
|
224
224
|
throw new Error("personal GitHub Git delegation is unavailable");
|
|
225
225
|
}
|
|
226
226
|
return delegation;
|
|
@@ -246,7 +246,6 @@ function exactRequestedRepositories(refs, credentialBindingId, snapshots) {
|
|
|
246
246
|
// src/pr-review-credentials.ts
|
|
247
247
|
import { environmentsEncryptionKeyBytes } from "@opengeni/config";
|
|
248
248
|
import { prReviewRegistrationIdFromCredentialBinding } from "@opengeni/core";
|
|
249
|
-
import { createNativeRemoteMcpCredentialsPort } from "@opengeni/core/remote-mcp-credentials";
|
|
250
249
|
import { decryptVariableSetValue, resolvePrReviewGitCredential } from "@opengeni/db";
|
|
251
250
|
import {
|
|
252
251
|
createGitHubAppInstallationTokenWithExpiry,
|
|
@@ -254,7 +253,6 @@ import {
|
|
|
254
253
|
} from "@opengeni/github";
|
|
255
254
|
function createStandaloneConnectionCredentialsPort(settings, db) {
|
|
256
255
|
return {
|
|
257
|
-
...createNativeRemoteMcpCredentialsPort(settings, db),
|
|
258
256
|
gitCredentials: async (request) => await resolveStandaloneGitCredentials(settings, db, request)
|
|
259
257
|
};
|
|
260
258
|
}
|
|
@@ -433,6 +431,7 @@ function createSharedActivityServices(dependencies) {
|
|
|
433
431
|
|
|
434
432
|
// src/activities/codex-capacity.ts
|
|
435
433
|
import {
|
|
434
|
+
connectionModelAllowed as connectionModelAllowed2,
|
|
436
435
|
armCodexCapacityWait,
|
|
437
436
|
fetchCodexUsageForAccount,
|
|
438
437
|
getCodexCapacityWaitForSession,
|
|
@@ -571,8 +570,9 @@ async function refreshExhaustedXaiQuota(input) {
|
|
|
571
570
|
}
|
|
572
571
|
|
|
573
572
|
// src/activities/codex-rotation.ts
|
|
574
|
-
|
|
575
|
-
|
|
573
|
+
import { connectionModelAllowed } from "@opengeni/db";
|
|
574
|
+
function codexAccountNeedsLiveCapacityRefresh(account, _now) {
|
|
575
|
+
return (account.primaryUsedPercent ?? 0) >= CODEX_USAGE_EXHAUSTED_PCT || (account.secondaryUsedPercent ?? 0) >= CODEX_USAGE_EXHAUSTED_PCT || account.exhaustedKind === "quota" && account.exhaustedUntil !== null;
|
|
576
576
|
}
|
|
577
577
|
function effectiveRotationStrategy(_stored) {
|
|
578
578
|
return "sharded";
|
|
@@ -761,7 +761,13 @@ function chooseRotationActive(args) {
|
|
|
761
761
|
return decide(chosen);
|
|
762
762
|
}
|
|
763
763
|
function selectCodexCredentialLeaseForTurn(args) {
|
|
764
|
-
const {
|
|
764
|
+
const { activeCredentialId, rotationEnabled, rotationStrategy, existingCredentialId } = args.context;
|
|
765
|
+
if (args.context.failoverExhausted) {
|
|
766
|
+
return { credentialId: null, decision: { kind: "none" }, advanceActivePointer: false };
|
|
767
|
+
}
|
|
768
|
+
const accounts = args.context.modelId ? args.context.accounts.filter(
|
|
769
|
+
(account) => connectionModelAllowed(account.allowedModelIds, args.context.modelId)
|
|
770
|
+
) : args.context.accounts;
|
|
765
771
|
const failedCredentialIds = new Set(args.context.failedCredentialIds ?? []);
|
|
766
772
|
const strategy = effectiveRotationStrategy(rotationStrategy);
|
|
767
773
|
const existing = existingCredentialId ? accounts.find((account) => account.id === existingCredentialId) : void 0;
|
|
@@ -787,6 +793,9 @@ function selectCodexCredentialLeaseForTurn(args) {
|
|
|
787
793
|
if (!pinned) {
|
|
788
794
|
return { credentialId: null, decision: { kind: "none" }, advanceActivePointer: false };
|
|
789
795
|
}
|
|
796
|
+
if (failedCredentialIds.has(pinned.id)) {
|
|
797
|
+
return { credentialId: null, decision: { kind: "none" }, advanceActivePointer: false };
|
|
798
|
+
}
|
|
790
799
|
if (!pinned.allocatorEnabled) {
|
|
791
800
|
return {
|
|
792
801
|
credentialId: null,
|
|
@@ -843,6 +852,9 @@ function selectCodexCredentialLeaseForTurn(args) {
|
|
|
843
852
|
if (!active) {
|
|
844
853
|
return { credentialId: null, decision: { kind: "none" }, advanceActivePointer: false };
|
|
845
854
|
}
|
|
855
|
+
if (failedCredentialIds.has(active.id)) {
|
|
856
|
+
return { credentialId: null, decision: { kind: "none" }, advanceActivePointer: false };
|
|
857
|
+
}
|
|
846
858
|
if (!active.allocatorEnabled) {
|
|
847
859
|
return {
|
|
848
860
|
credentialId: null,
|
|
@@ -910,8 +922,13 @@ async function signalPendingCodexCapacityWakeTargets(services, workspaceId) {
|
|
|
910
922
|
);
|
|
911
923
|
await signalCodexCapacityWakeTargets(services, targets);
|
|
912
924
|
}
|
|
913
|
-
function codexCapacityDecision(context) {
|
|
914
|
-
|
|
925
|
+
function codexCapacityDecision(context, now = /* @__PURE__ */ new Date()) {
|
|
926
|
+
context = {
|
|
927
|
+
...context,
|
|
928
|
+
accounts: context.accounts.filter(
|
|
929
|
+
(account) => !context.modelId || connectionModelAllowed2(account.allowedModelIds, context.modelId)
|
|
930
|
+
)
|
|
931
|
+
};
|
|
915
932
|
const selected = selectCodexCredentialLeaseForTurn({
|
|
916
933
|
context,
|
|
917
934
|
sessionId: context.sessionId,
|
|
@@ -928,7 +945,9 @@ function codexCapacityDecision(context) {
|
|
|
928
945
|
credentialId: selected.credentialId,
|
|
929
946
|
diagnostic: {
|
|
930
947
|
connectedCount: context.accounts.length,
|
|
931
|
-
eligibleCount: context.accounts.filter(
|
|
948
|
+
eligibleCount: context.accounts.filter(
|
|
949
|
+
(account) => (account.id === selected.credentialId || !context.failedCredentialIds?.includes(account.id)) && isCodexCredentialEligible(account, now)
|
|
950
|
+
).length
|
|
932
951
|
}
|
|
933
952
|
};
|
|
934
953
|
}
|
|
@@ -936,7 +955,7 @@ function codexCapacityDecision(context) {
|
|
|
936
955
|
const capacityAccounts = policyCredentialId ? context.accounts.filter((account) => account.id === policyCredentialId) : context.accounts;
|
|
937
956
|
const authoritativeReset = authoritativeCodexCapacityResetAt(capacityAccounts, now);
|
|
938
957
|
const hasReconcilableQuotaCooldown = capacityAccounts.some(
|
|
939
|
-
(account) => account.status === "active" && account.allocatorEnabled && account.exhaustedKind === "quota" && account.exhaustedUntil !== null
|
|
958
|
+
(account) => account.status === "active" && account.allocatorEnabled && account.exhaustedKind === "quota" && account.exhaustedUntil !== null
|
|
940
959
|
);
|
|
941
960
|
const policyAccount = capacityAccounts[0] ?? null;
|
|
942
961
|
const mutationOnlyStatusBlock = policyAccount != null && (!policyAccount.allocatorEnabled || policyAccount.status !== "active") || authoritativeReset === null && capacityAccounts.length > 0 && capacityAccounts.every(
|
|
@@ -946,7 +965,7 @@ function codexCapacityDecision(context) {
|
|
|
946
965
|
return {
|
|
947
966
|
kind: "unavailable",
|
|
948
967
|
earliestResetAt: authoritativeReset,
|
|
949
|
-
resetKind: selected.decision.kind === "none" || selected.decision.kind === "allocatorDisabled" || mutationOnlyStatusBlock ? "mutation_only" : authoritativeReset && !hasReconcilableQuotaCooldown ? "authoritative" : "bounded_refresh",
|
|
968
|
+
resetKind: selected.decision.kind === "none" && !hasReconcilableQuotaCooldown && !authoritativeReset || selected.decision.kind === "allocatorDisabled" || mutationOnlyStatusBlock ? "mutation_only" : authoritativeReset && !hasReconcilableQuotaCooldown ? "authoritative" : "bounded_refresh",
|
|
950
969
|
diagnostic: {
|
|
951
970
|
connectedCount: context.accounts.length,
|
|
952
971
|
allocatorEnabledCount: context.accounts.filter((account) => account.allocatorEnabled).length,
|
|
@@ -957,6 +976,16 @@ function codexCapacityDecision(context) {
|
|
|
957
976
|
}
|
|
958
977
|
async function armAndReconcileCodexCapacityWait(services, input, options = {}) {
|
|
959
978
|
const armed = await armCodexCapacityWait(services.db, input);
|
|
979
|
+
if (armed.action === "stopped") {
|
|
980
|
+
options.onArmed?.();
|
|
981
|
+
await publishDurableSessionEvents(
|
|
982
|
+
services.bus,
|
|
983
|
+
input.workspaceId,
|
|
984
|
+
input.sessionId,
|
|
985
|
+
armed.events
|
|
986
|
+
);
|
|
987
|
+
return armed;
|
|
988
|
+
}
|
|
960
989
|
if (armed.action !== "waiting") return armed;
|
|
961
990
|
options.onArmed?.();
|
|
962
991
|
await publishDurableSessionEvents(services.bus, input.workspaceId, input.sessionId, armed.events);
|
|
@@ -980,15 +1009,22 @@ async function armAndReconcileCodexCapacityWait(services, input, options = {}) {
|
|
|
980
1009
|
);
|
|
981
1010
|
return evaluated;
|
|
982
1011
|
}
|
|
983
|
-
async function refreshCapacityMetadata(services, workspaceId) {
|
|
984
|
-
const accounts = await listCodexAccountStatuses(services.db, workspaceId).catch(() => []);
|
|
1012
|
+
async function refreshCapacityMetadata(services, workspaceId, turnId) {
|
|
1013
|
+
const accounts = await listCodexAccountStatuses(services.db, workspaceId, turnId).catch(() => []);
|
|
985
1014
|
const now = /* @__PURE__ */ new Date();
|
|
986
1015
|
const stale = accounts.filter(
|
|
987
1016
|
(account) => account.allocatorEnabled && account.status === "active" && (codexAccountNeedsLiveCapacityRefresh(account, now) || account.usageCheckedAt === null)
|
|
988
1017
|
);
|
|
989
1018
|
await refreshCodexUsageAndRepairCapacityWaiters(
|
|
990
1019
|
stale.map(
|
|
991
|
-
(account) => () => fetchCodexUsageForAccount(
|
|
1020
|
+
(account) => () => fetchCodexUsageForAccount(
|
|
1021
|
+
services.db,
|
|
1022
|
+
services.settings,
|
|
1023
|
+
workspaceId,
|
|
1024
|
+
account.id,
|
|
1025
|
+
void 0,
|
|
1026
|
+
turnId
|
|
1027
|
+
)
|
|
992
1028
|
),
|
|
993
1029
|
() => signalPendingCodexCapacityWakeTargets(services, workspaceId)
|
|
994
1030
|
);
|
|
@@ -1078,7 +1114,7 @@ function createCodexCapacityActivities(services) {
|
|
|
1078
1114
|
}
|
|
1079
1115
|
const boundedRefreshAttempted = current.resetKind === "bounded_refresh" && input.cause === "timer" && current.nextCheckAt.getTime() <= Date.now();
|
|
1080
1116
|
if (boundedRefreshAttempted) {
|
|
1081
|
-
await refreshCapacityMetadata(resolved, input.workspaceId);
|
|
1117
|
+
await refreshCapacityMetadata(resolved, input.workspaceId, current.blockedTurnId);
|
|
1082
1118
|
}
|
|
1083
1119
|
const result = await reconcileCodexCapacityWaitDb(
|
|
1084
1120
|
resolved.db,
|
|
@@ -1427,6 +1463,7 @@ function goalContinuationPrompt(_goal, _autoContinuation, _cap, options = {}) {
|
|
|
1427
1463
|
"- For every explicit requirement, named artifact, command, test, gate, invariant, and deliverable, identify and inspect the authoritative evidence that would prove it.",
|
|
1428
1464
|
"- Match verification scope to requirement scope. Treat uncertain, indirect, incomplete, or missing evidence as not achieved and continue working.",
|
|
1429
1465
|
"- The audit must prove completion, not merely fail to find obvious remaining work.",
|
|
1466
|
+
"- For user-facing report deliverables, including reports produced during another task, follow the Documents Skill: create the durable native document first, inspect its relevant final head after the last edit, and provide the returned artifact reference. Declare report requirements through the available goal tools before authoring and satisfy every persisted report requirement with verified artifact delivery evidence before completion. Sandbox paths and raw file IDs do not prove report delivery. If artifact tooling or access is unavailable, keep that deliverable incomplete and state the blocker; never invent proof or silently substitute a local report. Ordinary chat answers, short progress updates, source-code links, and explicitly requested local-file work remain outside this report contract.",
|
|
1430
1467
|
"",
|
|
1431
1468
|
"Do not rely on intent, partial progress, memory of earlier work, or a plausible final answer as proof of completion. Call opengeni__goal_complete with concrete evidence only when the full objective is actually achieved and no required work remains.",
|
|
1432
1469
|
"",
|
|
@@ -4583,65 +4620,10 @@ var SyncFailure = class extends Error {
|
|
|
4583
4620
|
import {
|
|
4584
4621
|
resolveRigProviderImageSelection,
|
|
4585
4622
|
rigProviderImageSourceImage,
|
|
4586
|
-
settingsWithPackSandboxImage,
|
|
4587
4623
|
settingsWithRigImage,
|
|
4588
4624
|
settingsWithRigProviderImage
|
|
4589
4625
|
} from "@opengeni/core";
|
|
4590
4626
|
|
|
4591
|
-
// src/activities/packs.ts
|
|
4592
|
-
import { getWorkspace, listInstalledPortableSkills } from "@opengeni/db";
|
|
4593
|
-
import {
|
|
4594
|
-
legacySandboxRuntimeFromPacks,
|
|
4595
|
-
packInstallationUsesLegacyRuntime,
|
|
4596
|
-
resolveWorkspaceLegacyRuntimePacks
|
|
4597
|
-
} from "@opengeni/core";
|
|
4598
|
-
import {
|
|
4599
|
-
buildPortableSkillArtifact
|
|
4600
|
-
} from "@opengeni/runtime";
|
|
4601
|
-
var emptyPackRuntime = {
|
|
4602
|
-
sandboxImage: null,
|
|
4603
|
-
sandboxProviderImages: null,
|
|
4604
|
-
skillActivations: []
|
|
4605
|
-
};
|
|
4606
|
-
async function resolveWorkspacePackRuntime(db, workspaceId) {
|
|
4607
|
-
const packs = await resolveWorkspaceLegacyRuntimePacks(db, workspaceId);
|
|
4608
|
-
if (packs.length === 0) return emptyPackRuntime;
|
|
4609
|
-
return workspacePackRuntimeFromPacks(packs);
|
|
4610
|
-
}
|
|
4611
|
-
function workspacePackRuntimeFromPacks(packs) {
|
|
4612
|
-
const sandboxRuntime = legacySandboxRuntimeFromPacks(packs);
|
|
4613
|
-
const skillActivations = [];
|
|
4614
|
-
const skillOwners = /* @__PURE__ */ new Map();
|
|
4615
|
-
for (const pack of [...packs].sort((a, b) => a.id.localeCompare(b.id))) {
|
|
4616
|
-
for (const skill of pack.skills) {
|
|
4617
|
-
const key = skill.name.toLowerCase();
|
|
4618
|
-
const existingOwner = skillOwners.get(key);
|
|
4619
|
-
if (existingOwner !== void 0 && existingOwner !== pack.id) {
|
|
4620
|
-
throw new Error(
|
|
4621
|
-
`Enabled packs ${existingOwner} and ${pack.id} both declare a skill named "${skill.name}". Pack skill names must be unique across enabled packs; disable one of the packs and retry.`
|
|
4622
|
-
);
|
|
4623
|
-
}
|
|
4624
|
-
skillOwners.set(key, pack.id);
|
|
4625
|
-
const artifact = {
|
|
4626
|
-
name: skill.name,
|
|
4627
|
-
description: skill.description ?? null,
|
|
4628
|
-
files: skill.files.map((file) => ({ path: file.path, content: file.content }))
|
|
4629
|
-
};
|
|
4630
|
-
skillActivations.push({
|
|
4631
|
-
source: "pack",
|
|
4632
|
-
id: `pack:${pack.id}:${skill.name}`,
|
|
4633
|
-
artifact,
|
|
4634
|
-
reason: `active legacy Pack ${pack.id}`
|
|
4635
|
-
});
|
|
4636
|
-
}
|
|
4637
|
-
}
|
|
4638
|
-
return {
|
|
4639
|
-
sandboxImage: sandboxRuntime.sandboxImage,
|
|
4640
|
-
sandboxProviderImages: sandboxRuntime.sandboxProviderImages,
|
|
4641
|
-
skillActivations
|
|
4642
|
-
};
|
|
4643
|
-
}
|
|
4644
|
-
|
|
4645
4627
|
// src/activities/streaming.ts
|
|
4646
4628
|
import { TURN_ACTIVITY_CANCELLATION_HEARTBEAT_INTERVAL_MS } from "@opengeni/core";
|
|
4647
4629
|
import { Context } from "@temporalio/activity";
|
|
@@ -4816,6 +4798,73 @@ async function nextStreamEvent(iterator, context) {
|
|
|
4816
4798
|
});
|
|
4817
4799
|
}
|
|
4818
4800
|
|
|
4801
|
+
// src/sandbox-snapshot-diagnostics.ts
|
|
4802
|
+
import { sandboxLeaseTelemetryKey } from "@opengeni/observability";
|
|
4803
|
+
function safeSnapshotError(error, origin = "sandbox-resume") {
|
|
4804
|
+
const fields = {
|
|
4805
|
+
errorClass: "SnapshotOperationError",
|
|
4806
|
+
errorCode: "snapshot_operation_failed",
|
|
4807
|
+
origin
|
|
4808
|
+
};
|
|
4809
|
+
try {
|
|
4810
|
+
if (error && typeof error === "object") {
|
|
4811
|
+
const candidate = error;
|
|
4812
|
+
if (typeof candidate.name === "string" && /^[A-Z][A-Za-z0-9]{2,62}Error$/u.test(candidate.name)) {
|
|
4813
|
+
fields.causeName = candidate.name;
|
|
4814
|
+
}
|
|
4815
|
+
if (typeof candidate.code === "string" && /^[a-z0-9_]{1,64}$/u.test(candidate.code)) {
|
|
4816
|
+
fields.integrityCode = candidate.code;
|
|
4817
|
+
}
|
|
4818
|
+
const status = Number(candidate.status ?? candidate.statusCode);
|
|
4819
|
+
if (Number.isInteger(status) && status >= 100 && status <= 599) fields.status = status;
|
|
4820
|
+
}
|
|
4821
|
+
} catch {
|
|
4822
|
+
}
|
|
4823
|
+
const read = (value, key) => {
|
|
4824
|
+
try {
|
|
4825
|
+
return value && typeof value === "object" ? Reflect.get(value, key) : void 0;
|
|
4826
|
+
} catch {
|
|
4827
|
+
return void 0;
|
|
4828
|
+
}
|
|
4829
|
+
};
|
|
4830
|
+
const details = read(error, "details");
|
|
4831
|
+
const providerName = read(details, "errorName");
|
|
4832
|
+
if (typeof providerName === "string" && [
|
|
4833
|
+
"ClientError",
|
|
4834
|
+
"TimeoutError",
|
|
4835
|
+
"ConnectionError",
|
|
4836
|
+
"AuthError",
|
|
4837
|
+
"NotFoundError",
|
|
4838
|
+
"InvalidError",
|
|
4839
|
+
"RemoteError",
|
|
4840
|
+
"AbortError"
|
|
4841
|
+
].includes(providerName))
|
|
4842
|
+
fields.providerErrorName = providerName;
|
|
4843
|
+
const grpcCode = read(details, "errorCode");
|
|
4844
|
+
if (providerName === "ClientError" && typeof grpcCode === "number" && Number.isInteger(grpcCode) && grpcCode >= 0 && grpcCode <= 16)
|
|
4845
|
+
fields.providerGrpcCode = grpcCode;
|
|
4846
|
+
for (const key of ["status", "httpStatus", "responseStatus"]) {
|
|
4847
|
+
const status = read(details, key);
|
|
4848
|
+
if (typeof status === "number" && Number.isInteger(status) && status >= 100 && status <= 599) {
|
|
4849
|
+
fields.providerHttpStatus = status;
|
|
4850
|
+
break;
|
|
4851
|
+
}
|
|
4852
|
+
}
|
|
4853
|
+
const retryable = read(error, "retryable");
|
|
4854
|
+
if (typeof retryable === "boolean") fields.providerRetryable = retryable;
|
|
4855
|
+
return fields;
|
|
4856
|
+
}
|
|
4857
|
+
function warnDrainSnapshotFailure(observability, message, error, lease) {
|
|
4858
|
+
try {
|
|
4859
|
+
observability.warn(message, {
|
|
4860
|
+
...safeSnapshotError(error, "worker-lifecycle"),
|
|
4861
|
+
...lease.workspaceId ? { sandboxLeaseKey: sandboxLeaseTelemetryKey(lease.workspaceId, lease.sandboxGroupId) } : {},
|
|
4862
|
+
leaseEpoch: lease.leaseEpoch
|
|
4863
|
+
});
|
|
4864
|
+
} catch {
|
|
4865
|
+
}
|
|
4866
|
+
}
|
|
4867
|
+
|
|
4819
4868
|
// src/sandbox-archive-storage.ts
|
|
4820
4869
|
import { uploadWorkspaceArchiveSpool } from "@opengeni/storage";
|
|
4821
4870
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
@@ -4952,12 +5001,13 @@ async function deleteUnpublishedWorkspaceArchiveObject(objectStorage, ref, metri
|
|
|
4952
5001
|
import { sandboxLifecycleTransitionWaitMs as sandboxLifecycleTransitionWaitMs2 } from "@opengeni/config";
|
|
4953
5002
|
import {
|
|
4954
5003
|
createProviderCommandRetainer,
|
|
4955
|
-
|
|
5004
|
+
supervisedCommandProtocolReady
|
|
4956
5005
|
} from "@opengeni/db/retained-provider-commands";
|
|
4957
5006
|
import {
|
|
4958
5007
|
adoptConnectedMachineSessionBackgroundCommand,
|
|
4959
5008
|
adoptManagedSessionBackgroundCommand,
|
|
4960
5009
|
advanceWorkspaceGenerationForRetainedProcess,
|
|
5010
|
+
retainedProviderCommandPersistence,
|
|
4961
5011
|
advanceWorkspaceGeneration,
|
|
4962
5012
|
getRetainedProcess,
|
|
4963
5013
|
retainWorkspaceMutationProcess,
|
|
@@ -5002,6 +5052,15 @@ import {
|
|
|
5002
5052
|
sandboxLifecycleTransitionWaitMs
|
|
5003
5053
|
} from "@opengeni/config";
|
|
5004
5054
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
5055
|
+
|
|
5056
|
+
// src/warm-capture-holder.ts
|
|
5057
|
+
function retainsHolderForWarmCapture(lease, expectedEpoch, now = Date.now()) {
|
|
5058
|
+
return Boolean(
|
|
5059
|
+
lease?.liveness === "warm" && lease.leaseEpoch === expectedEpoch && lease.archiveCapture && lease.archiveCapture.deadlineAt.getTime() > now
|
|
5060
|
+
);
|
|
5061
|
+
}
|
|
5062
|
+
|
|
5063
|
+
// src/sandbox-resume.ts
|
|
5005
5064
|
import {
|
|
5006
5065
|
acquireLease,
|
|
5007
5066
|
adoptLegacyModalCheckpointArtifact,
|
|
@@ -5054,6 +5113,7 @@ import {
|
|
|
5054
5113
|
downloadWorkspaceArchiveSpool,
|
|
5055
5114
|
WorkspaceArchiveStorageError
|
|
5056
5115
|
} from "@opengeni/storage";
|
|
5116
|
+
import { sandboxLeaseTelemetryKey as sandboxLeaseTelemetryKey2 } from "@opengeni/observability";
|
|
5057
5117
|
import { parseWorkspaceArchiveObjectRef as parseWorkspaceArchiveObjectRef2 } from "@opengeni/contracts";
|
|
5058
5118
|
function sandboxLeaseHolderIdForAttempt(attemptId) {
|
|
5059
5119
|
const normalized = attemptId.trim();
|
|
@@ -5160,29 +5220,6 @@ var SnapshotTimeoutError = class extends Error {
|
|
|
5160
5220
|
this.name = "SnapshotTimeoutError";
|
|
5161
5221
|
}
|
|
5162
5222
|
};
|
|
5163
|
-
function safeSnapshotError(error) {
|
|
5164
|
-
const fields = {
|
|
5165
|
-
errorClass: "SnapshotOperationError",
|
|
5166
|
-
errorCode: "snapshot_operation_failed",
|
|
5167
|
-
origin: "sandbox-resume"
|
|
5168
|
-
};
|
|
5169
|
-
try {
|
|
5170
|
-
if (error && typeof error === "object") {
|
|
5171
|
-
const candidate = error;
|
|
5172
|
-
if (typeof candidate.name === "string" && /^[A-Z][A-Za-z0-9]{2,62}Error$/u.test(candidate.name)) {
|
|
5173
|
-
fields.causeName = candidate.name;
|
|
5174
|
-
}
|
|
5175
|
-
if (typeof candidate.code === "string" && /^[a-z0-9_]{1,64}$/u.test(candidate.code)) {
|
|
5176
|
-
fields.integrityCode = candidate.code;
|
|
5177
|
-
}
|
|
5178
|
-
const rawStatus = candidate.status ?? candidate.statusCode;
|
|
5179
|
-
const status = Number(rawStatus);
|
|
5180
|
-
if (Number.isInteger(status) && status >= 100 && status <= 599) fields.status = status;
|
|
5181
|
-
}
|
|
5182
|
-
} catch {
|
|
5183
|
-
}
|
|
5184
|
-
return fields;
|
|
5185
|
-
}
|
|
5186
5223
|
async function waitForWarmSnapshot(snapshot, timeoutMs, signal) {
|
|
5187
5224
|
if (signal?.aborted) return false;
|
|
5188
5225
|
let timeout;
|
|
@@ -5361,6 +5398,18 @@ function maybePersistWarmWorkspaceSnapshot(services, ids, session, leaseEpoch, s
|
|
|
5361
5398
|
}
|
|
5362
5399
|
async function persistWarmWorkspaceSnapshot(services, ids, session, leaseEpoch, signal, force, registerOwnedContinuation) {
|
|
5363
5400
|
const { db, settings } = services;
|
|
5401
|
+
const warnSnapshotFailure = (message, error) => {
|
|
5402
|
+
const fields = {
|
|
5403
|
+
...safeSnapshotError(error),
|
|
5404
|
+
sandboxLeaseKey: sandboxLeaseTelemetryKey2(ids.workspaceId, ids.sandboxGroupId),
|
|
5405
|
+
leaseEpoch
|
|
5406
|
+
};
|
|
5407
|
+
try {
|
|
5408
|
+
if (services.observability) services.observability.warn(message, fields);
|
|
5409
|
+
else console.warn(message, fields);
|
|
5410
|
+
} catch {
|
|
5411
|
+
}
|
|
5412
|
+
};
|
|
5364
5413
|
const intervalMs = settings.sandboxSnapshotIntervalMs;
|
|
5365
5414
|
if (intervalMs <= 0 && !force) {
|
|
5366
5415
|
return false;
|
|
@@ -5434,6 +5483,7 @@ async function persistWarmWorkspaceSnapshot(services, ids, session, leaseEpoch,
|
|
|
5434
5483
|
} : {}
|
|
5435
5484
|
});
|
|
5436
5485
|
if (claimed.status !== "claimed") {
|
|
5486
|
+
if (claimed.status === "throttled") return false;
|
|
5437
5487
|
console.error("mid-session workspace snapshot skipped (capture claim)", {
|
|
5438
5488
|
sandboxGroupId: ids.sandboxGroupId,
|
|
5439
5489
|
status: claimed.status
|
|
@@ -5472,6 +5522,8 @@ async function persistWarmWorkspaceSnapshot(services, ids, session, leaseEpoch,
|
|
|
5472
5522
|
}).catch(() => void 0);
|
|
5473
5523
|
};
|
|
5474
5524
|
const captureAndPublish = (async () => {
|
|
5525
|
+
const captureStarted = performance.now();
|
|
5526
|
+
let captureOutcome = "failed";
|
|
5475
5527
|
let archive;
|
|
5476
5528
|
let candidate = null;
|
|
5477
5529
|
let publicationAttempted = false;
|
|
@@ -5521,6 +5573,7 @@ async function persistWarmWorkspaceSnapshot(services, ids, session, leaseEpoch,
|
|
|
5521
5573
|
if (!wrote && candidate) {
|
|
5522
5574
|
await abandonCandidate(candidate.id, "snapshot_publication_fenced");
|
|
5523
5575
|
}
|
|
5576
|
+
if (wrote) captureOutcome = "completed";
|
|
5524
5577
|
return wrote;
|
|
5525
5578
|
} catch (error) {
|
|
5526
5579
|
if (candidate && !publicationAttempted)
|
|
@@ -5538,20 +5591,23 @@ async function persistWarmWorkspaceSnapshot(services, ids, session, leaseEpoch,
|
|
|
5538
5591
|
expectedEpoch: leaseEpoch,
|
|
5539
5592
|
expectedInstanceId: instanceId
|
|
5540
5593
|
}).catch((error) => {
|
|
5541
|
-
|
|
5542
|
-
|
|
5543
|
-
safeSnapshotError(error)
|
|
5544
|
-
);
|
|
5594
|
+
captureOutcome = "failed";
|
|
5595
|
+
warnSnapshotFailure("mid-session workspace capture gate release failed", error);
|
|
5545
5596
|
});
|
|
5597
|
+
try {
|
|
5598
|
+
services.sandboxMetrics?.onWorkspaceCapture?.({
|
|
5599
|
+
backend: lease.backend,
|
|
5600
|
+
outcome: captureOutcome,
|
|
5601
|
+
durationSeconds: Math.max(0, performance.now() - captureStarted) / 1e3
|
|
5602
|
+
});
|
|
5603
|
+
} catch {
|
|
5604
|
+
}
|
|
5546
5605
|
}
|
|
5547
5606
|
})();
|
|
5548
5607
|
const settled = captureAndPublish.then(
|
|
5549
5608
|
(persisted) => ({ kind: "settled", persisted }),
|
|
5550
5609
|
(error) => {
|
|
5551
|
-
|
|
5552
|
-
"mid-session workspace snapshot failed (turn unaffected)",
|
|
5553
|
-
safeSnapshotError(error)
|
|
5554
|
-
);
|
|
5610
|
+
warnSnapshotFailure("mid-session workspace snapshot failed (turn unaffected)", error);
|
|
5555
5611
|
return { kind: "settled", persisted: false };
|
|
5556
5612
|
}
|
|
5557
5613
|
);
|
|
@@ -5578,10 +5634,7 @@ async function persistWarmWorkspaceSnapshot(services, ids, session, leaseEpoch,
|
|
|
5578
5634
|
});
|
|
5579
5635
|
return outcome.kind === "settled" ? outcome.persisted : false;
|
|
5580
5636
|
} catch (error) {
|
|
5581
|
-
|
|
5582
|
-
"mid-session workspace snapshot failed (turn unaffected)",
|
|
5583
|
-
safeSnapshotError(error)
|
|
5584
|
-
);
|
|
5637
|
+
warnSnapshotFailure("mid-session workspace snapshot failed (turn unaffected)", error);
|
|
5585
5638
|
return false;
|
|
5586
5639
|
}
|
|
5587
5640
|
}
|
|
@@ -5714,7 +5767,12 @@ async function resumeBoxForTurn(services, ids, kind, holderId) {
|
|
|
5714
5767
|
});
|
|
5715
5768
|
await providerRenewalInFlight;
|
|
5716
5769
|
};
|
|
5717
|
-
const releaseDeadHolder = (reason) => {
|
|
5770
|
+
const releaseDeadHolder = async (reason) => {
|
|
5771
|
+
if (reason === "holder_gone" && kind === "turn" && holderLeaseHeartbeat) {
|
|
5772
|
+
const expectedEpoch = holderLeaseHeartbeat.expectedEpoch;
|
|
5773
|
+
const lease = await readLease(db, ids.workspaceId, ids.sandboxGroupId);
|
|
5774
|
+
if (retainsHolderForWarmCapture(lease, expectedEpoch)) return;
|
|
5775
|
+
}
|
|
5718
5776
|
const message = "sandbox resume holder released: holder no longer live";
|
|
5719
5777
|
const fields = {
|
|
5720
5778
|
workspaceId: ids.workspaceId,
|
|
@@ -5738,14 +5796,14 @@ async function resumeBoxForTurn(services, ids, kind, holderId) {
|
|
|
5738
5796
|
holderId,
|
|
5739
5797
|
expectedEpoch: heartbeat2.expectedEpoch,
|
|
5740
5798
|
leaseTtlMs: heartbeat2.leaseTtlMs
|
|
5741
|
-
}).then((status) => {
|
|
5799
|
+
}).then(async (status) => {
|
|
5742
5800
|
if (heartbeat2 !== holderLeaseHeartbeat) return;
|
|
5743
5801
|
if (!status.holderAlive) {
|
|
5744
|
-
releaseDeadHolder(status.fence);
|
|
5802
|
+
await releaseDeadHolder(status.fence);
|
|
5745
5803
|
return;
|
|
5746
5804
|
}
|
|
5747
5805
|
if (status.fence === "epoch") {
|
|
5748
|
-
releaseDeadHolder(status.fence);
|
|
5806
|
+
await releaseDeadHolder(status.fence);
|
|
5749
5807
|
return;
|
|
5750
5808
|
}
|
|
5751
5809
|
if (status.leaseExtended || status.fence === "rotation_requested") {
|
|
@@ -5760,10 +5818,10 @@ async function resumeBoxForTurn(services, ids, kind, holderId) {
|
|
|
5760
5818
|
sandboxGroupId: ids.sandboxGroupId,
|
|
5761
5819
|
kind,
|
|
5762
5820
|
holderId
|
|
5763
|
-
}).then((touched) => {
|
|
5821
|
+
}).then(async (touched) => {
|
|
5764
5822
|
if (heartbeat2 !== holderLeaseHeartbeat) return;
|
|
5765
5823
|
if (!touched) {
|
|
5766
|
-
releaseDeadHolder("holder_gone");
|
|
5824
|
+
await releaseDeadHolder("holder_gone");
|
|
5767
5825
|
return;
|
|
5768
5826
|
}
|
|
5769
5827
|
void maybeRenewProviderExpiration().catch(() => void 0);
|
|
@@ -5809,7 +5867,7 @@ async function resumeBoxForTurn(services, ids, kind, holderId) {
|
|
|
5809
5867
|
let spawnEnvelope = fallbackArchiveEnvelope ?? acquired.lease.resumeState ?? envelope;
|
|
5810
5868
|
const archiveSource = acquired.lease.recovery.archive.status === "none" ? fallbackArchiveEnvelope : acquired.lease.resumeState;
|
|
5811
5869
|
const continuityRecovery = acquired.lease.recovery.continuity;
|
|
5812
|
-
if (acquired.lease.recovery.archive.status === "available" && acquired.lease.archiveComplete || acquired.lease.recovery.archive.status === "none" && workspaceArchiveFieldsFromEnvelope(archiveSource) !== null) {
|
|
5870
|
+
if (acquired.lease.recovery.archive.status === "available" && (acquired.lease.archiveComplete || acquired.lease.historicalRecoveryAuthorized === true) || acquired.lease.recovery.archive.status === "none" && workspaceArchiveFieldsFromEnvelope(archiveSource) !== null) {
|
|
5813
5871
|
const rematerializationId = crypto.randomUUID();
|
|
5814
5872
|
const legacyNativeArchive = legacyNativeArchiveFromEnvelope(archiveSource);
|
|
5815
5873
|
const begun = await beginSandboxRematerialization(db, {
|
|
@@ -6159,7 +6217,8 @@ async function resumeBoxForTurn(services, ids, kind, holderId) {
|
|
|
6159
6217
|
workspaceId: ids.workspaceId,
|
|
6160
6218
|
sandboxGroupId: ids.sandboxGroupId,
|
|
6161
6219
|
expectedEpoch: leaseEpoch,
|
|
6162
|
-
expectedInstanceId: live.instanceId
|
|
6220
|
+
expectedInstanceId: live.instanceId,
|
|
6221
|
+
expectedBackend: ids.backend
|
|
6163
6222
|
});
|
|
6164
6223
|
if (marked.status === "marked") {
|
|
6165
6224
|
await services.onSandboxLost?.({
|
|
@@ -6289,7 +6348,7 @@ async function resolveCurrentHomeBackend(services, ids, established) {
|
|
|
6289
6348
|
throw homeRouteRecoveryError(lease, fallbackEpoch);
|
|
6290
6349
|
}
|
|
6291
6350
|
if (lease.instanceId === established.instanceId) {
|
|
6292
|
-
services.onHomeSandboxRebound?.({
|
|
6351
|
+
await services.onHomeSandboxRebound?.({
|
|
6293
6352
|
established,
|
|
6294
6353
|
leaseEpoch: lease.leaseEpoch
|
|
6295
6354
|
});
|
|
@@ -6329,6 +6388,7 @@ async function resolveCurrentHomeBackend(services, ids, established) {
|
|
|
6329
6388
|
sandboxGroupId: ids.sandboxGroupId,
|
|
6330
6389
|
expectedEpoch: lease.leaseEpoch,
|
|
6331
6390
|
expectedInstanceId: lease.instanceId,
|
|
6391
|
+
expectedBackend: lease.backend,
|
|
6332
6392
|
diagnostic: "provider_not_found_during_home_route_rebind"
|
|
6333
6393
|
});
|
|
6334
6394
|
if (marked.status === "marked") {
|
|
@@ -6348,7 +6408,7 @@ async function resolveCurrentHomeBackend(services, ids, established) {
|
|
|
6348
6408
|
if (rebound.instanceId !== lease.instanceId || reboundBackend !== resumeBackend) {
|
|
6349
6409
|
throw homeRouteRecoveryError(lease, lease.leaseEpoch);
|
|
6350
6410
|
}
|
|
6351
|
-
services.onHomeSandboxRebound?.({
|
|
6411
|
+
await services.onHomeSandboxRebound?.({
|
|
6352
6412
|
established: rebound,
|
|
6353
6413
|
leaseEpoch: lease.leaseEpoch
|
|
6354
6414
|
});
|
|
@@ -6553,7 +6613,7 @@ function settleRetainedProcessForTurn(services, ids) {
|
|
|
6553
6613
|
sessionId: ids.sessionId,
|
|
6554
6614
|
processId: process2.id
|
|
6555
6615
|
});
|
|
6556
|
-
if (!durable || durable.providerSessionId !== process2.providerSessionId || durable.providerBackend !== backend.kind || durable.providerInstanceId !== backend.providerInstanceId || durable.leaseEpoch !== backend.leaseEpoch || durable.routeKind !== (backend.sandboxId === null ? "home" : "active") || durable.routeTargetId !== backend.sandboxId || durable.routeEpoch !== backend.activeEpoch) {
|
|
6616
|
+
if (!durable || durable.providerSessionId !== process2.providerSessionId || durable.providerBackend !== (sandboxBackendForSdkBackendId(backend.kind) ?? backend.kind) || durable.providerInstanceId !== backend.providerInstanceId || durable.leaseEpoch !== backend.leaseEpoch || durable.routeKind !== (backend.sandboxId === null ? "home" : "active") || durable.routeTargetId !== backend.sandboxId || durable.routeEpoch !== backend.activeEpoch) {
|
|
6557
6617
|
throw new Error("Retained-process settlement lost its exact durable backend identity");
|
|
6558
6618
|
}
|
|
6559
6619
|
const settlement = await settleRetainedProcess(services.db, {
|
|
@@ -6584,7 +6644,7 @@ function adoptRetainedProcessAsBackgroundCommandForTurn(services, ids) {
|
|
|
6584
6644
|
sessionId: ids.sessionId,
|
|
6585
6645
|
processId: process2.id
|
|
6586
6646
|
});
|
|
6587
|
-
if (!durable || durable.providerSessionId !== process2.providerSessionId || durable.providerBackend !== backend.kind || durable.providerInstanceId !== backend.providerInstanceId || durable.leaseEpoch !== backend.leaseEpoch || durable.routeKind !== (backend.sandboxId === null ? "home" : "active") || durable.routeTargetId !== backend.sandboxId || durable.routeEpoch !== backend.activeEpoch) {
|
|
6647
|
+
if (!durable || durable.providerSessionId !== process2.providerSessionId || durable.providerBackend !== (sandboxBackendForSdkBackendId(backend.kind) ?? backend.kind) || durable.providerInstanceId !== backend.providerInstanceId || durable.leaseEpoch !== backend.leaseEpoch || durable.routeKind !== (backend.sandboxId === null ? "home" : "active") || durable.routeTargetId !== backend.sandboxId || durable.routeEpoch !== backend.activeEpoch) {
|
|
6588
6648
|
throw new Error("Background command adoption lost its exact retained-process identity");
|
|
6589
6649
|
}
|
|
6590
6650
|
await adoptManagedSessionBackgroundCommand(services.db, {
|
|
@@ -6769,14 +6829,20 @@ function wrapTurnBoxWithRouting(services, ids, established) {
|
|
|
6769
6829
|
},
|
|
6770
6830
|
resolveActiveBackend: resolver,
|
|
6771
6831
|
...services.onSandboxOperation ? { onOperation: services.onSandboxOperation } : {},
|
|
6832
|
+
...services.onSandboxCaptureWait ? { onCaptureWait: services.onSandboxCaptureWait } : {},
|
|
6772
6833
|
providerCommandHandle: admittedCommandHandle,
|
|
6834
|
+
providerSupervisionReady: async () => settings.modalCommandSupervisionEnabled && await supervisedCommandProtocolReady(db),
|
|
6773
6835
|
...ids.workspaceMutationFence ? {
|
|
6774
|
-
providerCommandPersistence: (process2) => retainedProviderCommandPersistence(
|
|
6775
|
-
|
|
6776
|
-
|
|
6777
|
-
|
|
6778
|
-
|
|
6779
|
-
|
|
6836
|
+
providerCommandPersistence: (process2) => retainedProviderCommandPersistence(
|
|
6837
|
+
db,
|
|
6838
|
+
{
|
|
6839
|
+
accountId: ids.workspaceMutationFence.accountId,
|
|
6840
|
+
workspaceId: ids.workspaceId,
|
|
6841
|
+
sessionId: ids.sessionId,
|
|
6842
|
+
processId: process2.id
|
|
6843
|
+
},
|
|
6844
|
+
services.bus ? (events) => services.bus.publish(ids.workspaceId, ids.sessionId, events) : void 0
|
|
6845
|
+
)
|
|
6780
6846
|
} : {},
|
|
6781
6847
|
...beforeMutation ? { beforeMutation } : {},
|
|
6782
6848
|
...afterMutation ? { afterMutation } : {},
|
|
@@ -6801,6 +6867,7 @@ function wrapTurnBoxWithRouting(services, ids, established) {
|
|
|
6801
6867
|
sandboxGroupId: home.sandboxGroupId,
|
|
6802
6868
|
expectedEpoch,
|
|
6803
6869
|
expectedInstanceId,
|
|
6870
|
+
expectedBackend: home.backend,
|
|
6804
6871
|
diagnostic: "provider_not_found_during_routed_operation"
|
|
6805
6872
|
});
|
|
6806
6873
|
if (marked.status === "marked") {
|
|
@@ -6965,15 +7032,21 @@ function wrapLazyTurnBoxWithRouting(services, ids, args) {
|
|
|
6965
7032
|
return routedResolver(pointer);
|
|
6966
7033
|
},
|
|
6967
7034
|
...services.onSandboxOperation ? { onOperation: services.onSandboxOperation } : {},
|
|
7035
|
+
...services.onSandboxCaptureWait ? { onCaptureWait: services.onSandboxCaptureWait } : {},
|
|
6968
7036
|
...args.onFirstOperation ? { onFirstOperation: args.onFirstOperation } : {},
|
|
6969
7037
|
providerCommandHandle: admittedCommandHandle,
|
|
7038
|
+
providerSupervisionReady: async () => settings.modalCommandSupervisionEnabled && await supervisedCommandProtocolReady(db),
|
|
6970
7039
|
...ids.workspaceMutationFence ? {
|
|
6971
|
-
providerCommandPersistence: (process2) => retainedProviderCommandPersistence(
|
|
6972
|
-
|
|
6973
|
-
|
|
6974
|
-
|
|
6975
|
-
|
|
6976
|
-
|
|
7040
|
+
providerCommandPersistence: (process2) => retainedProviderCommandPersistence(
|
|
7041
|
+
db,
|
|
7042
|
+
{
|
|
7043
|
+
accountId: ids.workspaceMutationFence.accountId,
|
|
7044
|
+
workspaceId: ids.workspaceId,
|
|
7045
|
+
sessionId: ids.sessionId,
|
|
7046
|
+
processId: process2.id
|
|
7047
|
+
},
|
|
7048
|
+
services.bus ? (events) => services.bus.publish(ids.workspaceId, ids.sessionId, events) : void 0
|
|
7049
|
+
)
|
|
6977
7050
|
} : {},
|
|
6978
7051
|
...beforeMutation ? { beforeMutation } : {},
|
|
6979
7052
|
...afterMutation ? { afterMutation } : {},
|
|
@@ -6999,6 +7072,7 @@ function wrapLazyTurnBoxWithRouting(services, ids, args) {
|
|
|
6999
7072
|
sandboxGroupId: home.sandboxGroupId,
|
|
7000
7073
|
expectedEpoch: backend.leaseEpoch,
|
|
7001
7074
|
expectedInstanceId: backend.providerInstanceId,
|
|
7075
|
+
expectedBackend: home.backend,
|
|
7002
7076
|
diagnostic: "provider_not_found_during_routed_operation"
|
|
7003
7077
|
});
|
|
7004
7078
|
if (marked.status === "marked") {
|
|
@@ -7202,6 +7276,7 @@ import {
|
|
|
7202
7276
|
getSession,
|
|
7203
7277
|
getSessionGoal as getSessionGoal2,
|
|
7204
7278
|
getSessionParentPersonalConnectionDelegations,
|
|
7279
|
+
getSessionParentMcpAccountBindings,
|
|
7205
7280
|
getSessionParentXaiProviderAccountAuthority,
|
|
7206
7281
|
addSessionSystemUpdateWithSourceMutation,
|
|
7207
7282
|
claimPendingSessionSystemUpdateOutbox,
|
|
@@ -7232,6 +7307,11 @@ async function notifyParentOfChildIdle(svc, workspaceId, childSessionId, episode
|
|
|
7232
7307
|
workspaceId,
|
|
7233
7308
|
childSessionId
|
|
7234
7309
|
);
|
|
7310
|
+
const mcpAccountBindings = await getSessionParentMcpAccountBindings(
|
|
7311
|
+
svc.db,
|
|
7312
|
+
workspaceId,
|
|
7313
|
+
childSessionId
|
|
7314
|
+
);
|
|
7235
7315
|
const xaiAuthority = await getSessionParentXaiProviderAccountAuthority(
|
|
7236
7316
|
svc.db,
|
|
7237
7317
|
workspaceId,
|
|
@@ -7254,6 +7334,7 @@ async function notifyParentOfChildIdle(svc, workspaceId, childSessionId, episode
|
|
|
7254
7334
|
...xaiAuthority.subjectId ? { xaiAuthoritySubjectId: xaiAuthority.subjectId } : {}
|
|
7255
7335
|
},
|
|
7256
7336
|
personalConnectionDelegations,
|
|
7337
|
+
mcpAccountBindings,
|
|
7257
7338
|
xaiProviderAccountAuthoritySnapshot: xaiAuthority.snapshot
|
|
7258
7339
|
});
|
|
7259
7340
|
if (outbox.status === "delivered") {
|
|
@@ -7329,6 +7410,7 @@ async function deliverParentSystemUpdateOutbox(svc, outbox) {
|
|
|
7329
7410
|
summary: outbox.summary,
|
|
7330
7411
|
lineage: outbox.lineage,
|
|
7331
7412
|
personalConnectionDelegations: outbox.personalConnectionDelegations,
|
|
7413
|
+
mcpAccountBindings: outbox.mcpAccountBindings,
|
|
7332
7414
|
xaiProviderAccountAuthoritySnapshot: outbox.xaiProviderAccountAuthoritySnapshot
|
|
7333
7415
|
},
|
|
7334
7416
|
async (tx) => {
|
|
@@ -8446,12 +8528,14 @@ async function persistOrSignalSessionAttemptQuiescence(input) {
|
|
|
8446
8528
|
return "receipt";
|
|
8447
8529
|
}
|
|
8448
8530
|
async function drainAttemptOwnedSandboxWriters(input) {
|
|
8531
|
+
input.onStage?.("tool_writers");
|
|
8449
8532
|
if (input.toolCancellationFence) {
|
|
8450
8533
|
input.toolCancellationFence.cancel(
|
|
8451
8534
|
input.cancellationReason ?? new Error("TURN_ATTEMPT_FENCED")
|
|
8452
8535
|
);
|
|
8453
8536
|
await input.toolCancellationFence.waitForQuiescence();
|
|
8454
8537
|
}
|
|
8538
|
+
input.onStage?.("credential_renewals");
|
|
8455
8539
|
await Promise.all(input.gitCredentialRenewals.map(async (renewal) => await renewal.stop()));
|
|
8456
8540
|
await input.codemodeTokenRenewal?.stop();
|
|
8457
8541
|
await input.runCredentialRenewal?.stop();
|
|
@@ -8597,10 +8681,14 @@ import {
|
|
|
8597
8681
|
ActiveBackendUnresolvableError as ActiveBackendUnresolvableError2,
|
|
8598
8682
|
CompactionProviderResponseError,
|
|
8599
8683
|
EmptyCompactionSummaryError,
|
|
8684
|
+
compactionProviderRejection,
|
|
8685
|
+
describeCompactionProviderRejection,
|
|
8600
8686
|
isMcpRequestTimeoutError,
|
|
8601
8687
|
isMcpTransportConnectivityError,
|
|
8602
8688
|
isModalTaskExecStartDnsResolutionError,
|
|
8603
8689
|
RoutingWorkspaceRootChangedError,
|
|
8690
|
+
SandboxMaterializationVerificationError,
|
|
8691
|
+
materializationVerificationDiagnostic,
|
|
8604
8692
|
SelfhostedWorkspaceRootChangedError,
|
|
8605
8693
|
UNKNOWN_MODEL_FINISH_REASON_CODE
|
|
8606
8694
|
} from "@opengeni/runtime";
|
|
@@ -8772,12 +8860,8 @@ function attachmentRefsFromItem(item) {
|
|
|
8772
8860
|
}
|
|
8773
8861
|
return refs;
|
|
8774
8862
|
}
|
|
8775
|
-
function attachmentReceiptText(ref
|
|
8776
|
-
|
|
8777
|
-
return `[Earlier attachment: fileId=${ref.fileId}; mountDirectory=${resourceMountPath(ref)}. Use the existing file there, or call files__files_get_download_url with this fileId and download it with the shell.]`;
|
|
8778
|
-
}
|
|
8779
|
-
const path = sandboxFilePath(ref, file);
|
|
8780
|
-
return `[Attachment: ${file.safeFilename}; fileId=${file.id}; type=${file.contentType}; bytes=${file.sizeBytes}; path=${path}. If the local path is absent, call files__files_get_download_url with this fileId and download it with the shell.]`;
|
|
8863
|
+
function attachmentReceiptText(ref) {
|
|
8864
|
+
return `[Attachment: fileId=${ref.fileId}; mountDirectory=${resourceMountPath(ref)}. Use the existing file there, or call files__files_get_download_url with this fileId and download it with the shell.]`;
|
|
8781
8865
|
}
|
|
8782
8866
|
function createModelHistoryAttachmentProjector(policy, readFileBytes, loadAuthorizedFiles) {
|
|
8783
8867
|
const contentById = /* @__PURE__ */ new Map();
|
|
@@ -8856,7 +8940,7 @@ function createModelHistoryAttachmentProjector(policy, readFileBytes, loadAuthor
|
|
|
8856
8940
|
const attachment = currentFile ? contentById.get(ref.fileId) : void 0;
|
|
8857
8941
|
const receipt = {
|
|
8858
8942
|
type: "input_text",
|
|
8859
|
-
text: attachmentReceiptText(ref
|
|
8943
|
+
text: attachmentReceiptText(ref)
|
|
8860
8944
|
};
|
|
8861
8945
|
if (!attachment || attachment.kind !== "image") {
|
|
8862
8946
|
return [receipt];
|
|
@@ -8875,12 +8959,18 @@ function createModelHistoryAttachmentProjector(policy, readFileBytes, loadAuthor
|
|
|
8875
8959
|
}
|
|
8876
8960
|
function withCurrentUserAttachmentRefs(historyItems, refs) {
|
|
8877
8961
|
if (refs.length === 0) return historyItems;
|
|
8962
|
+
const retainedIds = new Set(
|
|
8963
|
+
historyItems.flatMap((item) => attachmentRefsFromItem(item).map((ref) => ref.fileId))
|
|
8964
|
+
);
|
|
8965
|
+
const missing = refs.filter((ref) => !retainedIds.has(ref.fileId));
|
|
8966
|
+
if (missing.length === 0) return historyItems;
|
|
8878
8967
|
for (let index = historyItems.length - 1; index >= 0; index -= 1) {
|
|
8879
8968
|
const item = historyItems[index];
|
|
8969
|
+
if (item[MODEL_ATTACHMENT_CATALOG_MARKER] === true) continue;
|
|
8880
8970
|
if (item.type !== "message" || item.role !== "user") continue;
|
|
8881
8971
|
const existing = attachmentRefsFromItem(item);
|
|
8882
8972
|
const existingIds = new Set(existing.map((ref) => ref.fileId));
|
|
8883
|
-
const additions =
|
|
8973
|
+
const additions = missing.filter((ref) => !existingIds.has(ref.fileId));
|
|
8884
8974
|
if (additions.length === 0) return historyItems;
|
|
8885
8975
|
const projected = [...historyItems];
|
|
8886
8976
|
projected[index] = { ...item, [MODEL_ATTACHMENT_REFS_FIELD]: [...existing, ...additions] };
|
|
@@ -8950,8 +9040,8 @@ async function turnInput(db, runtime, agent, trigger, options) {
|
|
|
8950
9040
|
options
|
|
8951
9041
|
);
|
|
8952
9042
|
}
|
|
8953
|
-
if (trigger.type === "system.update.delivered") {
|
|
8954
|
-
if (updates.length === 0) {
|
|
9043
|
+
if (trigger.type === "system.update.delivered" || trigger.type === "session.context.compaction.requested") {
|
|
9044
|
+
if (trigger.type === "system.update.delivered" && updates.length === 0) {
|
|
8955
9045
|
throw new Error("Internal update inference has no delivered updates");
|
|
8956
9046
|
}
|
|
8957
9047
|
return await messageInput(
|
|
@@ -9117,6 +9207,7 @@ function sandboxFilePath(resource, file) {
|
|
|
9117
9207
|
// src/activities/agent-turn/errors.ts
|
|
9118
9208
|
import {
|
|
9119
9209
|
CodexReloginRequired,
|
|
9210
|
+
classifyCodexEncryptedArtifactRejection,
|
|
9120
9211
|
classifyCodexResponseTimeoutError,
|
|
9121
9212
|
classifyCodexUsageLimitError,
|
|
9122
9213
|
isCodexTransportError
|
|
@@ -9242,9 +9333,15 @@ function escapedMcpTimeoutRecoveryFailure(input) {
|
|
|
9242
9333
|
function preClaimAdmissionFailure(error) {
|
|
9243
9334
|
const persistenceFailure = isSessionEventPersistenceError(error) ? error : null;
|
|
9244
9335
|
const retryableCode = retryableDatabaseFailureCode(error);
|
|
9336
|
+
const rejectedClaim = persistenceFailure?.details.stage === "session_attempts.claim" && persistenceFailure.details.retryOutcome === "not_retryable" && !retryableCode;
|
|
9245
9337
|
const detail = {
|
|
9246
|
-
disposition: persistenceFailure || retryableCode ? "retryable" : "permanent",
|
|
9247
|
-
code: retryableCode ?? persistenceFailure?.details.code ?? "claim_invariant"
|
|
9338
|
+
disposition: rejectedClaim ? "blocked" : persistenceFailure || retryableCode ? "retryable" : "permanent",
|
|
9339
|
+
code: retryableCode ?? persistenceFailure?.details.code ?? "claim_invariant",
|
|
9340
|
+
...persistenceFailure && rejectedClaim ? {
|
|
9341
|
+
sqlState: persistenceFailure.details.sqlState,
|
|
9342
|
+
reason: persistenceFailure.details.stage === "session_attempts.claim" && persistenceFailure.details.sqlState === "OG001" ? "initiator_membership_required" : persistenceFailure.details.stage === "session_attempts.claim" && persistenceFailure.details.sqlState === "OG002" ? "personal_resource_grant_required" : "database_claim_rejected",
|
|
9343
|
+
retryPolicy: "explicit_recheck"
|
|
9344
|
+
} : {}
|
|
9248
9345
|
};
|
|
9249
9346
|
return ApplicationFailure.create({
|
|
9250
9347
|
message: PRE_CLAIM_FAILURE_MESSAGE,
|
|
@@ -9384,19 +9481,38 @@ function safeErrorForTelemetry(error) {
|
|
|
9384
9481
|
safe.origin = diagnostic.origin;
|
|
9385
9482
|
return safe;
|
|
9386
9483
|
}
|
|
9484
|
+
var COMPACTION_PROVIDER_REJECTION_GUIDANCE = "The provider refused this exact request, so repeating it fails the same way until the conversation changes. If a new message fails again, start a new session.";
|
|
9387
9485
|
function compactionFailureReasonFromError(error) {
|
|
9486
|
+
const rejection = compactionProviderRejection(error);
|
|
9487
|
+
if (rejection) {
|
|
9488
|
+
return compactionFailureReason(
|
|
9489
|
+
`the model provider rejected the compaction request (${describeCompactionProviderRejection(rejection)}). Active history was preserved. ${COMPACTION_PROVIDER_REJECTION_GUIDANCE}`
|
|
9490
|
+
);
|
|
9491
|
+
}
|
|
9388
9492
|
if (error instanceof CompactionProviderResponseError || error instanceof EmptyCompactionSummaryError) {
|
|
9389
9493
|
return compactionFailureReason(error.message);
|
|
9390
9494
|
}
|
|
9391
9495
|
const errorName = error instanceof Error && error.name ? error.name : "unknown error";
|
|
9392
9496
|
return compactionFailureReason(`unexpected ${errorName}`);
|
|
9393
9497
|
}
|
|
9498
|
+
function compactionFailureTurnEventPayload(error, overrides = {}) {
|
|
9499
|
+
const rejection = compactionProviderRejection(error);
|
|
9500
|
+
return {
|
|
9501
|
+
error: overrides.error ?? compactionFailureReasonFromError(error),
|
|
9502
|
+
code: "context_compaction_failed",
|
|
9503
|
+
retryable: false,
|
|
9504
|
+
recovery: "user_message",
|
|
9505
|
+
compacted: false,
|
|
9506
|
+
...rejection ? { providerRejection: rejection } : {}
|
|
9507
|
+
};
|
|
9508
|
+
}
|
|
9394
9509
|
function isCompactionSummaryFailure(error) {
|
|
9395
9510
|
return error instanceof CompactionProviderResponseError || error instanceof EmptyCompactionSummaryError;
|
|
9396
9511
|
}
|
|
9397
9512
|
function shouldRecoverCompactionProviderFailure(error) {
|
|
9398
9513
|
if (!(error instanceof CompactionProviderResponseError)) return false;
|
|
9399
9514
|
if (isCodexTransportError(error) && classifyCodexUsageLimitError(error)) return true;
|
|
9515
|
+
if (classifyCodexEncryptedArtifactRejection(error)) return true;
|
|
9400
9516
|
return agentRunFailurePayload(error).retryable === true;
|
|
9401
9517
|
}
|
|
9402
9518
|
function classifyContextWindowOverflowError(error) {
|
|
@@ -9546,6 +9662,19 @@ function findPostgresDriverError(error) {
|
|
|
9546
9662
|
return null;
|
|
9547
9663
|
}
|
|
9548
9664
|
function agentRunFailurePayload(error, options = {}) {
|
|
9665
|
+
const failure = baseAgentRunFailurePayload(error, options);
|
|
9666
|
+
const diagnostic = materializationVerificationDiagnostic(error);
|
|
9667
|
+
return diagnostic ? { ...failure, materializationDiagnostic: diagnostic } : failure;
|
|
9668
|
+
}
|
|
9669
|
+
function baseAgentRunFailurePayload(error, options = {}) {
|
|
9670
|
+
if (error instanceof SandboxMaterializationVerificationError) {
|
|
9671
|
+
return {
|
|
9672
|
+
error: error.message,
|
|
9673
|
+
code: error.code,
|
|
9674
|
+
retryable: false,
|
|
9675
|
+
materializationDiagnostic: error.diagnostic
|
|
9676
|
+
};
|
|
9677
|
+
}
|
|
9549
9678
|
if (error instanceof RetainedAttachmentTransportLimitError) {
|
|
9550
9679
|
return { error: error.message, code: "retained_attachment_transport_limit", retryable: false };
|
|
9551
9680
|
}
|
|
@@ -9846,12 +9975,11 @@ export {
|
|
|
9846
9975
|
withFirstPartyTools,
|
|
9847
9976
|
createKnowledgeSourceSyncActivities,
|
|
9848
9977
|
rigProviderImageSourceImage,
|
|
9849
|
-
settingsWithPackSandboxImage,
|
|
9850
|
-
resolveWorkspacePackRuntime,
|
|
9851
9978
|
createRuntimeBatcher,
|
|
9852
9979
|
currentActivityContext,
|
|
9853
9980
|
startActivityHeartbeat,
|
|
9854
9981
|
nextStreamEvent,
|
|
9982
|
+
warnDrainSnapshotFailure,
|
|
9855
9983
|
persistWorkspaceArchiveCandidate,
|
|
9856
9984
|
putVersion1TarArchiveOrInline,
|
|
9857
9985
|
sandboxLeaseHolderIdForAttempt,
|
|
@@ -9925,6 +10053,7 @@ export {
|
|
|
9925
10053
|
safeErrorDiagnostic,
|
|
9926
10054
|
safeErrorForTelemetry,
|
|
9927
10055
|
compactionFailureReasonFromError,
|
|
10056
|
+
compactionFailureTurnEventPayload,
|
|
9928
10057
|
isCompactionSummaryFailure,
|
|
9929
10058
|
shouldRecoverCompactionProviderFailure,
|
|
9930
10059
|
classifyContextWindowOverflowError,
|
|
@@ -9935,4 +10064,4 @@ export {
|
|
|
9935
10064
|
codexUsageLimitFailurePayload,
|
|
9936
10065
|
CODEX_USAGE_LIMIT_MAX_RESUME_MS
|
|
9937
10066
|
};
|
|
9938
|
-
//# sourceMappingURL=chunk-
|
|
10067
|
+
//# sourceMappingURL=chunk-TVEE2UUC.js.map
|