@opengeni/worker-bundle 0.26.0-canary.6 → 0.26.0-canary.7
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/goals.d.ts +0 -1
- package/dist/{activities-control-SHMDOQWS.js → activities-control-VMA3XMHE.js} +45 -8
- package/dist/{activities-control-SHMDOQWS.js.map → activities-control-VMA3XMHE.js.map} +1 -1
- package/dist/{activities-turn-GHSFZB64.js → activities-turn-57AOUNYN.js} +64 -13
- package/dist/activities-turn-57AOUNYN.js.map +1 -0
- package/dist/{chunk-O2LQWJIK.js → chunk-7LS42PHP.js} +4 -8
- package/dist/chunk-7LS42PHP.js.map +1 -0
- package/dist/index.js +1 -1
- package/package.json +17 -17
- package/src/activities/agent-turn/codex-capacity.ts +18 -3
- package/src/activities/agent-turn/run.ts +8 -0
- package/src/activities/agent-turn/tool-environment.ts +9 -0
- package/src/activities/agent-turn/xai-capacity.ts +17 -0
- package/src/activities/capabilities.ts +16 -3
- package/src/activities/goals.ts +5 -7
- package/src/activities/scheduled-tasks.ts +77 -8
- package/dist/activities-turn-GHSFZB64.js.map +0 -1
- package/dist/chunk-O2LQWJIK.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -781,7 +781,7 @@ function temporalWorkflowExecutionNotFound(error) {
|
|
|
781
781
|
return isGrpcServiceError(error) && error.code === 5;
|
|
782
782
|
}
|
|
783
783
|
async function createDefaultWorkerActivities(role, dependencies = {}) {
|
|
784
|
-
return role === "control" ? (await import("./activities-control-
|
|
784
|
+
return role === "control" ? (await import("./activities-control-VMA3XMHE.js")).createControlActivities(dependencies) : (await import("./activities-turn-57AOUNYN.js")).createTurnActivities(dependencies);
|
|
785
785
|
}
|
|
786
786
|
function resolveOpenGeniWorkflowDefinition(moduleUrl = import.meta.url) {
|
|
787
787
|
const modulePath = fileURLToPath(moduleUrl).replaceAll("\\", "/");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengeni/worker-bundle",
|
|
3
|
-
"version": "0.26.0-canary.
|
|
3
|
+
"version": "0.26.0-canary.7",
|
|
4
4
|
"description": "OpenGeni worker entry and reusable embedded lifecycle, shipped with a release-coherent pre-bundled Temporal workflow artifact.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -54,22 +54,22 @@
|
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
56
|
"@llamaindex/liteparse": "2.14.2",
|
|
57
|
-
"@opengeni/agent-proto": "^0.5.1-canary.
|
|
58
|
-
"@opengeni/capabilities": "^0.3.2-canary.
|
|
59
|
-
"@opengeni/codemode": "^0.4.27-canary.
|
|
60
|
-
"@opengeni/codex": "^0.2.21-canary.
|
|
61
|
-
"@opengeni/config": "^1.0.0-canary.
|
|
62
|
-
"@opengeni/contracts": "^2.13.0-canary.
|
|
63
|
-
"@opengeni/core": "^2.7.5-canary.
|
|
64
|
-
"@opengeni/db": "^4.0.0-canary.
|
|
65
|
-
"@opengeni/documents": "^0.8.19-canary.
|
|
66
|
-
"@opengeni/events": "^0.4.17-canary.
|
|
67
|
-
"@opengeni/github": "^0.7.3-canary.
|
|
68
|
-
"@opengeni/network": "^0.3.0-canary.
|
|
69
|
-
"@opengeni/observability": "^0.8.19-canary.
|
|
70
|
-
"@opengeni/runtime": "^2.3.0-canary.
|
|
71
|
-
"@opengeni/storage": "^0.2.120-canary.
|
|
72
|
-
"@opengeni/xai-subscription": "^0.1.3-canary.
|
|
57
|
+
"@opengeni/agent-proto": "^0.5.1-canary.17",
|
|
58
|
+
"@opengeni/capabilities": "^0.3.2-canary.8",
|
|
59
|
+
"@opengeni/codemode": "^0.4.27-canary.7",
|
|
60
|
+
"@opengeni/codex": "^0.2.21-canary.7",
|
|
61
|
+
"@opengeni/config": "^1.0.0-canary.7",
|
|
62
|
+
"@opengeni/contracts": "^2.13.0-canary.8",
|
|
63
|
+
"@opengeni/core": "^2.7.5-canary.7",
|
|
64
|
+
"@opengeni/db": "^4.0.0-canary.7",
|
|
65
|
+
"@opengeni/documents": "^0.8.19-canary.7",
|
|
66
|
+
"@opengeni/events": "^0.4.17-canary.7",
|
|
67
|
+
"@opengeni/github": "^0.7.3-canary.7",
|
|
68
|
+
"@opengeni/network": "^0.3.0-canary.8",
|
|
69
|
+
"@opengeni/observability": "^0.8.19-canary.7",
|
|
70
|
+
"@opengeni/runtime": "^2.3.0-canary.7",
|
|
71
|
+
"@opengeni/storage": "^0.2.120-canary.7",
|
|
72
|
+
"@opengeni/xai-subscription": "^0.1.3-canary.7",
|
|
73
73
|
"@temporalio/activity": "^1.17.0",
|
|
74
74
|
"@temporalio/client": "^1.17.0",
|
|
75
75
|
"@temporalio/worker": "^1.17.0",
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
connectionModelAllowed,
|
|
2
3
|
getSessionGoal,
|
|
3
4
|
acquireCodexCredentialLease,
|
|
4
5
|
CodexCredentialLeaseAttemptFencedError,
|
|
@@ -126,15 +127,29 @@ export async function selectCodexTurnCapacity(
|
|
|
126
127
|
const selectForTurn = (
|
|
127
128
|
context: CodexCredentialLeaseSelectionContext,
|
|
128
129
|
lockedSessionCodexState: CodexCredentialLeaseSessionState,
|
|
129
|
-
) =>
|
|
130
|
-
|
|
131
|
-
|
|
130
|
+
) => {
|
|
131
|
+
const allowed = context.accounts.filter((account) =>
|
|
132
|
+
connectionModelAllowed(account.allowedModelIds, deps.turnExecutionPolicy.productModelId),
|
|
133
|
+
);
|
|
134
|
+
if (context.accounts.length > 0 && allowed.length === 0)
|
|
135
|
+
throw new Error("This model is disabled for the connected Codex subscriptions");
|
|
136
|
+
const sessionPin = lockedSessionCodexState.pinnedCredentialId;
|
|
137
|
+
if (
|
|
138
|
+
sessionPin &&
|
|
139
|
+
lockedSessionCodexState.pinSource !== "policy" &&
|
|
140
|
+
context.accounts.some((account) => account.id === sessionPin) &&
|
|
141
|
+
!allowed.some((account) => account.id === sessionPin)
|
|
142
|
+
)
|
|
143
|
+
throw new Error("This model is disabled for the pinned Codex subscription");
|
|
144
|
+
return selectCodexCredentialLeaseForTurn({
|
|
145
|
+
context: { ...context, accounts: allowed },
|
|
132
146
|
sessionId: input.sessionId,
|
|
133
147
|
sessionPinnedCredentialId: lockedSessionCodexState.pinnedCredentialId,
|
|
134
148
|
sessionPinSource: lockedSessionCodexState.pinSource,
|
|
135
149
|
sessionLastCredentialId: lockedSessionCodexState.lastCredentialId,
|
|
136
150
|
now: new Date(),
|
|
137
151
|
});
|
|
152
|
+
};
|
|
138
153
|
|
|
139
154
|
let leaseAcquisitionStartedAtMs = performance.now();
|
|
140
155
|
let leased: CodexCredentialLeaseResult<CodexTurnLeaseDecision> =
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { assertModelConnectionAllowsTurn } from "@opengeni/db";
|
|
1
2
|
import {
|
|
2
3
|
setSessionLastInputTokensForTurnAttempt,
|
|
3
4
|
getMaterializedSandboxFileResources,
|
|
@@ -468,6 +469,13 @@ export function createRunAgentTurnActivity(services: () => Promise<ActivityServi
|
|
|
468
469
|
requiredGeneratedVideoFiles,
|
|
469
470
|
});
|
|
470
471
|
if ("exit" in governance) return governance.exit;
|
|
472
|
+
await assertModelConnectionAllowsTurn(db, {
|
|
473
|
+
workspaceId: input.workspaceId,
|
|
474
|
+
subjectId: turn.initiatingHumanSubjectId ?? "worker:model-access",
|
|
475
|
+
modelId: turnExecutionPolicy.productModelId,
|
|
476
|
+
codexCredentialId: providerTurn.effectiveCodexCredentialId,
|
|
477
|
+
xaiCredentialId: providerTurn.effectiveXaiCredentialId,
|
|
478
|
+
});
|
|
471
479
|
const {
|
|
472
480
|
runtimePreparationStartedAt,
|
|
473
481
|
packRuntime,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getWorkspaceConnectionModelRestrictions } from "@opengeni/db";
|
|
1
2
|
import {
|
|
2
3
|
beginConnectorActionExecution,
|
|
3
4
|
completeConnectorActionExecution,
|
|
@@ -562,6 +563,7 @@ export async function prepareTurnToolRuntime(deps: PrepareTurnToolRuntimeDeps) {
|
|
|
562
563
|
const currentSettings = currentCatalog.settings;
|
|
563
564
|
const xaiReadinessAuthority = xaiCatalogReadinessAuthority(turn, credentialSubjectId);
|
|
564
565
|
const [
|
|
566
|
+
connectionModelRestrictions,
|
|
565
567
|
policy,
|
|
566
568
|
codexSubscriptionActive,
|
|
567
569
|
xaiSubscriptionActive,
|
|
@@ -574,6 +576,12 @@ export async function prepareTurnToolRuntime(deps: PrepareTurnToolRuntimeDeps) {
|
|
|
574
576
|
organizationOpenRouterConnectionActive,
|
|
575
577
|
organizationOpenRouterCustomModels,
|
|
576
578
|
] = await Promise.all([
|
|
579
|
+
getWorkspaceConnectionModelRestrictions(
|
|
580
|
+
db,
|
|
581
|
+
input.workspaceId,
|
|
582
|
+
xaiReadinessAuthority?.subjectId ?? credentialSubjectId ?? "worker:model-access",
|
|
583
|
+
xaiReadinessAuthority?.authoritySnapshot,
|
|
584
|
+
),
|
|
577
585
|
getWorkspaceModelPolicy(db, input.workspaceId),
|
|
578
586
|
workspaceCodexSubscriptionActive(db, currentSettings, input.workspaceId),
|
|
579
587
|
xaiReadinessAuthority && currentSettings.supergrokSubscriptionEnabled
|
|
@@ -615,6 +623,7 @@ export async function prepareTurnToolRuntime(deps: PrepareTurnToolRuntimeDeps) {
|
|
|
615
623
|
]);
|
|
616
624
|
return {
|
|
617
625
|
selections: resolveWorkspaceModelSelection({
|
|
626
|
+
connectionModelRestrictions,
|
|
618
627
|
settings: currentSettings,
|
|
619
628
|
policy,
|
|
620
629
|
codexSubscriptionActive,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { connectionModelAllowed } from "@opengeni/db";
|
|
1
2
|
import {
|
|
2
3
|
getSessionGoal,
|
|
3
4
|
acquireXaiCredentialLease,
|
|
@@ -55,6 +56,7 @@ export async function selectXaiTurnCapacity(
|
|
|
55
56
|
authoritySnapshot,
|
|
56
57
|
});
|
|
57
58
|
const leased = await acquireXaiCredentialLease(db, {
|
|
59
|
+
modelId: deps.turnExecutionPolicy.productModelId,
|
|
58
60
|
accountId: input.accountId,
|
|
59
61
|
workspaceId: input.workspaceId,
|
|
60
62
|
subjectId,
|
|
@@ -82,6 +84,21 @@ export async function selectXaiTurnCapacity(
|
|
|
82
84
|
leased.generation !== null &&
|
|
83
85
|
leases.xai.confirmedUntilMs !== null;
|
|
84
86
|
if (!providerTurn.effectiveXaiCredentialId) {
|
|
87
|
+
const relevant =
|
|
88
|
+
sessionPin?.pinnedCredentialId && sessionPin.pinSource !== "policy"
|
|
89
|
+
? leased.accounts.filter((account) => account.id === sessionPin.pinnedCredentialId)
|
|
90
|
+
: leased.accounts;
|
|
91
|
+
if (
|
|
92
|
+
relevant.length > 0 &&
|
|
93
|
+
relevant.every(
|
|
94
|
+
(account) =>
|
|
95
|
+
!connectionModelAllowed(
|
|
96
|
+
account.allowedModelIds,
|
|
97
|
+
deps.turnExecutionPolicy.productModelId,
|
|
98
|
+
),
|
|
99
|
+
)
|
|
100
|
+
)
|
|
101
|
+
throw new Error("This model is disabled for the selected SuperGrok subscription");
|
|
85
102
|
const connected = leased.accounts.length;
|
|
86
103
|
const allocatorEnabled = leased.accounts.filter((account) => account.allocatorEnabled).length;
|
|
87
104
|
if (connected === 0) {
|
|
@@ -149,7 +149,10 @@ export async function settingsWithWorkspaceGatewayCredential(
|
|
|
149
149
|
settings: Settings,
|
|
150
150
|
retainedProductModelId?: string | null,
|
|
151
151
|
): Promise<Settings> {
|
|
152
|
-
const activeCustomModels = await listWorkspaceGatewayCustomModels(db, {
|
|
152
|
+
const activeCustomModels = await listWorkspaceGatewayCustomModels(db, {
|
|
153
|
+
accountId,
|
|
154
|
+
workspaceId,
|
|
155
|
+
});
|
|
153
156
|
const retainedUpstreamModelId = retainedProductModelId?.startsWith(
|
|
154
157
|
WORKSPACE_GATEWAY_MODEL_ID_PREFIX,
|
|
155
158
|
)
|
|
@@ -170,7 +173,12 @@ export async function settingsWithWorkspaceGatewayCredential(
|
|
|
170
173
|
? [...activeCustomModels, retainedCustomModel]
|
|
171
174
|
: activeCustomModels;
|
|
172
175
|
const catalogSettings = withWorkspaceGatewayCatalogProvider(settings, customModels);
|
|
173
|
-
const apiKey = await loadWorkspaceVercelAiGatewayApiKey(
|
|
176
|
+
const apiKey = await loadWorkspaceVercelAiGatewayApiKey(
|
|
177
|
+
db,
|
|
178
|
+
settings,
|
|
179
|
+
workspaceId,
|
|
180
|
+
retainedProductModelId,
|
|
181
|
+
);
|
|
174
182
|
return apiKey
|
|
175
183
|
? withWorkspaceGatewayCredential(catalogSettings, apiKey, customModels)
|
|
176
184
|
: catalogSettings;
|
|
@@ -207,7 +215,12 @@ export async function settingsWithWorkspaceOpenRouterCredential(
|
|
|
207
215
|
? [...activeCustomModels, retainedCustomModel]
|
|
208
216
|
: activeCustomModels;
|
|
209
217
|
const catalogSettings = withWorkspaceOpenRouterCatalogProvider(settings, customModels);
|
|
210
|
-
const apiKey = await loadWorkspaceOpenRouterApiKey(
|
|
218
|
+
const apiKey = await loadWorkspaceOpenRouterApiKey(
|
|
219
|
+
db,
|
|
220
|
+
settings,
|
|
221
|
+
workspaceId,
|
|
222
|
+
retainedProductModelId,
|
|
223
|
+
);
|
|
211
224
|
return apiKey
|
|
212
225
|
? withWorkspaceOpenRouterCredential(catalogSettings, apiKey, customModels)
|
|
213
226
|
: catalogSettings;
|
package/src/activities/goals.ts
CHANGED
|
@@ -104,7 +104,6 @@ export function createGoalActivities(services: () => Promise<ControlActivityServ
|
|
|
104
104
|
settings,
|
|
105
105
|
workspaceModelPolicy,
|
|
106
106
|
inheritedModel: inheritedContinuationModel,
|
|
107
|
-
sessionModel: session.model,
|
|
108
107
|
});
|
|
109
108
|
continuationModel = modelDecision.model;
|
|
110
109
|
let modelPolicyBlocked = modelDecision.blocked;
|
|
@@ -207,7 +206,6 @@ export function goalContinuationModelDecision(input: {
|
|
|
207
206
|
settings: Settings;
|
|
208
207
|
workspaceModelPolicy: Awaited<ReturnType<typeof getWorkspaceModelPolicy>>;
|
|
209
208
|
inheritedModel: string;
|
|
210
|
-
sessionModel: string;
|
|
211
209
|
}): { model: string; blocked: string | null } {
|
|
212
210
|
const catalogSettings = input.settings.supergrokSubscriptionEnabled
|
|
213
211
|
? withXaiSubscriptionCatalogProvider(
|
|
@@ -224,11 +222,11 @@ export function goalContinuationModelDecision(input: {
|
|
|
224
222
|
providerId: policyProviderIdForModel(catalogSettings, modelId),
|
|
225
223
|
modelId,
|
|
226
224
|
}).allowed;
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
}
|
|
225
|
+
if (
|
|
226
|
+
resolveModelProvider(catalogSettings, input.inheritedModel) &&
|
|
227
|
+
!policyBlocks(input.inheritedModel)
|
|
228
|
+
) {
|
|
229
|
+
return { model: input.inheritedModel, blocked: null };
|
|
232
230
|
}
|
|
233
231
|
if (!resolveModelProvider(catalogSettings, input.inheritedModel)) {
|
|
234
232
|
return {
|
|
@@ -7,6 +7,9 @@ import {
|
|
|
7
7
|
resolveWorkspaceCodexCompactionDefault,
|
|
8
8
|
SCHEDULED_TASK_OCCURRENCE_PAYLOAD_MAX_BYTES,
|
|
9
9
|
ScheduledTaskRunAcceptedExecution,
|
|
10
|
+
SessionAgentAccess,
|
|
11
|
+
SessionEndUser,
|
|
12
|
+
SessionMemoryScope,
|
|
10
13
|
normalizeAutomaticSessionTitle,
|
|
11
14
|
scheduledOccurrencePayloadUtf8Bytes,
|
|
12
15
|
stableJson,
|
|
@@ -35,6 +38,7 @@ import {
|
|
|
35
38
|
enqueueSessionWorkflowWakeIfRunnable,
|
|
36
39
|
failScheduledGeneratedSessionRoute,
|
|
37
40
|
getScheduledTask,
|
|
41
|
+
getScheduledTaskCreatorPolicy,
|
|
38
42
|
getScheduledTaskRunAcceptedExecution,
|
|
39
43
|
getScheduledTaskRunByProducerKey,
|
|
40
44
|
getScheduledTargetSessionExecution,
|
|
@@ -50,6 +54,7 @@ import {
|
|
|
50
54
|
getScheduledScopedRigVersionMetadata,
|
|
51
55
|
getNestedAgentDepthDeploymentPolicy,
|
|
52
56
|
getSessionByCreateIdempotencyKey,
|
|
57
|
+
getSessionCreationExecutionPolicy,
|
|
53
58
|
getVariableSet,
|
|
54
59
|
isCodexBilledModel,
|
|
55
60
|
initializeSessionStartAtomically,
|
|
@@ -71,7 +76,11 @@ import {
|
|
|
71
76
|
withSessionActivityRlsContext,
|
|
72
77
|
} from "@opengeni/db";
|
|
73
78
|
import { publishDurableSessionEvents } from "@opengeni/events";
|
|
74
|
-
import {
|
|
79
|
+
import {
|
|
80
|
+
allowedFirstPartyMcpToolsForSession,
|
|
81
|
+
resolveFirstPartyMcpToolPolicy,
|
|
82
|
+
resolveTurnExecutionPolicyV1,
|
|
83
|
+
} from "@opengeni/config";
|
|
75
84
|
import { Context } from "@temporalio/activity";
|
|
76
85
|
import { createHash } from "node:crypto";
|
|
77
86
|
import {
|
|
@@ -504,7 +513,21 @@ export function createScheduledTaskActivities(services: () => Promise<ControlAct
|
|
|
504
513
|
let sandboxBackend = task.agentConfig.sandboxBackend ?? settings.sandboxBackend;
|
|
505
514
|
let sandboxOs: "linux" | "macos" | "windows" = "linux";
|
|
506
515
|
const taskTools = withFirstPartyTools(settings, task.agentConfig.tools);
|
|
507
|
-
|
|
516
|
+
// A task created by a live agent attempt froze its creator's effective
|
|
517
|
+
// first-party selection, permission set, and session access policy;
|
|
518
|
+
// its generated sessions inherit that boundary under today's
|
|
519
|
+
// deployment ceiling. A human/API-created task (null policy) keeps the
|
|
520
|
+
// deployment default exactly as before.
|
|
521
|
+
const creatorPolicy = await getScheduledTaskCreatorPolicy(db, task.workspaceId, task.id);
|
|
522
|
+
const firstPartyMcpTools = creatorPolicy?.firstPartyMcpTools
|
|
523
|
+
? allowedFirstPartyMcpToolsForSession(settings, creatorPolicy.firstPartyMcpTools)
|
|
524
|
+
: resolveFirstPartyMcpToolPolicy(settings).default;
|
|
525
|
+
const firstPartyMcpPermissions = creatorPolicy?.firstPartyMcpPermissions
|
|
526
|
+
? [...creatorPolicy.firstPartyMcpPermissions]
|
|
527
|
+
: [...DEFAULT_FIRST_PARTY_MCP_PERMISSIONS];
|
|
528
|
+
const creatorSessionPolicy = scheduledCreatorSessionPolicyInput(
|
|
529
|
+
creatorPolicy?.sessionPolicy ?? null,
|
|
530
|
+
);
|
|
508
531
|
const generatedTarget =
|
|
509
532
|
task.runMode === "new_session_per_run" ||
|
|
510
533
|
(task.runMode === "reusable_session" && task.reusableSessionId === null);
|
|
@@ -700,7 +723,7 @@ export function createScheduledTaskActivities(services: () => Promise<ControlAct
|
|
|
700
723
|
: {
|
|
701
724
|
tools: taskTools,
|
|
702
725
|
firstPartyMcpTools,
|
|
703
|
-
firstPartyMcpPermissions
|
|
726
|
+
firstPartyMcpPermissions,
|
|
704
727
|
variableSetId: acceptedVariableSet?.id ?? null,
|
|
705
728
|
rigId: acceptedRig?.id ?? null,
|
|
706
729
|
rigVersionId: acceptedRig?.activeVersion?.id ?? null,
|
|
@@ -847,7 +870,7 @@ export function createScheduledTaskActivities(services: () => Promise<ControlAct
|
|
|
847
870
|
resolvedSandboxOs: sandboxOs,
|
|
848
871
|
resolvedTools: taskTools,
|
|
849
872
|
resolvedFirstPartyMcpTools: firstPartyMcpTools,
|
|
850
|
-
resolvedFirstPartyMcpPermissions:
|
|
873
|
+
resolvedFirstPartyMcpPermissions: firstPartyMcpPermissions,
|
|
851
874
|
resolvedVariableSet: acceptedVariableSet
|
|
852
875
|
? { id: acceptedVariableSet.id, generation: acceptedVariableSet.generation }
|
|
853
876
|
: null,
|
|
@@ -1059,7 +1082,8 @@ export function createScheduledTaskActivities(services: () => Promise<ControlAct
|
|
|
1059
1082
|
resources: task.agentConfig.resources,
|
|
1060
1083
|
tools: taskTools,
|
|
1061
1084
|
firstPartyMcpTools,
|
|
1062
|
-
firstPartyMcpPermissions
|
|
1085
|
+
firstPartyMcpPermissions,
|
|
1086
|
+
...creatorSessionPolicy,
|
|
1063
1087
|
metadata: {
|
|
1064
1088
|
...taskMetadata,
|
|
1065
1089
|
model,
|
|
@@ -2068,6 +2092,14 @@ async function recoverBoundScheduledTaskDispatch(input: {
|
|
|
2068
2092
|
}
|
|
2069
2093
|
const taskMetadata = { ...task.agentConfig.metadata };
|
|
2070
2094
|
delete taskMetadata[OPENGENI_SLACK_BOT_SESSION_METADATA_KEY];
|
|
2095
|
+
// Tools and permissions were frozen into the accepted execution. The
|
|
2096
|
+
// creator session policy is immutable on the task row (a tombstoned task
|
|
2097
|
+
// still answers), so re-reading it here is deterministic for the same run.
|
|
2098
|
+
const recoveredCreatorPolicy = await getScheduledTaskCreatorPolicy(
|
|
2099
|
+
input.db,
|
|
2100
|
+
task.workspaceId,
|
|
2101
|
+
task.id,
|
|
2102
|
+
);
|
|
2071
2103
|
const created = await createSessionWithIdempotencyKeyResult(input.db, {
|
|
2072
2104
|
accountId: task.accountId,
|
|
2073
2105
|
workspaceId: task.workspaceId,
|
|
@@ -2076,6 +2108,7 @@ async function recoverBoundScheduledTaskDispatch(input: {
|
|
|
2076
2108
|
tools: input.acceptedExecution.resolvedTools,
|
|
2077
2109
|
firstPartyMcpTools: input.acceptedExecution.resolvedFirstPartyMcpTools,
|
|
2078
2110
|
firstPartyMcpPermissions: input.acceptedExecution.resolvedFirstPartyMcpPermissions,
|
|
2111
|
+
...scheduledCreatorSessionPolicyInput(recoveredCreatorPolicy?.sessionPolicy ?? null),
|
|
2079
2112
|
metadata: {
|
|
2080
2113
|
...taskMetadata,
|
|
2081
2114
|
model: input.acceptedExecution.resolvedModel,
|
|
@@ -2197,6 +2230,13 @@ async function recoverBoundScheduledTaskDispatch(input: {
|
|
|
2197
2230
|
task.runMode === "reusable_session" && typeof session.metadata.scheduledTaskRunId === "string"
|
|
2198
2231
|
? session.metadata.scheduledTaskRunId
|
|
2199
2232
|
: input.run.id;
|
|
2233
|
+
// The public Session policy follows the latest started turn. Recovery must
|
|
2234
|
+
// instead validate the immutable creation binding accepted by this run.
|
|
2235
|
+
const creationPolicy = await getSessionCreationExecutionPolicy(
|
|
2236
|
+
input.db,
|
|
2237
|
+
task.workspaceId,
|
|
2238
|
+
session.id,
|
|
2239
|
+
);
|
|
2200
2240
|
const expectedTaskMetadata = { ...task.agentConfig.metadata };
|
|
2201
2241
|
delete expectedTaskMetadata[OPENGENI_SLACK_BOT_SESSION_METADATA_KEY];
|
|
2202
2242
|
const expectedMetadata = {
|
|
@@ -2242,9 +2282,9 @@ async function recoverBoundScheduledTaskDispatch(input: {
|
|
|
2242
2282
|
input.acceptedExecution.alertOccurrenceLabels === null &&
|
|
2243
2283
|
(session.metadata.scheduledTaskRunId !== input.run.id ||
|
|
2244
2284
|
session.createdByContext.scheduledTaskRunId !== input.run.id)) ||
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2285
|
+
creationPolicy?.model !== input.acceptedExecution.resolvedModel ||
|
|
2286
|
+
creationPolicy.reasoningEffort !== input.acceptedExecution.resolvedReasoningEffort ||
|
|
2287
|
+
creationPolicy.latencyMode !== input.acceptedExecution.resolvedLatencyMode ||
|
|
2248
2288
|
session.sandboxBackend !== input.acceptedExecution.resolvedSandboxBackend ||
|
|
2249
2289
|
session.sandboxOs !== input.acceptedExecution.resolvedSandboxOs ||
|
|
2250
2290
|
session.activeSandboxId !== (task.agentConfig.machineTarget?.targetSandboxId ?? null) ||
|
|
@@ -2531,6 +2571,35 @@ async function replayScheduledTaskDispatch(input: {
|
|
|
2531
2571
|
return result;
|
|
2532
2572
|
}
|
|
2533
2573
|
|
|
2574
|
+
/**
|
|
2575
|
+
* Session-create fields carried by a frozen creator session policy. Only the
|
|
2576
|
+
* facts the creating session projection exposed at task creation are set;
|
|
2577
|
+
* a null (or no longer valid) key leaves the generated session on its own
|
|
2578
|
+
* default. The field names are the session access-scope contract
|
|
2579
|
+
* (`agentAccess`, `endUser`, `memoryScope`) consumed by session create.
|
|
2580
|
+
*/
|
|
2581
|
+
function scheduledCreatorSessionPolicyInput(
|
|
2582
|
+
policy: {
|
|
2583
|
+
agentAccess: string | null;
|
|
2584
|
+
endUser: { source: string; id: string } | null;
|
|
2585
|
+
memoryScope: string | null;
|
|
2586
|
+
} | null,
|
|
2587
|
+
): {
|
|
2588
|
+
agentAccess?: SessionAgentAccess;
|
|
2589
|
+
endUser?: SessionEndUser;
|
|
2590
|
+
memoryScope?: SessionMemoryScope;
|
|
2591
|
+
} {
|
|
2592
|
+
if (!policy) return {};
|
|
2593
|
+
const agentAccess = SessionAgentAccess.safeParse(policy.agentAccess);
|
|
2594
|
+
const endUser = SessionEndUser.safeParse(policy.endUser);
|
|
2595
|
+
const memoryScope = SessionMemoryScope.safeParse(policy.memoryScope);
|
|
2596
|
+
return {
|
|
2597
|
+
...(agentAccess.success ? { agentAccess: agentAccess.data } : {}),
|
|
2598
|
+
...(endUser.success ? { endUser: endUser.data } : {}),
|
|
2599
|
+
...(memoryScope.success ? { memoryScope: memoryScope.data } : {}),
|
|
2600
|
+
};
|
|
2601
|
+
}
|
|
2602
|
+
|
|
2534
2603
|
function knowledgeSourceSyncEffectivelyPaused(task: {
|
|
2535
2604
|
status: "active" | "paused";
|
|
2536
2605
|
metadata: Record<string, unknown>;
|