@opengeni/worker-bundle 1.0.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/dist/activities/agent-turn/codex.d.ts +1 -1
  2. package/dist/activities/agent-turn/compaction-prep.d.ts +1 -5
  3. package/dist/activities/agent-turn/errors.d.ts +31 -5
  4. package/dist/activities/agent-turn/finalization-monitor.d.ts +17 -0
  5. package/dist/activities/agent-turn/finalization.d.ts +1 -1
  6. package/dist/activities/agent-turn/governance-model.d.ts +0 -2
  7. package/dist/activities/agent-turn/quiescence.d.ts +1 -0
  8. package/dist/activities/agent-turn/recovery-warning.d.ts +8 -0
  9. package/dist/activities/agent-turn/run-credentials.d.ts +0 -1
  10. package/dist/activities/agent-turn/sandbox-establish.d.ts +1 -1
  11. package/dist/activities/agent-turn/sandbox-route.d.ts +0 -20
  12. package/dist/activities/agent-turn/sandbox-runtime.d.ts +1 -1
  13. package/dist/activities/agent-turn/skill-remove.d.ts +14 -0
  14. package/dist/activities/agent-turn/skill-search.d.ts +1 -1
  15. package/dist/activities/agent-turn/stream-attempt.d.ts +1 -0
  16. package/dist/activities/agent-turn/tool-environment.d.ts +0 -4
  17. package/dist/activities/agent-turn/turn-context.d.ts +2 -0
  18. package/dist/activities/agent-turn/turn-sandbox-access.d.ts +3 -0
  19. package/dist/activities/codex-capacity.d.ts +6 -1
  20. package/dist/activities/codex-rotation.d.ts +1 -1
  21. package/dist/activities/context-compaction.d.ts +7 -1
  22. package/dist/activities/mcp-account-routes.d.ts +22 -0
  23. package/dist/activities/mcp-credentials.d.ts +12 -13
  24. package/dist/activities/mcp-operation-authority.d.ts +0 -5
  25. package/dist/activities/rig-verification.d.ts +2 -3
  26. package/dist/activities/sandbox-images.d.ts +1 -1
  27. package/dist/activities/sandbox-lease.d.ts +4 -3
  28. package/dist/activities/session-state.d.ts +57 -2
  29. package/dist/activities/types.d.ts +12 -3
  30. package/dist/{activities-control-HMFGSKC5.js → activities-control-BOLIY3H4.js} +366 -187
  31. package/dist/activities-control-BOLIY3H4.js.map +1 -0
  32. package/dist/activities-control.d.ts +110 -2
  33. package/dist/{activities-turn-AP67JADS.js → activities-turn-2B3WMHBB.js} +767 -471
  34. package/dist/activities-turn-2B3WMHBB.js.map +1 -0
  35. package/dist/activities.d.ts +110 -2
  36. package/dist/artifact-materializer-entry.js +5 -2
  37. package/dist/artifact-materializer-entry.js.map +1 -1
  38. package/dist/artifact-outbox-entry.js +2 -2
  39. package/dist/artifact-outbox-entry.js.map +1 -1
  40. package/dist/{chunk-A4XQWVZK.js → chunk-I7HKKMUJ.js} +77 -1
  41. package/dist/chunk-I7HKKMUJ.js.map +1 -0
  42. package/dist/{chunk-CYITU5UH.js → chunk-TVEE2UUC.js} +275 -146
  43. package/dist/chunk-TVEE2UUC.js.map +1 -0
  44. package/dist/editable-artifact-materializer-service.d.ts +2 -2
  45. package/dist/editable-artifact-outbox-service.d.ts +2 -2
  46. package/dist/index.d.ts +55 -1
  47. package/dist/index.js +4 -3
  48. package/dist/index.js.map +1 -1
  49. package/dist/observability-metrics.d.ts +11 -3
  50. package/dist/retained-process-diagnostics.d.ts +4 -0
  51. package/dist/sandbox-resume.d.ts +2 -12
  52. package/dist/sandbox-routing.d.ts +5 -3
  53. package/dist/sandbox-snapshot-diagnostics.d.ts +20 -0
  54. package/dist/warm-capture-holder.d.ts +3 -0
  55. package/dist/workflow-bundle.js +51 -11
  56. package/package.json +15 -15
  57. package/src/activities/agent-turn/agent-build.ts +42 -5
  58. package/src/activities/agent-turn/claim.ts +12 -0
  59. package/src/activities/agent-turn/codex-capacity.ts +26 -4
  60. package/src/activities/agent-turn/codex.ts +6 -2
  61. package/src/activities/agent-turn/compaction-prep.ts +53 -72
  62. package/src/activities/agent-turn/errors.ts +98 -10
  63. package/src/activities/agent-turn/failure-settlement.ts +49 -28
  64. package/src/activities/agent-turn/finalization-monitor.ts +121 -0
  65. package/src/activities/agent-turn/finalization.ts +79 -21
  66. package/src/activities/agent-turn/governance-model.ts +15 -19
  67. package/src/activities/agent-turn/history.ts +24 -10
  68. package/src/activities/agent-turn/quiescence.ts +3 -0
  69. package/src/activities/agent-turn/recovery-warning.ts +18 -0
  70. package/src/activities/agent-turn/run-credentials.ts +3 -7
  71. package/src/activities/agent-turn/run.ts +68 -52
  72. package/src/activities/agent-turn/sandbox-establish.ts +10 -2
  73. package/src/activities/agent-turn/sandbox-route.ts +0 -20
  74. package/src/activities/agent-turn/sandbox-runtime.ts +40 -7
  75. package/src/activities/agent-turn/skill-remove.ts +46 -0
  76. package/src/activities/agent-turn/skill-save.ts +1 -1
  77. package/src/activities/agent-turn/skill-search.ts +1 -1
  78. package/src/activities/agent-turn/skill-selection.ts +2 -0
  79. package/src/activities/agent-turn/skill-tools.ts +10 -5
  80. package/src/activities/agent-turn/stream-attempt.ts +38 -15
  81. package/src/activities/agent-turn/tool-environment.ts +44 -29
  82. package/src/activities/agent-turn/turn-context.ts +3 -0
  83. package/src/activities/agent-turn/turn-sandbox-access.ts +7 -1
  84. package/src/activities/capabilities.ts +17 -2
  85. package/src/activities/codex-capacity.ts +38 -9
  86. package/src/activities/codex-rotation.ts +18 -5
  87. package/src/activities/context-compaction.ts +26 -4
  88. package/src/activities/goals.ts +1 -0
  89. package/src/activities/google-drive-publication.ts +1 -3
  90. package/src/activities/mcp-account-routes.ts +139 -0
  91. package/src/activities/mcp-credentials.ts +83 -194
  92. package/src/activities/mcp-operation-authority.ts +16 -41
  93. package/src/activities/parent-wake.ts +8 -0
  94. package/src/activities/rig-verification.ts +38 -37
  95. package/src/activities/run-input.ts +25 -16
  96. package/src/activities/sandbox-images.ts +0 -1
  97. package/src/activities/sandbox-lease.ts +177 -44
  98. package/src/activities/scheduled-tasks.ts +118 -93
  99. package/src/activities/session-state.ts +83 -3
  100. package/src/activities/types.ts +18 -2
  101. package/src/activities/workflow-wake.ts +2 -17
  102. package/src/editable-artifact-materializer-service.ts +7 -3
  103. package/src/editable-artifact-outbox-service.ts +4 -4
  104. package/src/github-rest-mcp.ts +0 -1
  105. package/src/index.ts +2 -1
  106. package/src/observability-metrics.ts +105 -2
  107. package/src/personal-github-git-credentials.ts +0 -1
  108. package/src/pr-review-credentials.ts +0 -2
  109. package/src/retained-process-diagnostics.ts +50 -0
  110. package/src/sandbox-resume.ts +58 -73
  111. package/src/sandbox-routing.ts +44 -19
  112. package/src/sandbox-snapshot-diagnostics.ts +112 -0
  113. package/src/warm-capture-holder.ts +15 -0
  114. package/src/workflows/session.ts +64 -2
  115. package/dist/activities/agent-turn/knowledge-sources.d.ts +0 -20
  116. package/dist/activities/packs.d.ts +0 -55
  117. package/dist/activities-control-HMFGSKC5.js.map +0 -1
  118. package/dist/activities-turn-AP67JADS.js.map +0 -1
  119. package/dist/chunk-A4XQWVZK.js.map +0 -1
  120. package/dist/chunk-CYITU5UH.js.map +0 -1
  121. package/src/activities/agent-turn/knowledge-sources.ts +0 -86
  122. package/src/activities/packs.ts +0 -166
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengeni/worker-bundle",
3
- "version": "1.0.1",
3
+ "version": "2.0.0",
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": {
@@ -56,21 +56,21 @@
56
56
  "@llamaindex/liteparse": "2.14.2",
57
57
  "@opengeni/agent-proto": "^0.6.0",
58
58
  "@opengeni/capabilities": "^0.3.4",
59
- "@opengeni/codemode": "^0.5.9",
60
- "@opengeni/codex": "^0.2.23",
61
- "@opengeni/config": "^1.2.2",
62
- "@opengeni/contracts": "^4.1.0",
63
- "@opengeni/core": "^3.0.1",
64
- "@opengeni/db": "^5.0.1",
65
- "@opengeni/documents": "^0.8.30",
66
- "@opengeni/events": "^0.4.28",
67
- "@opengeni/github": "^0.7.13",
59
+ "@opengeni/codemode": "^0.6.0",
60
+ "@opengeni/codex": "^0.2.24",
61
+ "@opengeni/config": "^2.0.0",
62
+ "@opengeni/contracts": "^5.0.0",
63
+ "@opengeni/core": "^4.0.0",
64
+ "@opengeni/db": "^6.0.0",
65
+ "@opengeni/documents": "^0.8.31",
66
+ "@opengeni/events": "^0.4.29",
67
+ "@opengeni/github": "^0.7.14",
68
68
  "@opengeni/network": "^0.3.1",
69
- "@opengeni/observability": "^0.8.29",
70
- "@opengeni/runtime": "^3.0.1",
71
- "@opengeni/sdk": "^6.1.0",
72
- "@opengeni/storage": "^0.2.130",
73
- "@opengeni/tool-gateway": "^0.1.10",
69
+ "@opengeni/observability": "^0.8.30",
70
+ "@opengeni/runtime": "^4.0.0",
71
+ "@opengeni/sdk": "^7.0.0",
72
+ "@opengeni/storage": "^0.2.131",
73
+ "@opengeni/tool-gateway": "^0.1.11",
74
74
  "@opengeni/xai-subscription": "^0.1.4",
75
75
  "@temporalio/activity": "^1.17.0",
76
76
  "@temporalio/client": "^1.17.0",
@@ -8,7 +8,10 @@ import {
8
8
  loadWorkspaceVercelAiGatewayCredentialLease,
9
9
  getExternalLinkTurnAuthorization,
10
10
  getSessionTurnForAttempt,
11
+ ensureSessionReasoningConfiguration,
12
+ ensureSessionSkillCatalog,
11
13
  } from "@opengeni/db";
14
+ import { recoveryAwareSessionInstructions } from "./recovery-warning";
12
15
  import {
13
16
  formatSkillCatalog,
14
17
  type AttemptConnectorActionBinding,
@@ -24,7 +27,7 @@ import {
24
27
  resolveModelProvider,
25
28
  type Settings,
26
29
  } from "@opengeni/config";
27
- import { type CodexRequestContext } from "@opengeni/codex";
30
+ import { type CodexRequestContext, supportsReasoningConfiguration } from "@opengeni/codex";
28
31
  import { executeXaiSubscriptionImageGeneration } from "../xai-image-generation";
29
32
  import { rigProviderImageContentHash, videoGenerationCapabilitiesForPolicy } from "@opengeni/core";
30
33
  import {
@@ -34,7 +37,7 @@ import {
34
37
  type VideoGenerationCredentialLease,
35
38
  } from "../video-generation-admission";
36
39
  import { VideoReferenceInputError } from "../video-reference-staging";
37
- import { rigProviderImageSourceImage } from "../packs";
40
+ import { rigProviderImageSourceImage } from "../sandbox-images";
38
41
  import type { TurnActivityServices as ActivityServices, RunAgentTurnInput } from "../types";
39
42
  import { recordTurnStartupPhase } from "../../observability-metrics";
40
43
  import { summarizeCompanyBrainContributions } from "../../model-context-contributions";
@@ -191,6 +194,13 @@ export async function buildTurnAgent(deps: BuildTurnAgentDeps) {
191
194
  codexContext,
192
195
  } = deps;
193
196
  const preparedTools = eventing.preparedTools!;
197
+ // Durable recovery truth is read for every attempt, including reconstruction
198
+ // after compaction. It is never inferred from transcript tool successes.
199
+ const sessionInstructions = await recoveryAwareSessionInstructions(
200
+ db,
201
+ input.workspaceId,
202
+ session,
203
+ );
194
204
 
195
205
  const missingSessionTitleHint = preparationIndependentToolNames.includes(
196
206
  SESSION_TITLE_MODEL_TOOL_NAME,
@@ -556,7 +566,15 @@ export async function buildTurnAgent(deps: BuildTurnAgentDeps) {
556
566
  turnExecutionPolicy.latencyMode,
557
567
  );
558
568
  const approvedToolCallId = approvedConnectorActionCallId(trigger);
559
- const modelVisibleSkillCatalogText = formatSkillCatalog(deps.skillCatalog);
569
+ const modelVisibleSkillCatalogText = await ensureSessionSkillCatalog(db, {
570
+ accountId: input.accountId,
571
+ workspaceId: input.workspaceId,
572
+ sessionId: input.sessionId,
573
+ turnId: turn.id,
574
+ expectedExecutionGeneration: turn.executionGeneration,
575
+ expectedAttemptId: input.attemptId,
576
+ catalog: formatSkillCatalog(deps.skillCatalog),
577
+ });
560
578
  try {
561
579
  eventing.companyBrainContextContributions = summarizeCompanyBrainContributions(
562
580
  buildCompanyBrainContributionReceiptFor(modelVisibleSkillCatalogText),
@@ -581,6 +599,24 @@ export async function buildTurnAgent(deps: BuildTurnAgentDeps) {
581
599
  );
582
600
  if (linkedToolAuthority && !linkedToolAuthority.authorized)
583
601
  throw new Error("Native identity link was revoked");
602
+ const useReasoningUpdates =
603
+ eventing.modelRunSettings.reasoningConfigurationUpdatesEnabled &&
604
+ resolvedModel?.provider.api === "responses" &&
605
+ (resolvedModel.provider.id === "codex" || resolvedModel.provider.id === "openai") &&
606
+ supportsReasoningConfiguration(turnExecutionPolicy.upstreamModelId, turn.reasoningEffort);
607
+ const requestReasoningEffort =
608
+ useReasoningUpdates &&
609
+ supportsReasoningConfiguration(turnExecutionPolicy.upstreamModelId, turn.reasoningEffort)
610
+ ? await ensureSessionReasoningConfiguration(db, {
611
+ accountId: input.accountId,
612
+ workspaceId: input.workspaceId,
613
+ sessionId: input.sessionId,
614
+ turnId: turn.id,
615
+ expectedExecutionGeneration: turn.executionGeneration,
616
+ expectedAttemptId: input.attemptId,
617
+ effort: turn.reasoningEffort,
618
+ })
619
+ : turn.reasoningEffort;
584
620
  const agent = (() => {
585
621
  const agentConstructionStartedAt = performance.now();
586
622
  let agentConstructionOutcome: "completed" | "failed" = "completed";
@@ -605,7 +641,7 @@ export async function buildTurnAgent(deps: BuildTurnAgentDeps) {
605
641
  }
606
642
  : {}),
607
643
  ...(preparedTools.inputWaitYield ? { inputWaitYield: preparedTools.inputWaitYield } : {}),
608
- reasoningEffort: turn.reasoningEffort,
644
+ reasoningEffort: requestReasoningEffort,
609
645
  latencyMode: turnExecutionPolicy.latencyMode,
610
646
  ...(serviceTier ? { serviceTier } : {}),
611
647
  ...(humanInputResume ? { humanInputResponse: humanInputResume } : {}),
@@ -707,6 +743,7 @@ export async function buildTurnAgent(deps: BuildTurnAgentDeps) {
707
743
  }),
708
744
  onRetainableSessionImageOutput: media.retainSessionImageAtToolBoundary,
709
745
  skillCatalog: deps.skillCatalog,
746
+ skillCatalogInHistory: true,
710
747
  ...(!structuredWorkspacePolicyActive && workspaceAgentInstructions
711
748
  ? { instructionsTemplate: workspaceAgentInstructions }
712
749
  : {}),
@@ -715,7 +752,7 @@ export async function buildTurnAgent(deps: BuildTurnAgentDeps) {
715
752
  // Per-session persona tier (session > workspace > deployment default).
716
753
  // Composed system-level AFTER the workspace persona so it refines it for
717
754
  // this one session; absent ⇒ byte-identical to today's composition.
718
- ...(session.instructions ? { sessionInstructions: session.instructions } : {}),
755
+ ...(sessionInstructions ? { sessionInstructions } : {}),
719
756
  ...workspaceEnvironmentOption,
720
757
  // RIG RUNTIME (M3): the doctrine block, the setup-script hook (only when
721
758
  // the frozen version carries a non-empty script), and the rig credential
@@ -1,3 +1,4 @@
1
+ import { FILESYSTEM_DISCONTINUITY_PROTOCOL } from "./recovery-warning";
1
2
  import {
2
3
  applySessionTurnSettlement,
3
4
  claimSessionWorkForAttempt,
@@ -14,6 +15,7 @@ import {
14
15
  type SessionTurnForExecution,
15
16
  } from "@opengeni/db";
16
17
  import { appendAndPublishTurnEventsFenced, publishDurableSessionEvents } from "@opengeni/events";
18
+ import { linkCurrentSpanToAdmission, turnExecutionTelemetryKey } from "@opengeni/observability";
17
19
  import { deliverChildRequiresActionToParent } from "../parent-wake";
18
20
  import {
19
21
  assertTurnExecutionPolicyMatchesConfigV1,
@@ -192,6 +194,7 @@ export async function claimTurnAttempt(deps: ClaimTurnDeps): Promise<ClaimTurnOu
192
194
  update,
193
195
  });
194
196
  const claim = await claimSessionWorkForAttempt(db, input.workspaceId, {
197
+ filesystemDiscontinuityProtocol: FILESYSTEM_DISCONTINUITY_PROTOCOL,
195
198
  sessionId: input.sessionId,
196
199
  workflowId: input.workflowId,
197
200
  workflowRunId: input.workflowRunId,
@@ -249,6 +252,7 @@ export async function claimTurnAttempt(deps: ClaimTurnDeps): Promise<ClaimTurnOu
249
252
  db,
250
253
  mcpSettings,
251
254
  input.workspaceId,
255
+ turn.id,
252
256
  );
253
257
  const codexSettings = await settingsWithCodexCredential(
254
258
  db,
@@ -321,6 +325,7 @@ export async function claimTurnAttempt(deps: ClaimTurnDeps): Promise<ClaimTurnOu
321
325
  if (!trigger) {
322
326
  throw new Error(`Trigger event not found: ${attempt.triggerEventId}`);
323
327
  }
328
+ if (trigger.type === "user.message") linkCurrentSpanToAdmission(trigger.id);
324
329
  const humanInputResume = await getHumanInputResumeForEvent(
325
330
  db,
326
331
  input.workspaceId,
@@ -336,6 +341,7 @@ export async function claimTurnAttempt(deps: ClaimTurnDeps): Promise<ClaimTurnOu
336
341
  attempt.triggerType = trigger.type;
337
342
  const attachPendingUpdatesAfterOpenSuffix = async (): Promise<boolean> => {
338
343
  const attached = await claimSessionWorkForAttempt(db, input.workspaceId, {
344
+ filesystemDiscontinuityProtocol: FILESYSTEM_DISCONTINUITY_PROTOCOL,
339
345
  sessionId: input.sessionId,
340
346
  workflowId: input.workflowId,
341
347
  workflowRunId: input.workflowRunId,
@@ -387,6 +393,7 @@ export async function claimTurnAttempt(deps: ClaimTurnDeps): Promise<ClaimTurnOu
387
393
  turnId: attempt.turnId,
388
394
  opAcks: {},
389
395
  };
396
+ eventing.heartbeatDetails = heartbeatDetails;
390
397
  const opJournal = makeTurnOpJournal(activityContext, heartbeatDetails);
391
398
  eventing.heartbeatTimer = startActivityHeartbeat(activityContext, heartbeatDetails);
392
399
  let producerSeq = 0;
@@ -547,6 +554,11 @@ export async function claimTurnAttempt(deps: ClaimTurnDeps): Promise<ClaimTurnOu
547
554
  throwIfTurnCancelled();
548
555
  recordTurnStartupPhase(observability, {
549
556
  phase: "claim_and_policy",
557
+ executionCorrelationId: turnExecutionTelemetryKey(
558
+ input.workspaceId,
559
+ input.sessionId,
560
+ input.attemptId,
561
+ ),
550
562
  provider: turnExecutionPolicy.providerId,
551
563
  backend: turn.sandboxBackend,
552
564
  outcome: "completed",
@@ -173,10 +173,17 @@ export async function selectCodexTurnCapacity(
173
173
  );
174
174
  if (leased.decision.kind === "allCapped") {
175
175
  // Bounded self-heal of stale usage cache, then ONE new atomic selection.
176
- await refreshCappedCodexUsageRows(db, settings, input.workspaceId, leased.accounts, {
177
- signalCodexCapacityWorkflow,
178
- wakeSessionWorkflow,
179
- });
176
+ await refreshCappedCodexUsageRows(
177
+ db,
178
+ settings,
179
+ input.workspaceId,
180
+ leased.accounts,
181
+ {
182
+ signalCodexCapacityWorkflow,
183
+ wakeSessionWorkflow,
184
+ },
185
+ turn.id,
186
+ );
180
187
  leaseAcquisitionStartedAtMs = performance.now();
181
188
  leased = await acquireCodexCredentialLease(
182
189
  db,
@@ -466,6 +473,11 @@ export async function selectCodexTurnCapacity(
466
473
  },
467
474
  },
468
475
  );
476
+ if (evaluated.action === "stopped") {
477
+ control.turnMetricOutcome = "failed";
478
+ control.activityStatus = evaluated.sessionStatus === "queued" ? "idle" : "failed";
479
+ return { exit: claimedResult({ status: control.activityStatus }) };
480
+ }
469
481
  if (evaluated.action === "resumed") {
470
482
  control.turnMetricOutcome = "recovering";
471
483
  control.activityStatus = "recovering";
@@ -583,6 +595,11 @@ export async function selectCodexTurnCapacity(
583
595
  },
584
596
  },
585
597
  );
598
+ if (evaluated.action === "stopped") {
599
+ control.turnMetricOutcome = "failed";
600
+ control.activityStatus = evaluated.sessionStatus === "queued" ? "idle" : "failed";
601
+ return { exit: claimedResult({ status: control.activityStatus }) };
602
+ }
586
603
  if (evaluated.action === "resumed") {
587
604
  control.turnMetricOutcome = "recovering";
588
605
  control.activityStatus = "recovering";
@@ -682,6 +699,11 @@ export async function selectCodexTurnCapacity(
682
699
  failurePayload,
683
700
  },
684
701
  );
702
+ if (evaluated.action === "stopped") {
703
+ control.turnMetricOutcome = "failed";
704
+ control.activityStatus = evaluated.sessionStatus === "queued" ? "idle" : "failed";
705
+ return { exit: claimedResult({ status: control.activityStatus }) };
706
+ }
685
707
  if (evaluated.action === "resumed") {
686
708
  control.turnMetricOutcome = "recovering";
687
709
  control.activityStatus = "recovering";
@@ -61,6 +61,7 @@ export async function refreshCappedCodexUsageRows(
61
61
  signalCodexCapacityWorkflow?: ActivityServices["signalCodexCapacityWorkflow"] | undefined;
62
62
  wakeSessionWorkflow: ActivityServices["wakeSessionWorkflow"];
63
63
  },
64
+ acceptedTurnId?: string,
64
65
  ): Promise<
65
66
  Array<
66
67
  Pick<
@@ -82,10 +83,13 @@ export async function refreshCappedCodexUsageRows(
82
83
  return accounts;
83
84
  }
84
85
  await refreshCodexUsageAndRepairCapacityWaiters(
85
- stale.map((account) => () => fetchCodexUsageForAccount(db, settings, workspaceId, account.id)),
86
+ stale.map(
87
+ (account) => () =>
88
+ fetchCodexUsageForAccount(db, settings, workspaceId, account.id, undefined, acceptedTurnId),
89
+ ),
86
90
  () => signalPendingCodexCapacityWakeTargets({ db, ...capacitySignals }, workspaceId),
87
91
  );
88
- return listCodexAccountStatuses(db, workspaceId).catch(() => accounts);
92
+ return listCodexAccountStatuses(db, workspaceId, acceptedTurnId).catch(() => accounts);
89
93
  }
90
94
 
91
95
  /**
@@ -6,8 +6,11 @@ import {
6
6
  appendWorkspaceMemory,
7
7
  composeAgentInstructions,
8
8
  requestRemoteCompactionV2,
9
- serializedToolsForRemoteCompaction,
10
- EmptyCompactionSummaryError,
9
+ preparedCompactionRequest,
10
+ queuePreparedCompaction,
11
+ compactionThresholdTokens,
12
+ CompactionNeededError,
13
+ compactionProviderRejection,
11
14
  SUMMARY_BUFFER_TOKENS,
12
15
  type ModelResponseUsage,
13
16
  } from "@opengeni/runtime";
@@ -31,7 +34,7 @@ import { type SessionEvent } from "@opengeni/contracts";
31
34
  import { acceptsPromptCacheKeyForTurn } from "./codex";
32
35
  import {
33
36
  safeErrorDiagnostic,
34
- compactionFailureReasonFromError,
37
+ compactionFailureTurnEventPayload,
35
38
  isCompactionSummaryFailure,
36
39
  shouldRecoverCompactionProviderFailure,
37
40
  } from "./errors";
@@ -53,10 +56,7 @@ import type {
53
56
  } from "./turn-context";
54
57
 
55
58
  export type RemoteCompactionPrefix = {
56
- tools: Awaited<ReturnType<typeof serializedToolsForRemoteCompaction>>;
57
- instructions: string;
58
- toolsReady: boolean;
59
- agent: Parameters<typeof serializedToolsForRemoteCompaction>[0] | null;
59
+ agent: ReturnType<ActivityServices["runtime"]["buildAgent"]> | null;
60
60
  };
61
61
 
62
62
  export type CompactionPrepDeps = {
@@ -166,9 +166,6 @@ export async function prepareCompaction(deps: CompactionPrepDeps): Promise<Compa
166
166
  } = deps;
167
167
 
168
168
  const remotePrefix: RemoteCompactionPrefix = {
169
- tools: [],
170
- instructions: "",
171
- toolsReady: false,
172
169
  agent: null,
173
170
  };
174
171
 
@@ -234,45 +231,16 @@ export async function prepareCompaction(deps: CompactionPrepDeps): Promise<Compa
234
231
  resolvedModel && billingState.isCodexTurn
235
232
  ? (s: Settings, m: Array<Record<string, unknown>>) =>
236
233
  withCodexRemoteCompaction(async () => {
237
- // Lazily serialize tools here so EmptyCompactionSummaryError is
238
- // thrown inside the compaction try/settlement handlers, not as a
239
- // raw activity failure before maybeCompactContext runs.
240
- if (!remotePrefix.instructions.trim()) {
241
- throw new EmptyCompactionSummaryError({
242
- stage: "remote_v2_instructions",
243
- reason: "agent_missing_system_instructions",
244
- });
245
- }
246
- if (!remotePrefix.toolsReady) {
247
- if (!remotePrefix.agent) {
248
- throw new EmptyCompactionSummaryError({
249
- stage: "remote_v2_tools",
250
- reason: "agent_missing_for_tools",
251
- });
252
- }
253
- try {
254
- remotePrefix.tools = await serializedToolsForRemoteCompaction(remotePrefix.agent);
255
- } catch (error) {
256
- // Tool schemas sit before instructions in the cache prefix.
257
- // Failing open to [] would reintroduce a massive pre-compact
258
- // cache bust — fail closed so we never send a tools mismatch
259
- // on purpose.
260
- throw new EmptyCompactionSummaryError({
261
- stage: "remote_v2_tools",
262
- reason: "serialize_tools_failed",
263
- error: String(error),
264
- });
265
- }
266
- remotePrefix.toolsReady = true;
267
- }
234
+ if (!remotePrefix.agent) throw new Error("Compaction agent is unavailable");
235
+ const preparedRequest = preparedCompactionRequest(remotePrefix.agent);
268
236
  return requestRemoteCompactionV2(s, m, {
269
237
  client: resolvedModel.client,
270
238
  provider: resolvedModel.provider,
271
239
  model: turnExecutionPolicy.upstreamModelId,
272
- systemInstructions: remotePrefix.instructions,
240
+ preparedRequest,
241
+ captureAgent: remotePrefix.agent,
242
+ signal: cancellationSignal,
273
243
  onUsage: recordCompactionUsage,
274
- tools: remotePrefix.tools,
275
- ...(promptCacheKey ? { promptCacheKey } : {}),
276
244
  });
277
245
  })
278
246
  : undefined;
@@ -409,22 +377,16 @@ export async function prepareCompaction(deps: CompactionPrepDeps): Promise<Compa
409
377
  {
410
378
  clearRequestedCompaction: true,
411
379
  publishLiveEvents: publishCompactionLiveEvents,
380
+ providerRejection: compactionProviderRejection(error),
412
381
  },
413
382
  );
414
383
  if (!isCompactionSummaryFailure(error)) throw error;
415
- const errorMessage = String(compactionFailureReasonFromError(error));
416
384
  if (
417
385
  !(await eventing.settle!({
418
386
  events: [
419
387
  {
420
388
  type: "turn.failed",
421
- payload: {
422
- error: errorMessage,
423
- code: "context_compaction_failed",
424
- retryable: false,
425
- recovery: "user_message",
426
- compacted: false,
427
- },
389
+ payload: compactionFailureTurnEventPayload(error),
428
390
  },
429
391
  {
430
392
  type: "session.status.changed",
@@ -522,16 +484,25 @@ export async function runPostAgentCompaction(
522
484
  agentInstructions.trim() ? agentInstructions : undefined,
523
485
  );
524
486
  if (remoteCompactionRequester) {
525
- // Exact byte match with the ordinary turn prefix (CLI base_instructions).
526
- // Tools serialize lazily inside the requester so setup failures settle as
527
- // compaction failures rather than raw activity crashes.
528
- remotePrefix.instructions = agentInstructions;
487
+ // The prefix is captured only after this agent passes normal SDK preparation.
529
488
  remotePrefix.agent = agent;
530
489
  }
531
490
 
532
491
  if (compactionOnlyTurn) {
533
492
  const requested = await isSessionCompactionRequested(db, input.workspaceId, input.sessionId);
534
493
  let outcome: Awaited<ReturnType<typeof maybeCompactContext>> | null = null;
494
+ if (requested && remoteCompactionRequester && session.codexCompactionMode === "remote_v2") {
495
+ queuePreparedCompaction(
496
+ agent,
497
+ new CompactionNeededError({
498
+ trigger: "operator",
499
+ signalSource: "operator",
500
+ signalTokens: session.lastInputTokens ?? 0,
501
+ thresholdTokens: compactionThresholdTokens(eventing.modelRunSettings),
502
+ }),
503
+ );
504
+ return { ok: { compactSummarizer } };
505
+ }
535
506
  if (requested) {
536
507
  try {
537
508
  outcome = await waitForTurnOperation(
@@ -579,22 +550,16 @@ export async function runPostAgentCompaction(
579
550
  {
580
551
  clearRequestedCompaction: true,
581
552
  publishLiveEvents: publishCompactionLiveEvents,
553
+ providerRejection: compactionProviderRejection(error),
582
554
  },
583
555
  );
584
556
  if (!isCompactionSummaryFailure(error)) throw error;
585
- const errorMessage = String(compactionFailureReasonFromError(error));
586
557
  if (
587
558
  !(await eventing.settle!({
588
559
  events: [
589
560
  {
590
561
  type: "turn.failed",
591
- payload: {
592
- error: errorMessage,
593
- code: "context_compaction_failed",
594
- retryable: false,
595
- recovery: "user_message",
596
- compacted: false,
597
- },
562
+ payload: compactionFailureTurnEventPayload(error),
598
563
  },
599
564
  {
600
565
  type: "session.status.changed",
@@ -645,6 +610,28 @@ export async function runPostAgentCompaction(
645
610
  return { exit: claimedResult({ status: "idle" }) };
646
611
  }
647
612
 
613
+ if (remoteCompactionRequester && session.codexCompactionMode === "remote_v2") {
614
+ const forced = await isSessionCompactionRequested(db, input.workspaceId, input.sessionId);
615
+ const thresholdTokens = compactionThresholdTokens(eventing.modelRunSettings);
616
+ if (
617
+ forced ||
618
+ ((attempt.triggerType === "user.message" ||
619
+ attempt.triggerType === "system.update.delivered") &&
620
+ (session.lastInputTokens ?? 0) >= thresholdTokens)
621
+ ) {
622
+ queuePreparedCompaction(
623
+ agent,
624
+ new CompactionNeededError({
625
+ trigger: forced ? "operator" : "threshold",
626
+ signalSource: forced ? "operator" : "provider",
627
+ signalTokens: session.lastInputTokens ?? 0,
628
+ thresholdTokens,
629
+ }),
630
+ );
631
+ }
632
+ return { ok: { compactSummarizer } };
633
+ }
634
+
648
635
  // Pre-turn durable context compaction. When the single Codex-parity
649
636
  // threshold is crossed, this summarizes active history and rebuilds active
650
637
  // history as [user messages..., summary] BEFORE the model input is read.
@@ -731,12 +718,12 @@ export async function runPostAgentCompaction(
731
718
  {
732
719
  clearRequestedCompaction: forced,
733
720
  publishLiveEvents: publishCompactionLiveEvents,
721
+ providerRejection: compactionProviderRejection(compactError),
734
722
  },
735
723
  );
736
724
  if (!isCompactionSummaryFailure(compactError)) throw compactError;
737
725
  const deferredSteer = await settleDeferredSteerAfterCompaction();
738
726
  if (deferredSteer) return { exit: deferredSteer };
739
- const errorMessage = String(compactionFailureReasonFromError(compactError));
740
727
  observability.error("context compaction failed", {
741
728
  sessionId: input.sessionId,
742
729
  turnId: attempt.turnId,
@@ -747,13 +734,7 @@ export async function runPostAgentCompaction(
747
734
  events: [
748
735
  {
749
736
  type: "turn.failed",
750
- payload: {
751
- error: errorMessage,
752
- code: "context_compaction_failed",
753
- retryable: false,
754
- recovery: "user_message",
755
- compacted: false,
756
- },
737
+ payload: compactionFailureTurnEventPayload(compactError),
757
738
  },
758
739
  { type: "session.status.changed", payload: { status: "idle" } },
759
740
  ],