@opengeni/worker-bundle 1.0.1 → 2.0.0-canary.35585322809001
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 +19 -19
- 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
|
@@ -28,12 +28,12 @@ import {
|
|
|
28
28
|
reconcilePendingParentSystemUpdates,
|
|
29
29
|
reconcilePendingSessionWorkflowWakes,
|
|
30
30
|
resolveIncidentTelemetryResponderMetadata,
|
|
31
|
-
resolveWorkspacePackRuntime,
|
|
32
31
|
rigProviderImageSourceImage,
|
|
33
32
|
scheduledUserMessagePayload,
|
|
33
|
+
warnDrainSnapshotFailure,
|
|
34
34
|
withFirstPartyTools,
|
|
35
35
|
workflowIdForSession
|
|
36
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-TVEE2UUC.js";
|
|
37
37
|
import {
|
|
38
38
|
inspectOpenSandboxKubernetesInventory,
|
|
39
39
|
recordCreditBalanceGauges,
|
|
@@ -53,7 +53,7 @@ import {
|
|
|
53
53
|
recordTurnsQueuedGauge,
|
|
54
54
|
recordWorkerDeathRecoveryMetrics,
|
|
55
55
|
runtimeMetricsHooksForObservability
|
|
56
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-I7HKKMUJ.js";
|
|
57
57
|
import "./chunk-PZ5AY32C.js";
|
|
58
58
|
|
|
59
59
|
// src/activities/knowledge-indexing.ts
|
|
@@ -978,13 +978,13 @@ var RIG_VERIFICATION_CLEANUP_OPERATION_MAX_MS = 6e4;
|
|
|
978
978
|
var RIG_VERIFICATION_HEARTBEAT_MAX_INTERVAL_MS = 1e4;
|
|
979
979
|
var RIG_VERIFICATION_HEARTBEAT_MIN_INTERVAL_MS = 250;
|
|
980
980
|
var RIG_VERIFICATION_OWNER_TTL_MS = 20 * 6e4;
|
|
981
|
-
var RIG_VERIFICATION_OWNERS_DISABLED_MESSAGE = "
|
|
981
|
+
var RIG_VERIFICATION_OWNERS_DISABLED_MESSAGE = "Sandbox Environment verification lease ownership is disabled; refusing to create an unowned verifier sandbox";
|
|
982
982
|
var RIG_VERIFICATION_HOLDER_TOUCH_INTERVAL_MS = 1e4;
|
|
983
983
|
var RIG_VERIFICATION_RELEASE_GRACE_MS = 1;
|
|
984
984
|
var RigVerificationActivityDeadlineError = class extends Error {
|
|
985
985
|
constructor(startToCloseTimeoutMs, cleanupReserveMs) {
|
|
986
986
|
super(
|
|
987
|
-
`
|
|
987
|
+
`Sandbox Environment verification activity-local deadline reached with ${cleanupReserveMs}ms reserved for cleanup before the ${startToCloseTimeoutMs}ms Temporal start-to-close timeout`
|
|
988
988
|
);
|
|
989
989
|
this.startToCloseTimeoutMs = startToCloseTimeoutMs;
|
|
990
990
|
this.cleanupReserveMs = cleanupReserveMs;
|
|
@@ -1003,7 +1003,9 @@ function createRigVerificationActivityLifecycle(context = currentActivityContext
|
|
|
1003
1003
|
const temporalSignal = context?.cancellationSignal;
|
|
1004
1004
|
const forwardTemporalCancellation = () => {
|
|
1005
1005
|
if (!controller.signal.aborted) {
|
|
1006
|
-
controller.abort(
|
|
1006
|
+
controller.abort(
|
|
1007
|
+
temporalSignal?.reason ?? new Error("Sandbox Environment verification cancelled")
|
|
1008
|
+
);
|
|
1007
1009
|
}
|
|
1008
1010
|
};
|
|
1009
1011
|
if (temporalSignal?.aborted) {
|
|
@@ -1065,7 +1067,7 @@ function createRigVerificationActivityLifecycle(context = currentActivityContext
|
|
|
1065
1067
|
};
|
|
1066
1068
|
}
|
|
1067
1069
|
function abortReason(signal) {
|
|
1068
|
-
return signal.reason ?? new Error("
|
|
1070
|
+
return signal.reason ?? new Error("Sandbox Environment verification cancelled");
|
|
1069
1071
|
}
|
|
1070
1072
|
function throwIfAborted(signal) {
|
|
1071
1073
|
if (signal.aborted) throw abortReason(signal);
|
|
@@ -1145,7 +1147,9 @@ var defaultOwnershipDependencies = {
|
|
|
1145
1147
|
};
|
|
1146
1148
|
var RigVerificationLeaseUnavailableError = class extends Error {
|
|
1147
1149
|
constructor(sandboxGroupId, role) {
|
|
1148
|
-
super(
|
|
1150
|
+
super(
|
|
1151
|
+
`Sandbox Environment verification requires a new clean sandbox, but lease ${sandboxGroupId} was ${role}`
|
|
1152
|
+
);
|
|
1149
1153
|
this.sandboxGroupId = sandboxGroupId;
|
|
1150
1154
|
this.role = role;
|
|
1151
1155
|
}
|
|
@@ -1168,7 +1172,7 @@ async function runWithOwnedRigVerificationSandbox(input, run, dependencies = def
|
|
|
1168
1172
|
let establishmentSettled = false;
|
|
1169
1173
|
let establishmentPromise = null;
|
|
1170
1174
|
const warnCleanupTimeout = (operation, instanceId) => {
|
|
1171
|
-
input.observability.warn("
|
|
1175
|
+
input.observability.warn("sandbox environment verifier: ownership cleanup timed out", {
|
|
1172
1176
|
holderId,
|
|
1173
1177
|
instanceId,
|
|
1174
1178
|
operation,
|
|
@@ -1176,7 +1180,7 @@ async function runWithOwnedRigVerificationSandbox(input, run, dependencies = def
|
|
|
1176
1180
|
});
|
|
1177
1181
|
};
|
|
1178
1182
|
const warnCleanupFailure = (operation, instanceId, error) => {
|
|
1179
|
-
input.observability.warn("
|
|
1183
|
+
input.observability.warn("sandbox environment verifier: ownership cleanup failed", {
|
|
1180
1184
|
holderId,
|
|
1181
1185
|
instanceId,
|
|
1182
1186
|
operation,
|
|
@@ -1302,11 +1306,14 @@ async function runWithOwnedRigVerificationSandbox(input, run, dependencies = def
|
|
|
1302
1306
|
);
|
|
1303
1307
|
} catch (error) {
|
|
1304
1308
|
if (!signal.aborted) {
|
|
1305
|
-
input.observability.warn(
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1309
|
+
input.observability.warn(
|
|
1310
|
+
"sandbox environment verifier: Modal ownership tag failed",
|
|
1311
|
+
{
|
|
1312
|
+
holderId,
|
|
1313
|
+
instanceId: created.instanceId,
|
|
1314
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1315
|
+
}
|
|
1316
|
+
);
|
|
1310
1317
|
}
|
|
1311
1318
|
}
|
|
1312
1319
|
}
|
|
@@ -1501,10 +1508,12 @@ function rigProviderImageContentMarkerCommand(contentHash, markerRoot = "/var/op
|
|
|
1501
1508
|
}
|
|
1502
1509
|
function rigProviderImageContentMarker(contentHash, markerRoot = "/var/opengeni") {
|
|
1503
1510
|
if (!/^sha256:[0-9a-f]{64}$/u.test(contentHash)) {
|
|
1504
|
-
throw new Error(
|
|
1511
|
+
throw new Error(
|
|
1512
|
+
"Sandbox Environment provider image content marker requires a canonical SHA-256 value"
|
|
1513
|
+
);
|
|
1505
1514
|
}
|
|
1506
1515
|
if (!/^\/[A-Za-z0-9._/-]+$/u.test(markerRoot)) {
|
|
1507
|
-
throw new Error("
|
|
1516
|
+
throw new Error("Sandbox Environment provider image marker root must be a safe absolute path");
|
|
1508
1517
|
}
|
|
1509
1518
|
const normalizedRoot = markerRoot.replace(/\/+$/u, "") || "/";
|
|
1510
1519
|
const marker = `${normalizedRoot === "/" ? "" : normalizedRoot}/rig-setup-content-${contentHash.slice("sha256:".length)}.done`;
|
|
@@ -1542,7 +1551,9 @@ async function verifyRigProviderImageColdBoot(input, dependencies = defaultRigPr
|
|
|
1542
1551
|
runContext.commandRunner
|
|
1543
1552
|
);
|
|
1544
1553
|
if (markerResult.exitCode !== 0) {
|
|
1545
|
-
throw new Error(
|
|
1554
|
+
throw new Error(
|
|
1555
|
+
"built provider image is missing its exact sandbox environment-content marker"
|
|
1556
|
+
);
|
|
1546
1557
|
}
|
|
1547
1558
|
for (const check of rigPlatformChecksForSettings(input.settings)) {
|
|
1548
1559
|
const result = await runCommand(
|
|
@@ -1627,7 +1638,7 @@ async function buildVerifiedRigProviderImage(input) {
|
|
|
1627
1638
|
finishedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1628
1639
|
error: {
|
|
1629
1640
|
code: "provider_image_content_conflict",
|
|
1630
|
-
message: "this exact
|
|
1641
|
+
message: "this exact sandbox environment version already records a provider image for different effective content; mint and verify a new version",
|
|
1631
1642
|
retryable: false
|
|
1632
1643
|
}
|
|
1633
1644
|
};
|
|
@@ -1801,37 +1812,36 @@ async function buildVerifiedRigProviderImage(input) {
|
|
|
1801
1812
|
});
|
|
1802
1813
|
}
|
|
1803
1814
|
}
|
|
1804
|
-
function settingsForRigVerification(settings,
|
|
1805
|
-
void packRuntime;
|
|
1815
|
+
function settingsForRigVerification(settings, rigImage) {
|
|
1806
1816
|
void rigImage;
|
|
1807
1817
|
return settings;
|
|
1808
1818
|
}
|
|
1809
1819
|
async function loadChangeTarget(db, workspaceId, changeId) {
|
|
1810
1820
|
const change = await getRigChange(db, workspaceId, changeId);
|
|
1811
1821
|
if (!change) {
|
|
1812
|
-
throw new Error(`
|
|
1822
|
+
throw new Error(`Sandbox Environment change not found: ${changeId}`);
|
|
1813
1823
|
}
|
|
1814
1824
|
const rig = await getRig(db, workspaceId, change.rigId);
|
|
1815
1825
|
if (!rig) {
|
|
1816
|
-
throw new Error(`
|
|
1826
|
+
throw new Error(`Sandbox Environment not found for change: ${change.rigId}`);
|
|
1817
1827
|
}
|
|
1818
1828
|
if (!change.baseVersionId) {
|
|
1819
|
-
throw new Error(`
|
|
1829
|
+
throw new Error(`Sandbox Environment change ${change.id} has no base version`);
|
|
1820
1830
|
}
|
|
1821
1831
|
const baseVersion = await getRigVersionById(db, workspaceId, change.baseVersionId);
|
|
1822
1832
|
if (!baseVersion || baseVersion.rigId !== rig.id) {
|
|
1823
|
-
throw new Error(`Base
|
|
1833
|
+
throw new Error(`Base sandbox environment version not found: ${change.baseVersionId}`);
|
|
1824
1834
|
}
|
|
1825
1835
|
return { rig, baseVersion, change };
|
|
1826
1836
|
}
|
|
1827
1837
|
async function loadVersionTarget(db, workspaceId, versionId) {
|
|
1828
1838
|
const version = await getRigVersionById(db, workspaceId, versionId);
|
|
1829
1839
|
if (!version) {
|
|
1830
|
-
throw new Error(`
|
|
1840
|
+
throw new Error(`Sandbox Environment version not found: ${versionId}`);
|
|
1831
1841
|
}
|
|
1832
1842
|
const rig = await getRig(db, workspaceId, version.rigId);
|
|
1833
1843
|
if (!rig) {
|
|
1834
|
-
throw new Error(`
|
|
1844
|
+
throw new Error(`Sandbox Environment not found for version: ${version.rigId}`);
|
|
1835
1845
|
}
|
|
1836
1846
|
return { rig, version };
|
|
1837
1847
|
}
|
|
@@ -1874,12 +1884,7 @@ function createRigVerificationActivities(services) {
|
|
|
1874
1884
|
change,
|
|
1875
1885
|
candidateVersion
|
|
1876
1886
|
);
|
|
1877
|
-
const
|
|
1878
|
-
const runSettings = settingsForRigVerification(
|
|
1879
|
-
settings,
|
|
1880
|
-
packRuntime,
|
|
1881
|
-
candidateVersion.image
|
|
1882
|
-
);
|
|
1887
|
+
const runSettings = settingsForRigVerification(settings, candidateVersion.image);
|
|
1883
1888
|
const providerImageContentHash = rigProviderImageContentHash({
|
|
1884
1889
|
backend: runSettings.sandboxBackend,
|
|
1885
1890
|
sourceImage: rigProviderImageSourceImage(runSettings, runSettings.sandboxBackend),
|
|
@@ -1953,7 +1958,7 @@ function createRigVerificationActivities(services) {
|
|
|
1953
1958
|
);
|
|
1954
1959
|
if (markerResult.exitCode !== 0) {
|
|
1955
1960
|
throw new Error(
|
|
1956
|
-
`Failed to seal
|
|
1961
|
+
`Failed to seal sandbox environment provider image content marker: ${markerResult.output.slice(-2e3)}`
|
|
1957
1962
|
);
|
|
1958
1963
|
}
|
|
1959
1964
|
const platformCheckResults = await runRigChecks(
|
|
@@ -2064,8 +2069,7 @@ function createRigVerificationActivities(services) {
|
|
|
2064
2069
|
metadata: { versionId: version.id }
|
|
2065
2070
|
});
|
|
2066
2071
|
try {
|
|
2067
|
-
const
|
|
2068
|
-
const runSettings = settingsForRigVerification(settings, packRuntime, version.image);
|
|
2072
|
+
const runSettings = settingsForRigVerification(settings, version.image);
|
|
2069
2073
|
const providerImageContentHash = rigProviderImageContentHash({
|
|
2070
2074
|
backend: runSettings.sandboxBackend,
|
|
2071
2075
|
sourceImage: rigProviderImageSourceImage(runSettings, runSettings.sandboxBackend),
|
|
@@ -2107,7 +2111,7 @@ function createRigVerificationActivities(services) {
|
|
|
2107
2111
|
);
|
|
2108
2112
|
if (markerResult.exitCode !== 0) {
|
|
2109
2113
|
throw new Error(
|
|
2110
|
-
`Failed to seal
|
|
2114
|
+
`Failed to seal sandbox environment provider image content marker: ${markerResult.output.slice(-2e3)}`
|
|
2111
2115
|
);
|
|
2112
2116
|
}
|
|
2113
2117
|
const platformCheckResults = await runRigChecks(
|
|
@@ -2180,13 +2184,48 @@ function createRigVerificationActivities(services) {
|
|
|
2180
2184
|
};
|
|
2181
2185
|
}
|
|
2182
2186
|
|
|
2187
|
+
// src/retained-process-diagnostics.ts
|
|
2188
|
+
import {
|
|
2189
|
+
databaseFailureCode,
|
|
2190
|
+
nestedPostgresSqlState,
|
|
2191
|
+
safeDatabaseErrorFacts,
|
|
2192
|
+
SandboxWorkspaceMutationFencedError
|
|
2193
|
+
} from "@opengeni/db";
|
|
2194
|
+
function warnRetainedProcessProofFailure(observability, error, process) {
|
|
2195
|
+
let correlationId;
|
|
2196
|
+
try {
|
|
2197
|
+
const sqlState = nestedPostgresSqlState(error);
|
|
2198
|
+
const constraint = safeDatabaseErrorFacts(error).constraint;
|
|
2199
|
+
correlationId = observability.recordFailureDiagnostic({
|
|
2200
|
+
code: error instanceof SandboxWorkspaceMutationFencedError ? "retained_process_fenced" : sqlState ? databaseFailureCode(sqlState) : "retained_process_proof_failed",
|
|
2201
|
+
stage: "sandbox_retained_processes.proof",
|
|
2202
|
+
error,
|
|
2203
|
+
processId: process.id,
|
|
2204
|
+
sessionId: process.sessionId,
|
|
2205
|
+
...process.ownerAttemptId ? { attemptId: process.ownerAttemptId } : {},
|
|
2206
|
+
...process.ownerTurnId ? { turnId: process.ownerTurnId } : {},
|
|
2207
|
+
attempts: process.reconcileAttempts,
|
|
2208
|
+
sqlState,
|
|
2209
|
+
...constraint ? { constraint } : {}
|
|
2210
|
+
});
|
|
2211
|
+
} catch {
|
|
2212
|
+
}
|
|
2213
|
+
try {
|
|
2214
|
+
observability.warn("sandbox reaper: retained-process proof checkpoint failed", {
|
|
2215
|
+
...correlationId ? { correlationId } : {}
|
|
2216
|
+
});
|
|
2217
|
+
} catch {
|
|
2218
|
+
}
|
|
2219
|
+
}
|
|
2220
|
+
|
|
2183
2221
|
// src/activities/sandbox-lease.ts
|
|
2184
2222
|
import { createHash, randomUUID as randomUUID2 } from "crypto";
|
|
2185
|
-
import {
|
|
2223
|
+
import { requestRetainedProcessDeadlineCancellation } from "@opengeni/db/retained-provider-commands";
|
|
2186
2224
|
import { Context } from "@temporalio/activity";
|
|
2187
2225
|
import { OpLostReason, OpState } from "@opengeni/agent-proto";
|
|
2188
2226
|
import {
|
|
2189
2227
|
accrueWarmSeconds,
|
|
2228
|
+
retainedProviderCommandPersistence,
|
|
2190
2229
|
adoptLegacyModalCheckpointArtifact,
|
|
2191
2230
|
confirmDrainCold,
|
|
2192
2231
|
appendSessionEventToSandboxGroup,
|
|
@@ -2215,6 +2254,7 @@ import {
|
|
|
2215
2254
|
recordRetainedProcessReconciliationProof,
|
|
2216
2255
|
replaceWorkspaceArchiveCaptureAfterProof,
|
|
2217
2256
|
readLease,
|
|
2257
|
+
readWorkspaceArchiveCapturePreflight,
|
|
2218
2258
|
reapExpiredSessionListSnapshots,
|
|
2219
2259
|
reapStaleLeaseHoldersGlobal,
|
|
2220
2260
|
requestDueSandboxRotationsGlobal,
|
|
@@ -2356,7 +2396,7 @@ function sandboxDrainActivityAttempt() {
|
|
|
2356
2396
|
}
|
|
2357
2397
|
}
|
|
2358
2398
|
function createSandboxLeaseActivities(services, options = {}) {
|
|
2359
|
-
const terminateBox = options.terminateBox ?? (async (settings, lease, observability, persistArchive, providerCaptureRequestId, captureDisposition, capturePolicy, diskBackedArchives, releaseFailedCapture) => await terminateProviderBox(
|
|
2399
|
+
const terminateBox = options.terminateBox ?? (async (settings, lease, observability, persistArchive, providerCaptureRequestId, captureDisposition, capturePolicy, diskBackedArchives, releaseFailedCapture, workspaceId) => await terminateProviderBox(
|
|
2360
2400
|
settings,
|
|
2361
2401
|
lease,
|
|
2362
2402
|
observability,
|
|
@@ -2367,7 +2407,8 @@ function createSandboxLeaseActivities(services, options = {}) {
|
|
|
2367
2407
|
captureDisposition,
|
|
2368
2408
|
capturePolicy,
|
|
2369
2409
|
diskBackedArchives,
|
|
2370
|
-
releaseFailedCapture
|
|
2410
|
+
releaseFailedCapture,
|
|
2411
|
+
workspaceId
|
|
2371
2412
|
));
|
|
2372
2413
|
const sweepModalOrphans = options.sweepModalOrphans ?? sweepModalOrphansForConfiguredBackend;
|
|
2373
2414
|
const inspectOpenSandboxInventory = options.inspectOpenSandboxKubernetesInventory ?? inspectOpenSandboxKubernetesInventory;
|
|
@@ -2904,18 +2945,14 @@ async function reconcileConnectedMachineBackgroundCommands(db, settings, observa
|
|
|
2904
2945
|
journal: { attachGeneration: () => String(Date.now()), persistSettled: () => {
|
|
2905
2946
|
} }
|
|
2906
2947
|
});
|
|
2907
|
-
|
|
2948
|
+
await replayConnectedCommandOutput(
|
|
2949
|
+
client,
|
|
2908
2950
|
claim.opId,
|
|
2909
|
-
proof
|
|
2951
|
+
Boolean(proof),
|
|
2910
2952
|
async (frames) => {
|
|
2911
2953
|
await captureConnectedCommandOutput(db, claim, bus)(claim.commandId, frames);
|
|
2912
2954
|
}
|
|
2913
2955
|
);
|
|
2914
|
-
if (proof && replay.status !== "completed" && !replay.terminal) {
|
|
2915
|
-
throw new Error(
|
|
2916
|
-
"Connected command terminal output replay has not reached its exit frontier"
|
|
2917
|
-
);
|
|
2918
|
-
}
|
|
2919
2956
|
}
|
|
2920
2957
|
if (!proof) {
|
|
2921
2958
|
await deferConnectedCommandClaim(
|
|
@@ -2989,6 +3026,23 @@ async function reconcileConnectedMachineBackgroundCommands(db, settings, observa
|
|
|
2989
3026
|
if (claims.length < CONNECTED_COMMAND_RECONCILIATION_LIMIT) break;
|
|
2990
3027
|
} while (Date.now() < deadline);
|
|
2991
3028
|
}
|
|
3029
|
+
async function replayConnectedCommandOutput(client, opId, terminalKnown, capture) {
|
|
3030
|
+
let capturedThrough = 0n;
|
|
3031
|
+
while (true) {
|
|
3032
|
+
const before = capturedThrough;
|
|
3033
|
+
const replay = await client.readExisting(opId, terminalKnown ? 5e3 : 250, async (frames) => {
|
|
3034
|
+
await capture(frames);
|
|
3035
|
+
for (const frame of frames) {
|
|
3036
|
+
const sequence = BigInt(frame.sequence);
|
|
3037
|
+
if (sequence > capturedThrough) capturedThrough = sequence;
|
|
3038
|
+
}
|
|
3039
|
+
});
|
|
3040
|
+
if (!terminalKnown || replay.status === "completed" || replay.terminal) return;
|
|
3041
|
+
if (capturedThrough === before) {
|
|
3042
|
+
throw new Error("Connected command terminal output replay has not reached its exit frontier");
|
|
3043
|
+
}
|
|
3044
|
+
}
|
|
3045
|
+
}
|
|
2992
3046
|
async function probeConnectedMachineBackgroundCommand(claim, controlRpc, controlTimeoutMs, observedAt = /* @__PURE__ */ new Date()) {
|
|
2993
3047
|
const input = {
|
|
2994
3048
|
controlRpc,
|
|
@@ -3079,6 +3133,40 @@ async function reconcileTerminalRetainedProcesses(db, settings, observability, p
|
|
|
3079
3133
|
let process = claim.process;
|
|
3080
3134
|
const expected = retainedProcessSettlementIdentity(process);
|
|
3081
3135
|
let proof = retainedProcessReconciliationProof(process);
|
|
3136
|
+
const processScope = {
|
|
3137
|
+
accountId: process.accountId,
|
|
3138
|
+
workspaceId: process.workspaceId,
|
|
3139
|
+
sessionId: process.sessionId,
|
|
3140
|
+
processId: process.id
|
|
3141
|
+
};
|
|
3142
|
+
const storedCommandPersistence = retainedProviderCommandPersistence(
|
|
3143
|
+
db,
|
|
3144
|
+
processScope,
|
|
3145
|
+
bus ? (events) => bus.publish(process.workspaceId, process.sessionId, events) : void 0
|
|
3146
|
+
);
|
|
3147
|
+
const commandPersistence = {
|
|
3148
|
+
...storedCommandPersistence,
|
|
3149
|
+
requestCancellation: async (reason) => {
|
|
3150
|
+
if (reason === "provider_deadline") {
|
|
3151
|
+
await requestRetainedProcessDeadlineCancellation(db, processScope);
|
|
3152
|
+
if (!await storedCommandPersistence.cancellationRequested())
|
|
3153
|
+
throw new Error(
|
|
3154
|
+
"Supervised deadline cancellation no longer owns its original rotating lease"
|
|
3155
|
+
);
|
|
3156
|
+
} else await storedCommandPersistence.requestCancellation(reason);
|
|
3157
|
+
}
|
|
3158
|
+
};
|
|
3159
|
+
if (proof && process.providerBackend === "modal") {
|
|
3160
|
+
try {
|
|
3161
|
+
const command = await commandPersistence.load();
|
|
3162
|
+
if (command?.kind === "modal-router-v1" && command.supervision && (!await commandPersistence.loadSupervisionReceipt() || ![command.streams.stdout, command.streams.stderr].every(
|
|
3163
|
+
(stream) => stream.eof && stream.exitCode === 0
|
|
3164
|
+
)))
|
|
3165
|
+
proof = null;
|
|
3166
|
+
} catch {
|
|
3167
|
+
proof = null;
|
|
3168
|
+
}
|
|
3169
|
+
}
|
|
3082
3170
|
if (!proof) {
|
|
3083
3171
|
let observation = null;
|
|
3084
3172
|
if (process.providerBackend === "modal" && process.routeTargetId === null && !process.providerBindingKey) {
|
|
@@ -3162,6 +3250,19 @@ async function reconcileTerminalRetainedProcesses(db, settings, observability, p
|
|
|
3162
3250
|
}
|
|
3163
3251
|
} else {
|
|
3164
3252
|
try {
|
|
3253
|
+
const command = await commandPersistence.load();
|
|
3254
|
+
const supervised = command?.kind === "modal-router-v1" && Boolean(command.supervision);
|
|
3255
|
+
const supervisionMetric = (outcome) => observability.incrementCounter({
|
|
3256
|
+
name: "opengeni_command_supervision_total",
|
|
3257
|
+
help: "Native retained command supervision reconciliation outcomes.",
|
|
3258
|
+
labels: { outcome }
|
|
3259
|
+
});
|
|
3260
|
+
if (supervised && (lease.rotationReason === "provider_deadline" || claim.ownerState === "background_stopping")) {
|
|
3261
|
+
await commandPersistence.requestCancellation(
|
|
3262
|
+
lease.rotationReason === "provider_deadline" ? "provider_deadline" : "explicit_stop"
|
|
3263
|
+
);
|
|
3264
|
+
supervisionMetric("cancellation_intent");
|
|
3265
|
+
}
|
|
3165
3266
|
observation = await probe(
|
|
3166
3267
|
settings,
|
|
3167
3268
|
lease,
|
|
@@ -3183,13 +3284,17 @@ async function reconcileTerminalRetainedProcesses(db, settings, observability, p
|
|
|
3183
3284
|
if (events.length && bus)
|
|
3184
3285
|
await bus.publish(process.workspaceId, process.sessionId, events).catch(() => void 0);
|
|
3185
3286
|
},
|
|
3186
|
-
|
|
3187
|
-
accountId: process.accountId,
|
|
3188
|
-
workspaceId: process.workspaceId,
|
|
3189
|
-
sessionId: process.sessionId,
|
|
3190
|
-
processId: process.id
|
|
3191
|
-
})
|
|
3287
|
+
commandPersistence
|
|
3192
3288
|
);
|
|
3289
|
+
if (supervised) {
|
|
3290
|
+
supervisionMetric(
|
|
3291
|
+
await commandPersistence.loadSupervisionReceipt() ? "proof_retained" : "proof_missing"
|
|
3292
|
+
);
|
|
3293
|
+
if (observation.status === "deferred")
|
|
3294
|
+
supervisionMetric(
|
|
3295
|
+
observation.reason === "provider_running" ? "checkpoint_blocked" : "provider_failure"
|
|
3296
|
+
);
|
|
3297
|
+
}
|
|
3193
3298
|
} catch (error) {
|
|
3194
3299
|
observability.warn("sandbox reaper: retained-process provider probe failed", {
|
|
3195
3300
|
processId: process.id,
|
|
@@ -3248,10 +3353,7 @@ async function reconcileTerminalRetainedProcesses(db, settings, observability, p
|
|
|
3248
3353
|
recordRetainedProcessReconciliation(observability, `proof_${proof.outcome}`);
|
|
3249
3354
|
} catch (error) {
|
|
3250
3355
|
recordRetainedProcessReconciliation(observability, "proof_checkpoint_failed");
|
|
3251
|
-
observability
|
|
3252
|
-
processId: process.id,
|
|
3253
|
-
error: error instanceof Error ? error.message : String(error)
|
|
3254
|
-
});
|
|
3356
|
+
warnRetainedProcessProofFailure(observability, error, process);
|
|
3255
3357
|
continue;
|
|
3256
3358
|
}
|
|
3257
3359
|
}
|
|
@@ -3377,7 +3479,7 @@ async function captureRetainedProbeOutput(processId, result, capture) {
|
|
|
3377
3479
|
pendingRetainedProbeOutput.delete(processId);
|
|
3378
3480
|
}
|
|
3379
3481
|
async function probeRetainedProcessAtProvider(settings, lease, process, mode = "observe", captureOutput, providerPersistence) {
|
|
3380
|
-
if (lease.id !== process.leaseId || lease.sandboxGroupId !== process.sandboxGroupId || lease.leaseEpoch !== process.leaseEpoch || lease.backend !== process.providerBackend || lease.instanceId !== process.providerInstanceId || lease.resumeBackendId !== process.providerBackend || process.routeTargetId !== null) {
|
|
3482
|
+
if (lease.id !== process.leaseId || lease.sandboxGroupId !== process.sandboxGroupId || lease.leaseEpoch !== process.leaseEpoch || lease.backend !== process.providerBackend || lease.instanceId !== process.providerInstanceId || !lease.resumeBackendId || sandboxBackendForSdkBackendId(lease.resumeBackendId) !== process.providerBackend || process.routeTargetId !== null) {
|
|
3381
3483
|
return { status: "deferred", reason: "identity_mismatch" };
|
|
3382
3484
|
}
|
|
3383
3485
|
if (!lease.resumeState) {
|
|
@@ -3390,7 +3492,7 @@ async function probeRetainedProcessAtProvider(settings, lease, process, mode = "
|
|
|
3390
3492
|
return classifyRetainedProcessPollResult(pending.result, process.providerSessionId);
|
|
3391
3493
|
}
|
|
3392
3494
|
const envelopeBackend = lease.resumeState.backendId;
|
|
3393
|
-
if (envelopeBackend !== void 0 && envelopeBackend !== process.providerBackend) {
|
|
3495
|
+
if (envelopeBackend !== void 0 && (typeof envelopeBackend !== "string" || sandboxBackendForSdkBackendId(envelopeBackend) !== process.providerBackend)) {
|
|
3394
3496
|
return { status: "deferred", reason: "identity_mismatch" };
|
|
3395
3497
|
}
|
|
3396
3498
|
if (sandboxProviderInstanceIdFromEnvelope(lease.resumeState) !== process.providerInstanceId) {
|
|
@@ -3418,7 +3520,7 @@ async function probeRetainedProcessAtProvider(settings, lease, process, mode = "
|
|
|
3418
3520
|
} catch {
|
|
3419
3521
|
return { status: "deferred", reason: "provider_error" };
|
|
3420
3522
|
}
|
|
3421
|
-
if (!client || client.backendId !== process.providerBackend || !client.resume) {
|
|
3523
|
+
if (!client || sandboxBackendForSdkBackendId(client.backendId) !== process.providerBackend || !client.resume) {
|
|
3422
3524
|
return { status: "deferred", reason: "backend_unsupported" };
|
|
3423
3525
|
}
|
|
3424
3526
|
const envelopeSessionState = lease.resumeState.sessionState ?? lease.resumeState;
|
|
@@ -3502,6 +3604,11 @@ async function probeRetainedProcessAtProvider(settings, lease, process, mode = "
|
|
|
3502
3604
|
return;
|
|
3503
3605
|
}
|
|
3504
3606
|
const page = session.getProviderCommandOutput?.(value);
|
|
3607
|
+
if (page?.command.kind === "modal-router-v1" && typeof value === "string") {
|
|
3608
|
+
if (!session.captureCommandOutput || !await session.captureCommandOutput(value))
|
|
3609
|
+
throw new Error("Byte-offset output requires atomic capture before settlement");
|
|
3610
|
+
return;
|
|
3611
|
+
}
|
|
3505
3612
|
if (page) {
|
|
3506
3613
|
for (const chunk of page.chunks)
|
|
3507
3614
|
if (chunk.text)
|
|
@@ -3513,10 +3620,14 @@ async function probeRetainedProcessAtProvider(settings, lease, process, mode = "
|
|
|
3513
3620
|
};
|
|
3514
3621
|
let result;
|
|
3515
3622
|
try {
|
|
3623
|
+
const supervisedCancelled = mode === "cancel" || lease.rotationReason === "provider_deadline" ? await session.cancelSupervisedCommand?.(
|
|
3624
|
+
process.providerSessionId,
|
|
3625
|
+
lease.rotationReason === "provider_deadline" ? "provider_deadline" : "explicit_stop"
|
|
3626
|
+
) ?? false : false;
|
|
3516
3627
|
result = await withRetainedProcessProbeTimeout(
|
|
3517
3628
|
session.writeStdin({
|
|
3518
3629
|
sessionId: process.providerSessionId,
|
|
3519
|
-
chars: mode === "cancel" ? "" : "",
|
|
3630
|
+
chars: mode === "cancel" && !supervisedCancelled ? "" : "",
|
|
3520
3631
|
yieldTimeMs: 1e3,
|
|
3521
3632
|
maxOutputTokens: 2e3
|
|
3522
3633
|
})
|
|
@@ -3542,7 +3653,7 @@ async function probeRetainedProcessAtProvider(settings, lease, process, mode = "
|
|
|
3542
3653
|
}
|
|
3543
3654
|
await capturePage(result);
|
|
3544
3655
|
const observation = classifyRetainedProcessPollResult(result, process.providerSessionId, session);
|
|
3545
|
-
if (observation.status === "deferred" && observation.reason === "provider_running" && lease.rotationRequestedAt !== null) {
|
|
3656
|
+
if (observation.status === "deferred" && observation.reason === "provider_running" && lease.rotationRequestedAt !== null && !await providerPersistence?.load().then((command) => command?.kind === "modal-router-v1" && command.supervision)) {
|
|
3546
3657
|
try {
|
|
3547
3658
|
const interrupted = await withRetainedProcessProbeTimeout(
|
|
3548
3659
|
session.writeStdin({
|
|
@@ -4118,6 +4229,16 @@ async function terminateDrainableBox(db, settings, row, observability, terminate
|
|
|
4118
4229
|
}
|
|
4119
4230
|
return result;
|
|
4120
4231
|
};
|
|
4232
|
+
if (!providerMissingBeforeCapture && backend === "modal" && lease.instanceId && !await readWorkspaceArchiveCapturePreflight(db, {
|
|
4233
|
+
accountId,
|
|
4234
|
+
workspaceId: row.workspaceId,
|
|
4235
|
+
sandboxGroupId: row.sandboxGroupId,
|
|
4236
|
+
expectedEpoch: row.leaseEpoch,
|
|
4237
|
+
expectedInstanceId: lease.instanceId,
|
|
4238
|
+
liveness: "draining"
|
|
4239
|
+
})) {
|
|
4240
|
+
return false;
|
|
4241
|
+
}
|
|
4121
4242
|
const termination = providerMissingBeforeCapture ? { terminated: true, providerMissingBeforeCapture: true } : await terminateBox(
|
|
4122
4243
|
settings,
|
|
4123
4244
|
lease,
|
|
@@ -4137,7 +4258,8 @@ async function terminateDrainableBox(db, settings, row, observability, terminate
|
|
|
4137
4258
|
expectedEpoch: row.leaseEpoch,
|
|
4138
4259
|
expectedInstanceId: lease.instanceId
|
|
4139
4260
|
});
|
|
4140
|
-
}
|
|
4261
|
+
},
|
|
4262
|
+
row.workspaceId
|
|
4141
4263
|
);
|
|
4142
4264
|
const terminated = typeof termination === "boolean" ? termination : termination.terminated;
|
|
4143
4265
|
if (!terminated) {
|
|
@@ -4193,18 +4315,20 @@ function providerDrainLogIdentity(lease, backend) {
|
|
|
4193
4315
|
instanceId: lease.instanceId
|
|
4194
4316
|
};
|
|
4195
4317
|
}
|
|
4196
|
-
async function terminateProviderBox(settings, lease, observability, persistArchive, createClientForBackend = createSandboxClientForBackend, terminateModalById = terminateModalSandboxById, providerCaptureRequestId, captureDisposition = "capture_required", claimedCapturePolicy, diskBackedArchives = false, releaseFailedCapture) {
|
|
4318
|
+
async function terminateProviderBox(settings, lease, observability, persistArchive, createClientForBackend = createSandboxClientForBackend, terminateModalById = terminateModalSandboxById, providerCaptureRequestId, captureDisposition = "capture_required", claimedCapturePolicy, diskBackedArchives = false, releaseFailedCapture, workspaceId) {
|
|
4197
4319
|
const durableBackendId = lease.resumeBackendId ?? lease.backend;
|
|
4198
4320
|
const backend = sandboxBackendForSdkBackendId(durableBackendId) ?? durableBackendId;
|
|
4199
4321
|
const logIdentity = providerDrainLogIdentity(lease, backend);
|
|
4322
|
+
const warnCaptureFailure = (message, error) => warnDrainSnapshotFailure(observability, message, error, {
|
|
4323
|
+
sandboxGroupId: lease.sandboxGroupId,
|
|
4324
|
+
leaseEpoch: lease.leaseEpoch,
|
|
4325
|
+
...workspaceId ? { workspaceId } : {}
|
|
4326
|
+
});
|
|
4200
4327
|
const releaseAfterCaptureFailure = async () => {
|
|
4201
4328
|
try {
|
|
4202
4329
|
await releaseFailedCapture?.();
|
|
4203
4330
|
} catch (error) {
|
|
4204
|
-
|
|
4205
|
-
...logIdentity,
|
|
4206
|
-
error: error instanceof Error ? error.message : String(error)
|
|
4207
|
-
});
|
|
4331
|
+
warnCaptureFailure("sandbox reaper: failed capture claim release failed", error);
|
|
4208
4332
|
}
|
|
4209
4333
|
};
|
|
4210
4334
|
if (!backend || backend === "none") {
|
|
@@ -4359,26 +4483,17 @@ async function terminateProviderBox(settings, lease, observability, persistArchi
|
|
|
4359
4483
|
}
|
|
4360
4484
|
);
|
|
4361
4485
|
} catch (error) {
|
|
4362
|
-
|
|
4363
|
-
...logIdentity,
|
|
4364
|
-
error: error instanceof Error ? error.message : String(error)
|
|
4365
|
-
});
|
|
4486
|
+
warnCaptureFailure("sandbox reaper: late workspace capture publication failed", error);
|
|
4366
4487
|
} finally {
|
|
4367
4488
|
await disposeWorkspaceArchive(archive);
|
|
4368
4489
|
}
|
|
4369
4490
|
},
|
|
4370
4491
|
observeLatePublicationFailure: (error) => {
|
|
4371
|
-
|
|
4372
|
-
...logIdentity,
|
|
4373
|
-
error: error instanceof Error ? error.message : String(error)
|
|
4374
|
-
});
|
|
4492
|
+
warnCaptureFailure("sandbox reaper: late capture publication cleanup failed", error);
|
|
4375
4493
|
},
|
|
4376
4494
|
observeLateFailure: (error) => {
|
|
4377
4495
|
void releaseAfterCaptureFailure();
|
|
4378
|
-
|
|
4379
|
-
...logIdentity,
|
|
4380
|
-
error: error instanceof Error ? error.message : String(error)
|
|
4381
|
-
});
|
|
4496
|
+
warnCaptureFailure("sandbox reaper: timed-out provider capture later failed", error);
|
|
4382
4497
|
}
|
|
4383
4498
|
});
|
|
4384
4499
|
}
|
|
@@ -4389,12 +4504,9 @@ async function terminateProviderBox(settings, lease, observability, persistArchi
|
|
|
4389
4504
|
});
|
|
4390
4505
|
return { terminated: true, providerMissingBeforeCapture: true };
|
|
4391
4506
|
}
|
|
4392
|
-
|
|
4507
|
+
warnCaptureFailure(
|
|
4393
4508
|
"sandbox reaper: persistWorkspace failed \u2014 leaving box draining (files NOT lost)",
|
|
4394
|
-
|
|
4395
|
-
...logIdentity,
|
|
4396
|
-
error: error instanceof Error ? error.message : String(error)
|
|
4397
|
-
}
|
|
4509
|
+
error
|
|
4398
4510
|
);
|
|
4399
4511
|
if (!(error instanceof SandboxProviderCaptureTimeoutError)) {
|
|
4400
4512
|
await releaseAfterCaptureFailure();
|
|
@@ -4467,7 +4579,6 @@ import {
|
|
|
4467
4579
|
TurnExecutionPolicyV1
|
|
4468
4580
|
} from "@opengeni/contracts";
|
|
4469
4581
|
import {
|
|
4470
|
-
defaultSessionMcpServerIds,
|
|
4471
4582
|
openGeniSlackBotMetadata,
|
|
4472
4583
|
requireOpenGeniSlackBotConnection,
|
|
4473
4584
|
resolveWorkspaceCatalogSettings as resolveWorkspaceCatalogSettings2,
|
|
@@ -4475,6 +4586,12 @@ import {
|
|
|
4475
4586
|
workspaceCustomModelReference,
|
|
4476
4587
|
lockActiveCustomModelForAdmission,
|
|
4477
4588
|
scheduledSlackBotConnectionId,
|
|
4589
|
+
freezeConnectionAccounts,
|
|
4590
|
+
ConnectionAccountSelectionError,
|
|
4591
|
+
scheduledConnectionSurfaceEligibility,
|
|
4592
|
+
scheduledConnectionTools,
|
|
4593
|
+
settingsWithEnabledCapabilityMcpServers,
|
|
4594
|
+
settingsWithSessionMcpServerMetadata,
|
|
4478
4595
|
swapActiveSandbox
|
|
4479
4596
|
} from "@opengeni/core";
|
|
4480
4597
|
import {
|
|
@@ -4489,7 +4606,6 @@ import {
|
|
|
4489
4606
|
getScheduledTaskRunAcceptedExecution,
|
|
4490
4607
|
getScheduledTaskRunByProducerKey,
|
|
4491
4608
|
getScheduledTargetSessionExecution,
|
|
4492
|
-
getScheduledTaskPersonalConnectionDelegations,
|
|
4493
4609
|
getScheduledTaskRunPersonalResourceAuthority,
|
|
4494
4610
|
getScheduledTaskPersonalResourceAuthoritySubject,
|
|
4495
4611
|
getScheduledTaskRevisionAuthority,
|
|
@@ -4505,7 +4621,6 @@ import {
|
|
|
4505
4621
|
isCodexBilledModel,
|
|
4506
4622
|
initializeSessionStartAtomically,
|
|
4507
4623
|
materializeScheduledTaskReusableSessionFromRun,
|
|
4508
|
-
listEnabledMcpCapabilityServerIds,
|
|
4509
4624
|
listInstalledApiIntegrationServerIdsForDelegations,
|
|
4510
4625
|
markScheduledTaskRunFailedIfQueued,
|
|
4511
4626
|
markScheduledTaskRunSkippedIfQueued,
|
|
@@ -4805,20 +4920,6 @@ function createScheduledTaskActivities(services) {
|
|
|
4805
4920
|
if (incidentDeclaration.action === "blocked") {
|
|
4806
4921
|
return incidentDeclaration;
|
|
4807
4922
|
}
|
|
4808
|
-
const taskPersonalConnectionDelegations = await getScheduledTaskPersonalConnectionDelegations(
|
|
4809
|
-
db,
|
|
4810
|
-
task.workspaceId,
|
|
4811
|
-
task.id
|
|
4812
|
-
);
|
|
4813
|
-
const taskConnectionAuthoritySubjects = [
|
|
4814
|
-
...new Set(
|
|
4815
|
-
taskPersonalConnectionDelegations.map((delegation) => delegation.ownerSubjectId)
|
|
4816
|
-
)
|
|
4817
|
-
];
|
|
4818
|
-
if (taskConnectionAuthoritySubjects.length > 1) {
|
|
4819
|
-
throw new Error("scheduled connection authority has multiple causal humans");
|
|
4820
|
-
}
|
|
4821
|
-
const taskConnectionAuthoritySubjectId = taskConnectionAuthoritySubjects[0] ?? null;
|
|
4822
4923
|
const taskPersonalResourceAuthoritySubjectId = await getScheduledTaskPersonalResourceAuthoritySubject(db, {
|
|
4823
4924
|
accountId: task.accountId,
|
|
4824
4925
|
workspaceId: task.workspaceId,
|
|
@@ -4831,10 +4932,12 @@ function createScheduledTaskActivities(services) {
|
|
|
4831
4932
|
taskId: task.id,
|
|
4832
4933
|
taskAuthorityRevision: task.authorityRevision
|
|
4833
4934
|
});
|
|
4834
|
-
|
|
4835
|
-
|
|
4935
|
+
const taskAuthoritySubjectId = task.ownerSubjectId;
|
|
4936
|
+
if (task.action.kind === "agent_turn" && ((taskRevisionAuthority?.subjectId ?? null) !== taskAuthoritySubjectId || [taskPersonalResourceAuthoritySubjectId].some(
|
|
4937
|
+
(subject) => subject !== null && subject !== taskAuthoritySubjectId
|
|
4938
|
+
))) {
|
|
4939
|
+
throw new Error("scheduled authority differs from its immutable execution owner");
|
|
4836
4940
|
}
|
|
4837
|
-
const taskAuthoritySubjectId = taskRevisionAuthority?.subjectId ?? taskPersonalResourceAuthoritySubjectId ?? taskConnectionAuthoritySubjectId;
|
|
4838
4941
|
const acceptedTargetSessionId = task.runMode === "existing_session" ? task.targetSessionId : task.runMode === "reusable_session" ? task.reusableSessionId : null;
|
|
4839
4942
|
const targetSessionExecutionBase = acceptedTargetSessionId ? await getScheduledTargetSessionExecution(
|
|
4840
4943
|
db,
|
|
@@ -4851,6 +4954,50 @@ function createScheduledTaskActivities(services) {
|
|
|
4851
4954
|
const creatorPolicy = await getScheduledTaskCreatorPolicy(db, task.workspaceId, task.id);
|
|
4852
4955
|
const firstPartyMcpTools = creatorPolicy?.firstPartyMcpTools ? allowedFirstPartyMcpToolsForSession(settings, creatorPolicy.firstPartyMcpTools) : resolveFirstPartyMcpToolPolicy(settings).default;
|
|
4853
4956
|
const firstPartyMcpPermissions = creatorPolicy?.firstPartyMcpPermissions ? [...creatorPolicy.firstPartyMcpPermissions] : [...DEFAULT_FIRST_PARTY_MCP_PERMISSIONS];
|
|
4957
|
+
const connectionSettings = await settingsWithEnabledCapabilityMcpServers(
|
|
4958
|
+
db,
|
|
4959
|
+
task.workspaceId,
|
|
4960
|
+
settings,
|
|
4961
|
+
taskAuthoritySubjectId ? { subjectId: taskAuthoritySubjectId } : {}
|
|
4962
|
+
);
|
|
4963
|
+
const connectionTarget = acceptedTargetSessionId && targetSessionExecutionBase ? await requireSession(db, task.workspaceId, acceptedTargetSessionId) : null;
|
|
4964
|
+
const connectionTools = await scheduledConnectionTools(
|
|
4965
|
+
db,
|
|
4966
|
+
task.workspaceId,
|
|
4967
|
+
connectionSettings,
|
|
4968
|
+
connectionTarget,
|
|
4969
|
+
taskTools,
|
|
4970
|
+
taskAuthoritySubjectId ?? void 0
|
|
4971
|
+
);
|
|
4972
|
+
const taskConnections = await freezeConnectionAccounts({
|
|
4973
|
+
db,
|
|
4974
|
+
accountId: task.accountId,
|
|
4975
|
+
workspaceId: task.workspaceId,
|
|
4976
|
+
settings: connectionTarget ? settingsWithSessionMcpServerMetadata(connectionSettings, connectionTarget.mcpServers) : connectionSettings,
|
|
4977
|
+
tools: connectionTools,
|
|
4978
|
+
resources: connectionTarget?.resources ?? task.agentConfig.resources,
|
|
4979
|
+
source: taskAuthoritySubjectId ? { kind: "subject", subjectId: taskAuthoritySubjectId, accountId: task.accountId } : { kind: "none" },
|
|
4980
|
+
authoritySelections: task.agentConfig.connectionAccounts ?? [],
|
|
4981
|
+
authoritySelectionsFrozen: task.agentConfig.connectionAccountsFrozen === true,
|
|
4982
|
+
...scheduledConnectionSurfaceEligibility(
|
|
4983
|
+
settings,
|
|
4984
|
+
connectionTarget ?? {
|
|
4985
|
+
firstPartyMcpTools,
|
|
4986
|
+
firstPartyMcpPermissions
|
|
4987
|
+
}
|
|
4988
|
+
)
|
|
4989
|
+
}).catch((error) => {
|
|
4990
|
+
if (error instanceof ConnectionAccountSelectionError) return null;
|
|
4991
|
+
throw error;
|
|
4992
|
+
});
|
|
4993
|
+
if (taskConnections === null) {
|
|
4994
|
+
return { action: "blocked", reason: "connection_account_unavailable" };
|
|
4995
|
+
}
|
|
4996
|
+
const {
|
|
4997
|
+
personalConnectionDelegations: taskPersonalConnectionDelegations,
|
|
4998
|
+
mcpAccountBindings: taskMcpAccountBindings
|
|
4999
|
+
} = taskConnections;
|
|
5000
|
+
const taskConnectionAuthoritySubjectId = taskPersonalConnectionDelegations.length > 0 ? taskAuthoritySubjectId : null;
|
|
4854
5001
|
const creatorSessionPolicy = scheduledCreatorSessionPolicyInput(
|
|
4855
5002
|
creatorPolicy?.sessionPolicy ?? null
|
|
4856
5003
|
);
|
|
@@ -4898,20 +5045,15 @@ function createScheduledTaskActivities(services) {
|
|
|
4898
5045
|
};
|
|
4899
5046
|
})() : null;
|
|
4900
5047
|
const targetSessionExecution = targetSessionExecutionBase ? await (async () => {
|
|
4901
|
-
const
|
|
4902
|
-
|
|
4903
|
-
|
|
4904
|
-
|
|
4905
|
-
task.workspaceId,
|
|
4906
|
-
taskPersonalConnectionDelegations
|
|
4907
|
-
)
|
|
4908
|
-
]);
|
|
4909
|
-
const workspaceDefaultMcpServerIds = new Set(
|
|
4910
|
-
settings.mcpServers.map((server) => server.id)
|
|
5048
|
+
const apiIntegrationServerIds = await listInstalledApiIntegrationServerIdsForDelegations(
|
|
5049
|
+
db,
|
|
5050
|
+
task.workspaceId,
|
|
5051
|
+
taskPersonalConnectionDelegations
|
|
4911
5052
|
);
|
|
4912
|
-
|
|
4913
|
-
|
|
4914
|
-
|
|
5053
|
+
const availableMcpServerIds = /* @__PURE__ */ new Set([
|
|
5054
|
+
...connectionSettings.mcpServers.map((server) => server.id),
|
|
5055
|
+
...apiIntegrationServerIds
|
|
5056
|
+
]);
|
|
4915
5057
|
for (const id of targetSessionExecutionBase.mcpServerIds) {
|
|
4916
5058
|
availableMcpServerIds.add(id);
|
|
4917
5059
|
}
|
|
@@ -4919,9 +5061,10 @@ function createScheduledTaskActivities(services) {
|
|
|
4919
5061
|
toolPolicy: targetSessionExecutionBase.toolPolicy,
|
|
4920
5062
|
sessionTools: targetSessionExecutionBase.tools,
|
|
4921
5063
|
availableMcpServerIds,
|
|
4922
|
-
defaultMcpServerIds:
|
|
4923
|
-
|
|
4924
|
-
|
|
5064
|
+
defaultMcpServerIds: [
|
|
5065
|
+
...connectionTools.map((tool) => tool.id),
|
|
5066
|
+
...apiIntegrationServerIds
|
|
5067
|
+
]
|
|
4925
5068
|
});
|
|
4926
5069
|
return {
|
|
4927
5070
|
...targetSessionExecutionBase,
|
|
@@ -4958,7 +5101,7 @@ function createScheduledTaskActivities(services) {
|
|
|
4958
5101
|
task.rigId
|
|
4959
5102
|
) : null;
|
|
4960
5103
|
if (generatedTarget && task.rigId && (!acceptedRig || !acceptedRig.activeVersion)) {
|
|
4961
|
-
throw new Error(`
|
|
5104
|
+
throw new Error(`sandbox environment has no active version to bind: ${task.rigId}`);
|
|
4962
5105
|
}
|
|
4963
5106
|
const acceptedRigDefaultVariableSets = acceptedRig?.activeVersion ? await Promise.all(
|
|
4964
5107
|
acceptedRig.activeVersion.defaultVariableSetIds.map(async (variableSetId) => {
|
|
@@ -4972,7 +5115,9 @@ function createScheduledTaskActivities(services) {
|
|
|
4972
5115
|
variableSetId
|
|
4973
5116
|
);
|
|
4974
5117
|
if (!variableSet) {
|
|
4975
|
-
throw new Error(
|
|
5118
|
+
throw new Error(
|
|
5119
|
+
`sandbox environment default Variable Set not found: ${variableSetId}`
|
|
5120
|
+
);
|
|
4976
5121
|
}
|
|
4977
5122
|
return { id: variableSet.id, generation: variableSet.generation };
|
|
4978
5123
|
})
|
|
@@ -5130,6 +5275,7 @@ function createScheduledTaskActivities(services) {
|
|
|
5130
5275
|
targetSessionExecution,
|
|
5131
5276
|
generatedSessionBinding,
|
|
5132
5277
|
personalConnectionDelegations: taskPersonalConnectionDelegations,
|
|
5278
|
+
mcpAccountBindings: taskMcpAccountBindings,
|
|
5133
5279
|
personalResourceAuthoritySubjectId: taskPersonalResourceAuthoritySubjectId,
|
|
5134
5280
|
causalHumanSubjectId,
|
|
5135
5281
|
causalHumanAuthority: taskRevisionAuthority,
|
|
@@ -5243,13 +5389,7 @@ function createScheduledTaskActivities(services) {
|
|
|
5243
5389
|
taskId: task.id
|
|
5244
5390
|
}
|
|
5245
5391
|
);
|
|
5246
|
-
if (stableJson({
|
|
5247
|
-
task: exactAuthority.task,
|
|
5248
|
-
personalConnectionDelegations: exactAuthority.personalConnectionDelegations
|
|
5249
|
-
}) !== stableJson({
|
|
5250
|
-
task,
|
|
5251
|
-
personalConnectionDelegations: taskPersonalConnectionDelegations
|
|
5252
|
-
})) {
|
|
5392
|
+
if (stableJson(exactAuthority) !== stableJson(task)) {
|
|
5253
5393
|
throw new IncidentTelemetryPreflightBlockedError(
|
|
5254
5394
|
"incident_preflight_metadata_missing"
|
|
5255
5395
|
);
|
|
@@ -5270,14 +5410,16 @@ function createScheduledTaskActivities(services) {
|
|
|
5270
5410
|
if (task.rigId) {
|
|
5271
5411
|
const rig = acceptedRig;
|
|
5272
5412
|
if (!rig || !rig.activeVersion) {
|
|
5273
|
-
throw new Error(`
|
|
5413
|
+
throw new Error(`sandbox environment has no active version to bind: ${task.rigId}`);
|
|
5274
5414
|
}
|
|
5275
5415
|
frozenRigId = rig.id;
|
|
5276
5416
|
frozenRigVersionId = runPersonalResourceAuthority?.resources.find(
|
|
5277
5417
|
(resource) => resource.resourceKind === "rig" && resource.resourceId === rig.id
|
|
5278
5418
|
)?.resourceVersionId ?? rig.activeVersion.id;
|
|
5279
5419
|
if (frozenRigVersionId !== rig.activeVersion.id) {
|
|
5280
|
-
throw new Error(
|
|
5420
|
+
throw new Error(
|
|
5421
|
+
"scheduled run sandbox environment version changed during admission"
|
|
5422
|
+
);
|
|
5281
5423
|
}
|
|
5282
5424
|
}
|
|
5283
5425
|
let session;
|
|
@@ -5577,6 +5719,7 @@ function createScheduledTaskActivities(services) {
|
|
|
5577
5719
|
...taskXaiProviderAccountAuthoritySnapshot.scope === "user" && task.createdBy.kind === "subject" ? { xaiAuthoritySubjectId: task.createdBy.subjectId } : {}
|
|
5578
5720
|
},
|
|
5579
5721
|
personalConnectionDelegations: taskPersonalConnectionDelegations,
|
|
5722
|
+
mcpAccountBindings: taskMcpAccountBindings,
|
|
5580
5723
|
xaiProviderAccountAuthoritySnapshot: taskXaiProviderAccountAuthoritySnapshot,
|
|
5581
5724
|
scheduledTaskRunId: run.id
|
|
5582
5725
|
},
|
|
@@ -5686,6 +5829,7 @@ function createScheduledTaskActivities(services) {
|
|
|
5686
5829
|
...taskXaiProviderAccountAuthoritySnapshot.scope === "user" && task.createdBy.kind === "subject" ? { xaiAuthoritySubjectId: task.createdBy.subjectId } : {}
|
|
5687
5830
|
},
|
|
5688
5831
|
personalConnectionDelegations: taskPersonalConnectionDelegations,
|
|
5832
|
+
mcpAccountBindings: taskMcpAccountBindings,
|
|
5689
5833
|
xaiProviderAccountAuthoritySnapshot: taskXaiProviderAccountAuthoritySnapshot,
|
|
5690
5834
|
scheduledTaskRunId: run.id
|
|
5691
5835
|
},
|
|
@@ -5941,46 +6085,38 @@ function scheduledSessionRejectionError(rejectionReason) {
|
|
|
5941
6085
|
}
|
|
5942
6086
|
async function prepareIncidentTelemetrySource(input) {
|
|
5943
6087
|
const session = await requireSession(input.tx, input.workspaceId, input.sessionId);
|
|
5944
|
-
const { task, personalConnectionDelegations } = input.acceptedExecution
|
|
5945
|
-
task: input.acceptedExecution.task,
|
|
5946
|
-
personalConnectionDelegations: input.acceptedExecution.personalConnectionDelegations
|
|
5947
|
-
} : await requireScheduledTaskIncidentAuthorityInTransaction(input.tx, {
|
|
5948
|
-
workspaceId: input.workspaceId,
|
|
5949
|
-
taskId: input.taskId
|
|
5950
|
-
});
|
|
6088
|
+
const { task, personalConnectionDelegations } = input.acceptedExecution;
|
|
5951
6089
|
const responder = await resolveIncidentTelemetryResponderMetadata({
|
|
5952
6090
|
db: input.tx,
|
|
5953
6091
|
settings: input.settings,
|
|
5954
6092
|
task,
|
|
5955
6093
|
session,
|
|
5956
6094
|
personalConnectionDelegations,
|
|
5957
|
-
personalResourceAuthoritySubjectId: input.acceptedExecution
|
|
5958
|
-
|
|
5959
|
-
|
|
5960
|
-
|
|
5961
|
-
|
|
5962
|
-
|
|
5963
|
-
|
|
5964
|
-
|
|
5965
|
-
|
|
5966
|
-
|
|
5967
|
-
|
|
5968
|
-
|
|
5969
|
-
|
|
5970
|
-
|
|
5971
|
-
|
|
5972
|
-
|
|
5973
|
-
|
|
5974
|
-
|
|
5975
|
-
|
|
5976
|
-
|
|
5977
|
-
|
|
5978
|
-
|
|
5979
|
-
|
|
5980
|
-
|
|
5981
|
-
|
|
5982
|
-
}
|
|
5983
|
-
} : {}
|
|
6095
|
+
personalResourceAuthoritySubjectId: input.acceptedExecution.personalResourceAuthoritySubjectId ?? null,
|
|
6096
|
+
executionPolicy: input.acceptedExecution.targetSessionExecution ? {
|
|
6097
|
+
tools: input.acceptedExecution.targetSessionExecution.tools,
|
|
6098
|
+
firstPartyMcpTools: input.acceptedExecution.targetSessionExecution.firstPartyMcpTools,
|
|
6099
|
+
firstPartyMcpPermissions: input.acceptedExecution.targetSessionExecution.firstPartyMcpPermissions,
|
|
6100
|
+
variableSetIds: input.acceptedExecution.targetSessionExecution.variableSets.map(
|
|
6101
|
+
(variableSet) => variableSet.id
|
|
6102
|
+
),
|
|
6103
|
+
variableSetId: input.acceptedExecution.targetSessionExecution.variableSetId,
|
|
6104
|
+
rigId: input.acceptedExecution.targetSessionExecution.rigId,
|
|
6105
|
+
rigVersionId: input.acceptedExecution.targetSessionExecution.rigVersionId,
|
|
6106
|
+
toolPolicy: input.acceptedExecution.targetSessionExecution.toolPolicy,
|
|
6107
|
+
mcpServerIds: input.acceptedExecution.targetSessionExecution.mcpServerIds,
|
|
6108
|
+
toolPolicyVersion: input.acceptedExecution.targetSessionExecution.toolPolicyVersion
|
|
6109
|
+
} : {
|
|
6110
|
+
tools: input.acceptedExecution.resolvedTools,
|
|
6111
|
+
firstPartyMcpTools: input.acceptedExecution.resolvedFirstPartyMcpTools,
|
|
6112
|
+
firstPartyMcpPermissions: input.acceptedExecution.resolvedFirstPartyMcpPermissions,
|
|
6113
|
+
variableSetId: input.acceptedExecution.resolvedVariableSet?.id ?? null,
|
|
6114
|
+
rigId: input.acceptedExecution.resolvedRig?.id ?? null,
|
|
6115
|
+
rigVersionId: input.acceptedExecution.resolvedRig?.versionId ?? null,
|
|
6116
|
+
toolPolicy: session.toolPolicy,
|
|
6117
|
+
mcpServerIds: [],
|
|
6118
|
+
toolPolicyVersion: session.toolPolicyVersion
|
|
6119
|
+
}
|
|
5984
6120
|
});
|
|
5985
6121
|
const preflight = evaluateIncidentTelemetryPreflight({
|
|
5986
6122
|
agentConfig: task.agentConfig,
|
|
@@ -6370,6 +6506,7 @@ async function recoverBoundScheduledTaskDispatch(input) {
|
|
|
6370
6506
|
...input.acceptedExecution.xaiAuthoritySubjectId ? { xaiAuthoritySubjectId: input.acceptedExecution.xaiAuthoritySubjectId } : {}
|
|
6371
6507
|
},
|
|
6372
6508
|
personalConnectionDelegations: input.acceptedExecution.personalConnectionDelegations,
|
|
6509
|
+
mcpAccountBindings: input.acceptedExecution.mcpAccountBindings ?? null,
|
|
6373
6510
|
xaiProviderAccountAuthoritySnapshot: input.acceptedExecution.xaiProviderAccountAuthoritySnapshot,
|
|
6374
6511
|
scheduledTaskRunId: input.run.id
|
|
6375
6512
|
},
|
|
@@ -6766,6 +6903,7 @@ import {
|
|
|
6766
6903
|
applySessionTurnSettlement,
|
|
6767
6904
|
enqueueSessionWorkflowWake,
|
|
6768
6905
|
failSessionWorkBeforeAttemptClaim,
|
|
6906
|
+
blockSessionWorkBeforeAttemptClaim,
|
|
6769
6907
|
requestSessionTurnRecovery,
|
|
6770
6908
|
recoverSessionDispatch,
|
|
6771
6909
|
reconcileSessionAttemptQuiescence,
|
|
@@ -6782,12 +6920,14 @@ import {
|
|
|
6782
6920
|
settleSessionIdleWithParentOutbox
|
|
6783
6921
|
} from "@opengeni/db";
|
|
6784
6922
|
import { publishDurableSessionEvents as publishDurableSessionEvents2 } from "@opengeni/events";
|
|
6923
|
+
import { CancelledFailure } from "@temporalio/activity";
|
|
6785
6924
|
var WORKER_DEATH_MAX_REDISPATCHES = 3;
|
|
6786
6925
|
function createSessionStateActivities(services, overrides = {}) {
|
|
6787
6926
|
const settleSessionAttemptInterruptionsFn = overrides.settleSessionAttemptInterruptions ?? settleSessionAttemptInterruptions;
|
|
6788
6927
|
const applySessionTurnSettlementFn = overrides.applySessionTurnSettlement ?? applySessionTurnSettlement;
|
|
6789
6928
|
const enqueueSessionWorkflowWakeFn = overrides.enqueueSessionWorkflowWake ?? enqueueSessionWorkflowWake;
|
|
6790
6929
|
const failSessionWorkBeforeAttemptClaimFn = overrides.failSessionWorkBeforeAttemptClaim ?? failSessionWorkBeforeAttemptClaim;
|
|
6930
|
+
const blockSessionWorkBeforeAttemptClaimFn = overrides.blockSessionWorkBeforeAttemptClaim ?? blockSessionWorkBeforeAttemptClaim;
|
|
6791
6931
|
const requestSessionTurnRecoveryFn = overrides.requestSessionTurnRecovery ?? requestSessionTurnRecovery;
|
|
6792
6932
|
const recoverSessionDispatchFn = overrides.recoverSessionDispatch ?? recoverSessionDispatch;
|
|
6793
6933
|
const reconcileSessionAttemptQuiescenceFn = overrides.reconcileSessionAttemptQuiescence ?? reconcileSessionAttemptQuiescence;
|
|
@@ -6830,6 +6970,24 @@ function createSessionStateActivities(services, overrides = {}) {
|
|
|
6830
6970
|
});
|
|
6831
6971
|
if (attempt) return { action: "stale" };
|
|
6832
6972
|
const preClaimFailureDisposition = input.preClaimFailure?.disposition ?? input.preClaimFailureDisposition;
|
|
6973
|
+
if (preClaimFailureDisposition === "blocked" && input.admissionFence && input.preClaimFailure?.reason) {
|
|
6974
|
+
const blocked = await blockSessionWorkBeforeAttemptClaimFn(db, input.workspaceId, {
|
|
6975
|
+
accountId: input.accountId,
|
|
6976
|
+
sessionId: input.sessionId,
|
|
6977
|
+
workflowId,
|
|
6978
|
+
attemptId: input.attemptId,
|
|
6979
|
+
fence: input.admissionFence,
|
|
6980
|
+
reason: input.preClaimFailure.reason,
|
|
6981
|
+
sqlState: input.preClaimFailure.sqlState ?? null
|
|
6982
|
+
});
|
|
6983
|
+
await publishDurableSessionEventsFn(
|
|
6984
|
+
bus,
|
|
6985
|
+
input.workspaceId,
|
|
6986
|
+
input.sessionId,
|
|
6987
|
+
blocked.events
|
|
6988
|
+
);
|
|
6989
|
+
return { action: blocked.action };
|
|
6990
|
+
}
|
|
6833
6991
|
if (preClaimFailureDisposition === "permanent" && input.trigger) {
|
|
6834
6992
|
const failed = await failSessionWorkBeforeAttemptClaimFn(db, input.workspaceId, {
|
|
6835
6993
|
accountId: input.accountId,
|
|
@@ -6837,7 +6995,12 @@ function createSessionStateActivities(services, overrides = {}) {
|
|
|
6837
6995
|
workflowId,
|
|
6838
6996
|
trigger: input.trigger,
|
|
6839
6997
|
error: input.error ?? "Agent turn admission failed before attempt claim.",
|
|
6840
|
-
...input.preClaimFailure
|
|
6998
|
+
...input.preClaimFailure?.disposition === "permanent" ? {
|
|
6999
|
+
admissionFailure: {
|
|
7000
|
+
disposition: "permanent",
|
|
7001
|
+
code: input.preClaimFailure.code
|
|
7002
|
+
}
|
|
7003
|
+
} : {}
|
|
6841
7004
|
});
|
|
6842
7005
|
if (failed.action === "terminal") return { action: "terminal" };
|
|
6843
7006
|
if (failed.action === "stale") return { action: "stale" };
|
|
@@ -7091,8 +7254,39 @@ function createSessionStateActivities(services, overrides = {}) {
|
|
|
7091
7254
|
return { action: "recovering" };
|
|
7092
7255
|
}
|
|
7093
7256
|
async function peekSessionWork(input) {
|
|
7094
|
-
const { db, observability } = await services();
|
|
7095
|
-
const peek = await peekSessionWorkFn(
|
|
7257
|
+
const { db, observability, inspectSessionAttemptActivity } = await services();
|
|
7258
|
+
const peek = await peekSessionWorkFn(
|
|
7259
|
+
db,
|
|
7260
|
+
input.workspaceId,
|
|
7261
|
+
input.sessionId,
|
|
7262
|
+
input.includeAdmissionFence,
|
|
7263
|
+
input.observerAccountId
|
|
7264
|
+
);
|
|
7265
|
+
if (peek.kind === "unavailable") return peek;
|
|
7266
|
+
if (peek.kind === "attempt-owned") {
|
|
7267
|
+
let ownerActivityState = "unknown";
|
|
7268
|
+
if (inspectSessionAttemptActivity) {
|
|
7269
|
+
try {
|
|
7270
|
+
ownerActivityState = await inspectSessionAttemptActivity(peek.activityRef);
|
|
7271
|
+
} catch (error) {
|
|
7272
|
+
if (error instanceof CancelledFailure) throw error;
|
|
7273
|
+
if (currentActivityContext()?.cancellationSignal.aborted)
|
|
7274
|
+
throw new CancelledFailure("Control observation cancelled");
|
|
7275
|
+
}
|
|
7276
|
+
}
|
|
7277
|
+
if (currentActivityContext()?.cancellationSignal.aborted)
|
|
7278
|
+
throw new CancelledFailure("Control observation cancelled");
|
|
7279
|
+
const current = await peekSessionWorkFn(
|
|
7280
|
+
db,
|
|
7281
|
+
input.workspaceId,
|
|
7282
|
+
input.sessionId,
|
|
7283
|
+
input.includeAdmissionFence,
|
|
7284
|
+
input.observerAccountId
|
|
7285
|
+
);
|
|
7286
|
+
if (current.kind !== "attempt-owned" || current.turnId !== peek.turnId || current.attemptId !== peek.attemptId || current.executionGeneration !== peek.executionGeneration || current.activityRef.workflowId !== peek.activityRef.workflowId || current.activityRef.workflowRunId !== peek.activityRef.workflowRunId || current.activityRef.activityId !== peek.activityRef.activityId)
|
|
7287
|
+
return current;
|
|
7288
|
+
return { ...current, ownerActivityState };
|
|
7289
|
+
}
|
|
7096
7290
|
await refreshQueuedTurnsGauge(db, observability, countQueuedTurnsFn, recordTurnsQueuedGaugeFn);
|
|
7097
7291
|
return peek;
|
|
7098
7292
|
}
|
|
@@ -7173,6 +7367,7 @@ import {
|
|
|
7173
7367
|
getWorkspaceControlEvent
|
|
7174
7368
|
} from "@opengeni/db";
|
|
7175
7369
|
import { publishDurableWorkspaceControlEvent } from "@opengeni/events";
|
|
7370
|
+
import { recordWorkflowWakeReconciliation } from "@opengeni/observability";
|
|
7176
7371
|
var BATCH_SIZE = 1e3;
|
|
7177
7372
|
var MAX_DELIVERIES_PER_ACTIVITY = 1e4;
|
|
7178
7373
|
var MAX_TITLE_FANOUT_PER_ACTIVITY = 1e3;
|
|
@@ -7258,23 +7453,7 @@ function createWorkflowWakeActivities(services) {
|
|
|
7258
7453
|
pendingAdmissionBlockers,
|
|
7259
7454
|
exhaustedBatchLimit
|
|
7260
7455
|
};
|
|
7261
|
-
|
|
7262
|
-
service.observability.info("session workflow wake delivery reconciled", {
|
|
7263
|
-
claimed,
|
|
7264
|
-
signaled,
|
|
7265
|
-
delivered,
|
|
7266
|
-
pendingAdmission,
|
|
7267
|
-
unconfirmed,
|
|
7268
|
-
failed,
|
|
7269
|
-
exhaustedBatchLimit,
|
|
7270
|
-
...Object.fromEntries(
|
|
7271
|
-
Object.entries(pendingAdmissionBlockers).map(([blocker, count]) => [
|
|
7272
|
-
`pendingAdmissionBlockers.${blocker}`,
|
|
7273
|
-
count
|
|
7274
|
-
])
|
|
7275
|
-
)
|
|
7276
|
-
});
|
|
7277
|
-
}
|
|
7456
|
+
recordWorkflowWakeReconciliation(service.observability, result);
|
|
7278
7457
|
return result;
|
|
7279
7458
|
}
|
|
7280
7459
|
};
|
|
@@ -7319,4 +7498,4 @@ export {
|
|
|
7319
7498
|
createControlActivities,
|
|
7320
7499
|
createControlActivitiesFromServices
|
|
7321
7500
|
};
|
|
7322
|
-
//# sourceMappingURL=activities-control-
|
|
7501
|
+
//# sourceMappingURL=activities-control-BOLIY3H4.js.map
|