@opengeni/worker-bundle 2.2.0-canary.36844267522001 → 2.2.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 (40) hide show
  1. package/dist/activities/agent-run-admission.d.ts +1 -3
  2. package/dist/activities/agent-turn/admission.d.ts +3 -24
  3. package/dist/activities/agent-turn/claude-usage-observer.d.ts +1 -13
  4. package/dist/activities/agent-turn/run-credentials.d.ts +0 -2
  5. package/dist/activities/agent-turn/stream-attempt.d.ts +0 -1
  6. package/dist/activities/agent-turn/turn-context.d.ts +0 -1
  7. package/dist/activities/goals.d.ts +0 -8
  8. package/dist/activities/run-credentials.d.ts +2 -4
  9. package/dist/activities/types.d.ts +1 -1
  10. package/dist/{activities-control-KQ5OK2GD.js → activities-control-MHNA3CYV.js} +66 -28
  11. package/dist/activities-control-MHNA3CYV.js.map +1 -0
  12. package/dist/{activities-turn-LSRAUGEK.js → activities-turn-FQ5OO2WW.js} +195 -459
  13. package/dist/activities-turn-FQ5OO2WW.js.map +1 -0
  14. package/dist/{chunk-WADNTBZZ.js → chunk-RZAAGRFQ.js} +64 -109
  15. package/dist/chunk-RZAAGRFQ.js.map +1 -0
  16. package/dist/index.js +1 -1
  17. package/dist/workflow-bundle.js +1 -1
  18. package/package.json +20 -20
  19. package/src/activities/agent-run-admission.ts +1 -17
  20. package/src/activities/agent-turn/admission.ts +1 -64
  21. package/src/activities/agent-turn/claim.ts +14 -56
  22. package/src/activities/agent-turn/claude-usage-observer.ts +1 -33
  23. package/src/activities/agent-turn/failure-settlement.ts +0 -5
  24. package/src/activities/agent-turn/run-credentials.ts +3 -15
  25. package/src/activities/agent-turn/run.ts +3 -32
  26. package/src/activities/agent-turn/stream-attempt.ts +32 -58
  27. package/src/activities/agent-turn/tool-environment.ts +20 -13
  28. package/src/activities/agent-turn/turn-context.ts +0 -1
  29. package/src/activities/capabilities.ts +14 -52
  30. package/src/activities/goals.ts +78 -36
  31. package/src/activities/knowledge-indexing.ts +0 -29
  32. package/src/activities/run-credentials.ts +16 -22
  33. package/src/activities/scheduled-tasks.ts +0 -1
  34. package/src/activities/types.ts +0 -1
  35. package/src/activities/workspace-credential-provider.ts +0 -12
  36. package/dist/activities/agent-turn/model-call-admission.d.ts +0 -15
  37. package/dist/activities-control-KQ5OK2GD.js.map +0 -1
  38. package/dist/activities-turn-LSRAUGEK.js.map +0 -1
  39. package/dist/chunk-WADNTBZZ.js.map +0 -1
  40. package/src/activities/agent-turn/model-call-admission.ts +0 -94
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengeni/worker-bundle",
3
- "version": "2.2.0-canary.36844267522001",
3
+ "version": "2.2.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": {
@@ -54,25 +54,25 @@
54
54
  },
55
55
  "dependencies": {
56
56
  "@llamaindex/liteparse": "2.14.2",
57
- "@opengeni/agent-proto": "^0.6.0-canary.36844267522001",
58
- "@opengeni/capabilities": "^0.3.4-canary.36844267522001",
59
- "@opengeni/codemode": "^0.6.5-canary.36844267522001",
60
- "@opengeni/codex": "^0.2.29-canary.36844267522001",
61
- "@opengeni/config": "^3.1.1-canary.36844267522001",
62
- "@opengeni/contracts": "^5.4.0-canary.36844267522001",
63
- "@opengeni/core": "^5.0.0-canary.36844267522001",
64
- "@opengeni/db": "^6.2.0-canary.36844267522001",
65
- "@opengeni/documents": "^0.8.37-canary.36844267522001",
66
- "@opengeni/events": "^0.4.35-canary.36844267522001",
67
- "@opengeni/github": "^0.8.0-canary.36844267522001",
68
- "@opengeni/jev": "^0.2.0-canary.36844267522001",
69
- "@opengeni/network": "^0.3.1-canary.36844267522001",
70
- "@opengeni/observability": "^0.8.35-canary.36844267522001",
71
- "@opengeni/runtime": "^4.3.0-canary.36844267522001",
72
- "@opengeni/sdk": "^7.4.0-canary.36844267522001",
73
- "@opengeni/storage": "^0.2.136-canary.36844267522001",
74
- "@opengeni/tool-gateway": "^0.1.16-canary.36844267522001",
75
- "@opengeni/xai-subscription": "^0.1.4-canary.36844267522001",
57
+ "@opengeni/agent-proto": "^0.6.0",
58
+ "@opengeni/capabilities": "^0.3.4",
59
+ "@opengeni/codemode": "^0.6.5",
60
+ "@opengeni/codex": "^0.2.29",
61
+ "@opengeni/config": "^3.1.1",
62
+ "@opengeni/contracts": "^5.4.0",
63
+ "@opengeni/core": "^5.0.0",
64
+ "@opengeni/db": "^6.2.0",
65
+ "@opengeni/documents": "^0.8.37",
66
+ "@opengeni/events": "^0.4.35",
67
+ "@opengeni/github": "^0.8.0",
68
+ "@opengeni/jev": "^0.2.0",
69
+ "@opengeni/network": "^0.3.1",
70
+ "@opengeni/observability": "^0.8.35",
71
+ "@opengeni/runtime": "^4.3.0",
72
+ "@opengeni/sdk": "^7.4.0",
73
+ "@opengeni/storage": "^0.2.136",
74
+ "@opengeni/tool-gateway": "^0.1.16",
75
+ "@opengeni/xai-subscription": "^0.1.4",
76
76
  "@temporalio/activity": "^1.17.0",
77
77
  "@temporalio/client": "^1.17.0",
78
78
  "@temporalio/worker": "^1.17.0",
@@ -1,16 +1,10 @@
1
1
  import { configuredStaticUsageLimits, type Settings } from "@opengeni/config";
2
2
  import { modelFundingForAdmission } from "@opengeni/core";
3
- import {
4
- checkWorkspaceAllowance,
5
- getBillingBalance,
6
- isCodexBilledTurn,
7
- sumUsageQuantity,
8
- } from "@opengeni/db";
3
+ import { getBillingBalance, isCodexBilledTurn, sumUsageQuantity } from "@opengeni/db";
9
4
  import type { ControlActivityServices } from "./types";
10
5
 
11
6
  export type AgentRunAdmissionDenial =
12
7
  | "insufficient_credits"
13
- | "allowance_exhausted"
14
8
  | "monthly_model_cost_limit"
15
9
  | "monthly_agent_run_limit";
16
10
 
@@ -22,8 +16,6 @@ export async function agentRunAdmissionDenial(
22
16
  workspaceId: string;
23
17
  model: string;
24
18
  requestedAgentRuns: number;
25
- /** The accepted work's causal human, not the scheduler/service caller. */
26
- initiatingHumanSubjectId?: string | null;
27
19
  },
28
20
  ): Promise<AgentRunAdmissionDenial | null> {
29
21
  const codexBilled = await isCodexBilledTurn({
@@ -54,14 +46,6 @@ export async function agentRunAdmissionDenial(
54
46
  if (balance.balanceMicros <= 0) return "insufficient_credits";
55
47
  }
56
48
  }
57
- if (!externallyBilled) {
58
- const refusal = await checkWorkspaceAllowance(services.db, {
59
- accountId: input.accountId,
60
- workspaceId: input.workspaceId,
61
- subjectId: input.initiatingHumanSubjectId ?? null,
62
- });
63
- if (refusal) return refusal.code;
64
- }
65
49
  if (
66
50
  services.settings.usageLimitsMode !== "static" &&
67
51
  services.settings.usageLimitsMode !== "managed"
@@ -1,4 +1,4 @@
1
- import { checkWorkspaceAllowance, getBillingBalance, sumUsageQuantity } from "@opengeni/db";
1
+ import { getBillingBalance, sumUsageQuantity } from "@opengeni/db";
2
2
  import {
3
3
  configuredStaticUsageLimits,
4
4
  resolveTurnExecutionPolicyV1,
@@ -8,7 +8,6 @@ import { selectCodexCredentialId } from "@opengeni/codex";
8
8
  import { directPersonalConnectionSubjectId } from "@opengeni/core";
9
9
  import type { TurnActivityServices as ActivityServices } from "../types";
10
10
  import {
11
- type AllowanceExhaustedRefusal,
12
11
  type SessionEvent,
13
12
  type SessionTurn,
14
13
  type ToolAuthNeededPayload,
@@ -244,65 +243,12 @@ export class BudgetExhaustedError extends Error {
244
243
  constructor(
245
244
  message: string,
246
245
  readonly serializedRunState: string | null,
247
- readonly allowance: AllowanceRefusal | null = null,
248
246
  ) {
249
247
  super(message);
250
248
  this.name = "BudgetExhaustedError";
251
249
  }
252
250
  }
253
251
 
254
- export type AllowanceRefusal = AllowanceExhaustedRefusal;
255
-
256
- /** Account allowance exhaustion is recoverable state, never a provider failure. */
257
- export class AllowanceExhaustedError extends Error {
258
- readonly code = "allowance_exhausted";
259
-
260
- constructor(readonly refusal: AllowanceRefusal) {
261
- super(refusal.message);
262
- this.name = "AllowanceExhaustedError";
263
- }
264
- }
265
-
266
- /** Revalidate between paid calls without replaying provider work or reserving credits. */
267
- export async function ensureRunAllowedBetweenModelCalls(input: {
268
- settings: Settings;
269
- db: ActivityServices["db"];
270
- accountId: string;
271
- workspaceId: string;
272
- isExternallyBilledTurn: boolean;
273
- entitlements?: ActivityServices["entitlements"];
274
- chargesOpenGeniCredits: boolean;
275
- countsTowardTokenCap: boolean;
276
- initiatingHumanSubjectId: string | null;
277
- serializedRunState?: () => string | null;
278
- }): Promise<void> {
279
- try {
280
- await ensureRunAllowed(
281
- input.settings,
282
- input.db,
283
- input.accountId,
284
- input.workspaceId,
285
- input.isExternallyBilledTurn,
286
- input.entitlements,
287
- input.chargesOpenGeniCredits,
288
- input.countsTowardTokenCap,
289
- input.initiatingHumanSubjectId,
290
- );
291
- } catch (limitError) {
292
- let serializedRunState: string | null = null;
293
- try {
294
- serializedRunState = input.serializedRunState?.() ?? null;
295
- } catch {
296
- // Durable history remains authoritative when the SDK state cannot serialize.
297
- }
298
- throw new BudgetExhaustedError(
299
- limitError instanceof Error ? limitError.message : String(limitError),
300
- serializedRunState,
301
- limitError instanceof AllowanceExhaustedError ? limitError.refusal : null,
302
- );
303
- }
304
- }
305
-
306
252
  // Exported for unit testing the external-billing bypass (codex-billing.test.ts); not
307
253
  // part of the activity surface. Takes the accepted policy's billing attribution and
308
254
  // the optional §7.5 P3 host `entitlements` port (when bound, its `admitRun` REPLACES
@@ -316,7 +262,6 @@ export async function ensureRunAllowed(
316
262
  entitlements?: ActivityServices["entitlements"],
317
263
  chargesOpenGeniCredits = !isExternallyBilledTurn,
318
264
  countsTowardTokenCap = !isExternallyBilledTurn,
319
- initiatingHumanSubjectId: string | null = null,
320
265
  ): Promise<void> {
321
266
  // Upstream settlement and workspace-facing cost are independent. External
322
267
  // metering skips the token cap; free/subscription/workspace cost skips the
@@ -357,14 +302,6 @@ export async function ensureRunAllowed(
357
302
  throw new Error("insufficient OpenGeni credits");
358
303
  }
359
304
  }
360
- if (chargesOpenGeniCredits) {
361
- const refusal = await checkWorkspaceAllowance(db, {
362
- accountId,
363
- workspaceId,
364
- subjectId: initiatingHumanSubjectId,
365
- });
366
- if (refusal) throw new AllowanceExhaustedError(refusal);
367
- }
368
305
  if (settings.usageLimitsMode === "static" || settings.usageLimitsMode === "managed") {
369
306
  const limits = configuredStaticUsageLimits(settings);
370
307
  if (limits.maxMonthlyAgentRunsPerWorkspace) {
@@ -62,8 +62,6 @@ import {
62
62
  turnExecutionPolicyBillingIdentity,
63
63
  legacyTurnExecutionPolicyInput,
64
64
  ensureRunAllowed,
65
- AllowanceExhaustedError,
66
- type AllowanceRefusal,
67
65
  } from "./admission";
68
66
  import { providerRecoveryCountFromMetadata, isWorkerShutdownCancellation } from "./errors";
69
67
  import { throwIfTurnOperationCancelled, waitForTurnOperation } from "./sandbox-provision";
@@ -370,27 +368,20 @@ export async function claimTurnAttempt(deps: ClaimTurnDeps): Promise<ClaimTurnOu
370
368
  // bypass OpenGeni credit/token gates)
371
369
  // AND the optional host `entitlements` port (when bound, its admitRun replaces
372
370
  // the local credit read). Unset port → today's local-ledger path.
373
- let allowanceRefusal: AllowanceRefusal | null = null;
374
- try {
375
- await waitForTurnOperation(
376
- ensureRunAllowed(
377
- capabilitySettings,
378
- db,
379
- input.accountId,
380
- input.workspaceId,
381
- billingState.isExternallyBilledTurn,
382
- entitlements,
383
- billingState.chargesOpenGeniCredits,
384
- billingState.countsTowardTokenCap,
385
- turn.initiatingHumanSubjectId,
386
- ),
387
- cancellationSignal,
388
- undefined,
389
- );
390
- } catch (error) {
391
- if (!(error instanceof AllowanceExhaustedError)) throw error;
392
- allowanceRefusal = error.refusal;
393
- }
371
+ await waitForTurnOperation(
372
+ ensureRunAllowed(
373
+ capabilitySettings,
374
+ db,
375
+ input.accountId,
376
+ input.workspaceId,
377
+ billingState.isExternallyBilledTurn,
378
+ entitlements,
379
+ billingState.chargesOpenGeniCredits,
380
+ billingState.countsTowardTokenCap,
381
+ ),
382
+ cancellationSignal,
383
+ undefined,
384
+ );
394
385
  // Setup (variableSet load, MCP connects, sandbox restore) does not
395
386
  // stream and so never observes cancellation on its own; these explicit
396
387
  // checks let a graceful shutdown checkpoint the turn before the worker is
@@ -523,9 +514,6 @@ export async function claimTurnAttempt(deps: ClaimTurnDeps): Promise<ClaimTurnOu
523
514
  ...(inputSettlement.suppressGoalContinuation !== undefined
524
515
  ? { suppressGoalContinuation: inputSettlement.suppressGoalContinuation }
525
516
  : {}),
526
- ...(inputSettlement.allowanceGoalPause
527
- ? { allowanceGoalPause: inputSettlement.allowanceGoalPause }
528
- : {}),
529
517
  events: inputs,
530
518
  ...(runState ? { runState } : {}),
531
519
  ...(compactionRequestFailure ? { compactionRequestFailure } : {}),
@@ -587,36 +575,6 @@ export async function claimTurnAttempt(deps: ClaimTurnDeps): Promise<ClaimTurnOu
587
575
  durationSeconds: (performance.now() - activityStarted) / 1_000,
588
576
  });
589
577
  const turnStartSettlementStartedAt = performance.now();
590
- if (allowanceRefusal) {
591
- // Claim has frozen the exact human, but no provider or sandbox has started.
592
- // Use the same terminal valve as a post-response stop, retaining a usable
593
- // session and a visible typed refusal instead of manufacturing a failure.
594
- if (
595
- !(await eventing.settle({
596
- events: [
597
- { type: "usage.exhausted", payload: allowanceRefusal },
598
- {
599
- type: "turn.completed",
600
- payload: {
601
- output: "",
602
- segmentLimit: "budget_exhausted",
603
- ...allowanceRefusal,
604
- },
605
- },
606
- { type: "session.status.changed", payload: { status: "idle" } },
607
- ],
608
- turnStatus: "completed",
609
- sessionStatus: "idle",
610
- activeTurnId: null,
611
- allowanceGoalPause: { rationale: allowanceRefusal.message },
612
- }))
613
- ) {
614
- return { exit: claimedResult({ status: "cancelled" }) };
615
- }
616
- control.turnMetricOutcome = "completed";
617
- control.activityStatus = "idle";
618
- return { exit: claimedResult({ status: "idle" }) };
619
- }
620
578
  if (
621
579
  !(await eventing.settle({
622
580
  events: [
@@ -35,17 +35,6 @@ export async function createClaudeUsageObserver(
35
35
  .map(async (provider) => {
36
36
  const scope: Scope =
37
37
  provider.kind === "claude-subscription-workspace" ? "workspace" : "organization";
38
- const binding = provider.anthropic?.credentialBinding;
39
- if (binding && provider.apiKey)
40
- return [
41
- provider.id,
42
- {
43
- scope,
44
- token: provider.apiKey,
45
- expectedConnectionId: binding.connectionId,
46
- expectedCredentialVersion: binding.credentialVersion,
47
- },
48
- ] as const;
49
38
  const credential = await readCredential(scope).catch(() => null);
50
39
  if (!credential || credential.token !== provider.apiKey) return null;
51
40
  return [
@@ -60,7 +49,7 @@ export async function createClaudeUsageObserver(
60
49
  }),
61
50
  );
62
51
  const captured = new Map(bindings.filter((binding) => binding !== null));
63
- const observe = (providerId: string, response: Response) => {
52
+ return (providerId: string, response: Response) => {
64
53
  const binding = captured.get(providerId);
65
54
  if (!binding) return;
66
55
  const { scope, ...identity } = binding;
@@ -87,25 +76,4 @@ export async function createClaudeUsageObserver(
87
76
  : {}),
88
77
  });
89
78
  };
90
- return Object.assign(observe, {
91
- binding(providerId: string) {
92
- return captured.get(providerId);
93
- },
94
- renew(
95
- providerId: string,
96
- credential: {
97
- token: string;
98
- connectionId: string;
99
- credentialVersion: number;
100
- },
101
- ) {
102
- const binding = captured.get(providerId);
103
- if (
104
- binding &&
105
- binding.expectedConnectionId === credential.connectionId &&
106
- binding.expectedCredentialVersion === credential.credentialVersion
107
- )
108
- captured.set(providerId, { ...binding, token: credential.token });
109
- },
110
- });
111
79
  }
@@ -1536,16 +1536,12 @@ export async function settleTurnFailure(deps: TurnFailureDeps): Promise<RunAgent
1536
1536
  if (
1537
1537
  !(await eventing.settle!({
1538
1538
  events: [
1539
- ...(error.allowance
1540
- ? [{ type: "usage.exhausted" as const, payload: error.allowance }]
1541
- : []),
1542
1539
  {
1543
1540
  type: "turn.completed",
1544
1541
  payload: {
1545
1542
  output: "",
1546
1543
  segmentLimit: "budget_exhausted",
1547
1544
  detail: error.message,
1548
- ...(error.allowance ?? {}),
1549
1545
  },
1550
1546
  },
1551
1547
  { type: "session.status.changed", payload: { status: "idle" } },
@@ -1553,7 +1549,6 @@ export async function settleTurnFailure(deps: TurnFailureDeps): Promise<RunAgent
1553
1549
  turnStatus: "completed",
1554
1550
  sessionStatus: "idle",
1555
1551
  activeTurnId: null,
1556
- ...(error.allowance ? { allowanceGoalPause: { rationale: error.allowance.message } } : {}),
1557
1552
  }))
1558
1553
  ) {
1559
1554
  return claimedResult({ status: "cancelled" });
@@ -28,8 +28,6 @@ import {
28
28
  type loadWorkspaceEnvironmentForRunWithCredentials,
29
29
  } from "../environment";
30
30
  import type { mergeResourceRefs } from "../common";
31
- import type { withFirstPartyTools } from "../goals";
32
- import { expandMcpAccountRoutes } from "../mcp-account-routes";
33
31
  import { startGitCredentialRenewalLoop } from "../git-credential-renewal";
34
32
  import {
35
33
  RUN_CREDENTIAL_EXPIRY_LEAD_MS,
@@ -76,7 +74,6 @@ import type {
76
74
 
77
75
  export type PrepareRunCredentialsDeps = {
78
76
  localMcpServerIds?: readonly string[];
79
- turnTools: ReturnType<typeof withFirstPartyTools>;
80
77
  input: RunAgentTurnInput;
81
78
  settings: Settings;
82
79
  db: ActivityServices["db"];
@@ -156,14 +153,6 @@ export async function prepareRunCredentials(deps: PrepareRunCredentialsDeps) {
156
153
  const platformGitResources = turnResources.filter(
157
154
  (resource) => resource.kind !== "repository" || repositoryHasExplicitGitConnection(resource),
158
155
  );
159
- // Credential targets follow the same accepted-account narrowing as execution.
160
- // A canonical connection without an accepted account does not execute, and
161
- // account-qualified aliases never inherit an attachment's product headers.
162
- const accountRoutes = expandMcpAccountRoutes({
163
- settings: runSettings,
164
- tools: deps.turnTools,
165
- bindings: turn.mcpAccountBindings,
166
- });
167
156
 
168
157
  const runCredentialResolver =
169
158
  effectiveRunCredentialBackend === "none" || effectiveRunCredentialBackend === "selfhosted"
@@ -171,11 +160,10 @@ export async function prepareRunCredentials(deps: PrepareRunCredentialsDeps) {
171
160
  : await waitForTurnOperation(
172
161
  bindRunCredentialResolver({
173
162
  db,
174
- settings: accountRoutes.settings,
163
+ settings: runSettings,
175
164
  initiatingHumanSubjectId: turn.initiatingHumanSubjectId ?? null,
176
165
  connectionCredentials: connectionCredentials ?? null,
177
166
  localMcpServerIds: deps.localMcpServerIds ?? [],
178
- effectiveTools: accountRoutes.tools,
179
167
  accountId: input.accountId,
180
168
  workspaceId: input.workspaceId,
181
169
  session,
@@ -226,9 +214,9 @@ export async function prepareRunCredentials(deps: PrepareRunCredentialsDeps) {
226
214
  : null;
227
215
  const runMcpCredentials = new RunMcpCredentials(
228
216
  selectedSessionRemoteMcpTargets(
229
- accountRoutes.settings,
217
+ runSettings,
230
218
  session.mcpServers ?? [],
231
- accountRoutes.tools,
219
+ turn.tools ?? [],
232
220
  (deps.localMcpServerIds ?? []).map((id) => ({ id })),
233
221
  ),
234
222
  {
@@ -3,8 +3,6 @@ import {
3
3
  readActiveSandbox,
4
4
  getWorkspaceCredentialProvider,
5
5
  loadClaudeSubscriptionUsageCredential,
6
- resolveClaudeSubscriptionCredential,
7
- ClaudeSubscriptionReconnectRequired,
8
6
  } from "@opengeni/db";
9
7
  import { routingEnabled } from "../../sandbox-routing";
10
8
  import { createKnowledgeSourceSyncActivities } from "../knowledge-source-sync";
@@ -28,7 +26,6 @@ import {
28
26
  import {
29
27
  REMOTE_COMPACTION_V2_BETA_FEATURE,
30
28
  REMOTE_COMPACTION_V2_IMPLEMENTATION,
31
- awaitModelCallAdmission,
32
29
  materializeSandboxFileDownloads,
33
30
  sandboxFileDownloadFailureNote,
34
31
  type SandboxFileDownload,
@@ -381,14 +378,12 @@ export function createRunAgentTurnActivity(services: () => Promise<ActivityServi
381
378
  getModelRunSettings: () => eventing.modelRunSettings,
382
379
  getExecutionGeneration: () => attempt.executionGeneration,
383
380
  });
384
- const checkpointBeforeProviderDispatch = async () => {
385
- await awaitModelCallAdmission();
386
- await checkpointHistoryBeforeProviderDispatch(historySink, {
381
+ const checkpointBeforeProviderDispatch = () =>
382
+ checkpointHistoryBeforeProviderDispatch(historySink, {
387
383
  effectiveSandboxBackend: eventing.modelRunSettings.sandboxBackend,
388
384
  routingEnabled: routingEnabled(settings),
389
385
  readActiveSandbox: () => readActiveSandbox(db, input.workspaceId, input.sessionId),
390
386
  });
391
- };
392
387
 
393
388
  try {
394
389
  const claimed = await claimTurnAttempt({
@@ -937,30 +932,7 @@ export function createRunAgentTurnActivity(services: () => Promise<ActivityServi
937
932
  }),
938
933
  );
939
934
  const withClaudeUsage = <T>(fn: () => Promise<T>): Promise<T> =>
940
- withClaudeUsageObserver(claudeUsageObserver, fn, async (providerId, headers) => {
941
- const binding = claudeUsageObserver.binding(providerId);
942
- if (!binding) return headers;
943
- const credential = await resolveClaudeSubscriptionCredential(
944
- db,
945
- settings,
946
- {
947
- accountId: input.accountId,
948
- workspaceId: input.workspaceId,
949
- scope: binding.scope,
950
- },
951
- {
952
- expectedConnectionId: binding.expectedConnectionId,
953
- expectedCredentialVersion: binding.expectedCredentialVersion,
954
- },
955
- );
956
- if (!credential) return headers; // A replaced connection never lends its new token to this turn.
957
- if ("reconnectRequired" in credential)
958
- throw new ClaudeSubscriptionReconnectRequired();
959
- claudeUsageObserver.renew(providerId, credential);
960
- headers.set("authorization", `Bearer ${credential.token}`);
961
- headers.delete("x-api-key");
962
- return headers;
963
- });
935
+ withClaudeUsageObserver(claudeUsageObserver, fn);
964
936
  const withCodex = <T>(fn: () => Promise<T>): Promise<T> =>
965
937
  codexContext ? codexRequestStorage.run(codexContext, fn) : fn();
966
938
  const withProviderRequestContext = <T>(fn: () => Promise<T>): Promise<T> =>
@@ -1203,7 +1175,6 @@ export function createRunAgentTurnActivity(services: () => Promise<ActivityServi
1203
1175
  );
1204
1176
 
1205
1177
  const runCredentials = await prepareRunCredentials({
1206
- turnTools,
1207
1178
  localMcpServerIds: installedApiIntegrations.map((integration) => integration.serverId),
1208
1179
  input,
1209
1180
  settings,
@@ -90,14 +90,14 @@ import {
90
90
  type SessionTurn,
91
91
  } from "@opengeni/contracts";
92
92
  import { createModelCheckpointMemoryCollector } from "../../model-checkpoint-memory-collector";
93
- import { createModelCallAdmission } from "./model-call-admission";
94
93
 
95
94
  import {
96
95
  assertWorkspaceHumanInputAllowed,
97
96
  stableHumanInputRequestId,
98
97
  stableInteractionInterventionId,
99
98
  stableInteractionInterventionOperationId,
100
- ensureRunAllowedBetweenModelCalls,
99
+ BudgetExhaustedError,
100
+ ensureRunAllowed,
101
101
  } from "./admission";
102
102
  import {
103
103
  compactionFailureReason,
@@ -235,7 +235,6 @@ export type TurnStreamAttemptDeps = {
235
235
  groupBoxBackend: Settings["sandboxBackend"];
236
236
  turnExecutionPolicy: TurnExecutionPolicyV1;
237
237
  turn: Pick<SessionTurn, "initiator" | "initiatorContext"> & {
238
- initiatingHumanSubjectId: string | null;
239
238
  id: string;
240
239
  executionGeneration: number;
241
240
  model: string;
@@ -584,39 +583,14 @@ export async function runTurnStreamAttempt(
584
583
  // durably: the reply a wait-ended human turn records on turn.completed.
585
584
  let latestAssistantMessageText: string | null = null;
586
585
  let workerPreparationTotalRecorded = false;
587
- const revalidateModelCallAdmission = async () => {
588
- await historySink.reconcileConversationTruth({ requireDurable: true });
589
- await ensureRunAllowedBetweenModelCalls({
590
- settings,
591
- db,
592
- accountId: input.accountId,
593
- workspaceId: input.workspaceId,
594
- isExternallyBilledTurn: billingState.isExternallyBilledTurn,
595
- entitlements,
596
- chargesOpenGeniCredits: billingState.chargesOpenGeniCredits,
597
- countsTowardTokenCap: billingState.countsTowardTokenCap,
598
- initiatingHumanSubjectId: turn.initiatingHumanSubjectId,
599
- });
600
- };
601
586
  const runStreamAttempt = async (options: {
602
587
  requireTerminalModelResponse: boolean;
603
588
  }): Promise<RunAgentTurnResult> => {
604
589
  if (!runInput) {
605
590
  throw new Error("Run input was not prepared");
606
591
  }
607
- // The previous stream was persisted before compaction; the sink is now
608
- // seeded from its durable replacement. Do not reconcile the old prefix
609
- // against that replacement while checking the next stream's admission.
610
- eventing.stream = undefined;
611
- // Compaction commits its paid usage and replacement history before this
612
- // boundary, both during preparation and in-activity recovery. Revalidate
613
- // the accepted turn's frozen human before another stream can dispatch.
614
- if (options.requireTerminalModelResponse) await revalidateModelCallAdmission();
615
- const modelCallAdmission = createModelCallAdmission({
616
- signal: runtimeCancellationSignal,
617
- admit: revalidateModelCallAdmission,
618
- });
619
592
  const responseCountBeforeStream = modelResponseState.responseCount;
593
+ eventing.stream = undefined;
620
594
  eventing.batcher = null;
621
595
  // The SDK emits every processed call item for one model response before
622
596
  // it emits any result for that response. Keep that response-local batch
@@ -832,8 +806,6 @@ export async function runTurnStreamAttempt(
832
806
  }
833
807
  attempt.modelRequestStarted = true;
834
808
  return await runtime.runStream(agent, runInput!, eventing.modelRunSettings, {
835
- beforeModelRequest: modelCallAdmission.beforeModelRequest,
836
- onModelResponse: modelCallAdmission.onModelResponse,
837
809
  signal: runtimeCancellationSignal,
838
810
  sandboxEnvironment,
839
811
  onModelVisibleContext: async (snapshot) => {
@@ -969,13 +941,7 @@ export async function runTurnStreamAttempt(
969
941
  if (leases.xai.lost) {
970
942
  throw new Error("xAI credential lease expired before the model run");
971
943
  }
972
- try {
973
- eventing.stream = await withProviderRequestContext(runStreamOnce);
974
- } catch (error) {
975
- modelCallAdmission.fail(error);
976
- modelCallAdmission.close();
977
- throw error;
978
- }
944
+ eventing.stream = await withProviderRequestContext(runStreamOnce);
979
945
  // Bounded provider label for the streaming SLIs — the resolved registry
980
946
  // provider id (or the built-in OpenAI/Azure provider), never a raw
981
947
  // user-supplied model string.
@@ -1128,22 +1094,35 @@ export async function runTurnStreamAttempt(
1128
1094
  await historySink.reconcileConversationTruth();
1129
1095
  turnLifecycleMetricsFor(observability).progress({ attemptId: input.attemptId });
1130
1096
  modelCheckpointMemoryCollector.schedule(observability);
1131
- await ensureRunAllowedBetweenModelCalls({
1132
- settings,
1133
- db,
1134
- accountId: input.accountId,
1135
- workspaceId: input.workspaceId,
1136
- isExternallyBilledTurn: billingState.isExternallyBilledTurn,
1137
- entitlements,
1138
- chargesOpenGeniCredits: billingState.chargesOpenGeniCredits,
1139
- countsTowardTokenCap: billingState.countsTowardTokenCap,
1140
- initiatingHumanSubjectId: turn.initiatingHumanSubjectId,
1141
- serializedRunState: () =>
1142
- media.compactMediaRunState(String(eventing.stream!.state.toString())),
1143
- });
1097
+ try {
1098
+ await ensureRunAllowed(
1099
+ settings,
1100
+ db,
1101
+ input.accountId,
1102
+ input.workspaceId,
1103
+ billingState.isExternallyBilledTurn,
1104
+ entitlements,
1105
+ billingState.chargesOpenGeniCredits,
1106
+ billingState.countsTowardTokenCap,
1107
+ );
1108
+ } catch (limitError) {
1109
+ // Capture the run state at the boundary so the budget valve in
1110
+ // the outer catch can end this segment gracefully with full
1111
+ // conversation context preserved for the post-top-up resume.
1112
+ let serializedRunState: string | null = null;
1113
+ try {
1114
+ serializedRunState = media.compactMediaRunState(
1115
+ String(eventing.stream.state.toString()),
1116
+ );
1117
+ } catch {
1118
+ serializedRunState = null;
1119
+ }
1120
+ throw new BudgetExhaustedError(
1121
+ limitError instanceof Error ? limitError.message : String(limitError),
1122
+ serializedRunState,
1123
+ );
1124
+ }
1144
1125
  }
1145
- // Release only after both the debit and frozen-human admission finish.
1146
- modelCallAdmission.settle(next.value);
1147
1126
  const durableSdkEvent = generatedImageReceipt
1148
1127
  ? compactGeneratedImageSdkEvent(next.value, generatedImageReceipt)
1149
1128
  : next.value;
@@ -1417,7 +1396,6 @@ export async function runTurnStreamAttempt(
1417
1396
  }
1418
1397
  }
1419
1398
  } catch (error) {
1420
- modelCallAdmission.fail(error);
1421
1399
  // Event processing can fail while SDK completion is still pending.
1422
1400
  // Close this stream before any failure publication; a legitimate
1423
1401
  // compaction retry may start a new, independently fenced generation.
@@ -1473,7 +1451,6 @@ export async function runTurnStreamAttempt(
1473
1451
  }
1474
1452
  throw error;
1475
1453
  } finally {
1476
- modelCallAdmission.close();
1477
1454
  if (!streamDone) {
1478
1455
  // ReadableStream cancellation synchronously trips the Agents SDK's
1479
1456
  // abort controller, but its returned promise may wait for an
@@ -1857,9 +1834,6 @@ export async function runTurnStreamAttempt(
1857
1834
  ) {
1858
1835
  return claimedResult({ status: "cancelled" });
1859
1836
  }
1860
- // Preparation may have spent the last allowance on a completed summary.
1861
- // Neither the title sidecar nor ordinary inference may dispatch afterward.
1862
- await revalidateModelCallAdmission();
1863
1837
  if (
1864
1838
  turn.source !== "compaction" &&
1865
1839
  generateSessionTitleInParallel &&