@opengeni/worker-bundle 0.26.0-canary.5 → 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/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-SHMDOQWS.js")).createControlActivities(dependencies) : (await import("./activities-turn-GHSFZB64.js")).createTurnActivities(dependencies);
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.5",
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.14",
58
- "@opengeni/capabilities": "^0.3.2-canary.5",
59
- "@opengeni/codemode": "^0.4.27-canary.5",
60
- "@opengeni/codex": "^0.2.21-canary.5",
61
- "@opengeni/config": "^1.0.0-canary.5",
62
- "@opengeni/contracts": "^2.13.0-canary.5",
63
- "@opengeni/core": "^2.7.5-canary.5",
64
- "@opengeni/db": "^4.0.0-canary.5",
65
- "@opengeni/documents": "^0.8.19-canary.5",
66
- "@opengeni/events": "^0.4.17-canary.5",
67
- "@opengeni/github": "^0.7.3-canary.5",
68
- "@opengeni/network": "^0.3.0-canary.5",
69
- "@opengeni/observability": "^0.8.19-canary.5",
70
- "@opengeni/runtime": "^2.3.0-canary.5",
71
- "@opengeni/storage": "^0.2.120-canary.5",
72
- "@opengeni/xai-subscription": "^0.1.3-canary.5",
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
- selectCodexCredentialLeaseForTurn({
131
- context,
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, { accountId, workspaceId });
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(db, settings, workspaceId);
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(db, settings, workspaceId);
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;
@@ -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
- const candidates = [...new Set([input.inheritedModel, input.sessionModel])];
228
- for (const model of candidates) {
229
- if (resolveModelProvider(catalogSettings, model) && !policyBlocks(model)) {
230
- return { model, blocked: null };
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 { resolveFirstPartyMcpToolPolicy, resolveTurnExecutionPolicyV1 } from "@opengeni/config";
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
- const firstPartyMcpTools = resolveFirstPartyMcpToolPolicy(settings).default;
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: [...DEFAULT_FIRST_PARTY_MCP_PERMISSIONS],
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: [...DEFAULT_FIRST_PARTY_MCP_PERMISSIONS],
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: [...DEFAULT_FIRST_PARTY_MCP_PERMISSIONS],
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
- session.model !== input.acceptedExecution.resolvedModel ||
2246
- session.reasoningEffort !== input.acceptedExecution.resolvedReasoningEffort ||
2247
- session.latencyMode !== input.acceptedExecution.resolvedLatencyMode ||
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>;