@opengeni/worker-bundle 2.2.0 → 2.2.1-canary.36927100590001

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 (88) hide show
  1. package/dist/activities/agent-run-admission.d.ts +3 -1
  2. package/dist/activities/agent-turn/admission.d.ts +24 -3
  3. package/dist/activities/agent-turn/agent-build.d.ts +1 -0
  4. package/dist/activities/agent-turn/claude-usage-observer.d.ts +13 -1
  5. package/dist/activities/agent-turn/compaction-prep.d.ts +20 -0
  6. package/dist/activities/agent-turn/credential-restriction.d.ts +3 -0
  7. package/dist/activities/agent-turn/final-reply.d.ts +18 -0
  8. package/dist/activities/agent-turn/governance-model.d.ts +6 -0
  9. package/dist/activities/agent-turn/model-call-admission.d.ts +15 -0
  10. package/dist/activities/agent-turn/run-credentials.d.ts +4 -0
  11. package/dist/activities/agent-turn/sandbox-establish.d.ts +1 -0
  12. package/dist/activities/agent-turn/session-title.d.ts +3 -1
  13. package/dist/activities/agent-turn/stream-attempt.d.ts +1 -0
  14. package/dist/activities/agent-turn/turn-context.d.ts +1 -0
  15. package/dist/activities/automations.d.ts +3 -1
  16. package/dist/activities/browser-deadline-checkpoint.d.ts +29 -0
  17. package/dist/activities/goals.d.ts +8 -0
  18. package/dist/activities/run-credentials.d.ts +4 -2
  19. package/dist/activities/scheduled-tasks.d.ts +4 -35
  20. package/dist/activities/types.d.ts +4 -1
  21. package/dist/activities/workspace-capture.d.ts +2 -0
  22. package/dist/{activities-control-MHNA3CYV.js → activities-control-4F2A734B.js} +502 -133
  23. package/dist/activities-control-4F2A734B.js.map +1 -0
  24. package/dist/activities-control.d.ts +30 -0
  25. package/dist/{activities-turn-FQ5OO2WW.js → activities-turn-TESOIOEX.js} +696 -251
  26. package/dist/activities-turn-TESOIOEX.js.map +1 -0
  27. package/dist/activities.d.ts +30 -0
  28. package/dist/browser-deadline-checkpoint-contract.d.ts +2 -0
  29. package/dist/{chunk-RZAAGRFQ.js → chunk-4PJTUBWQ.js} +220 -88
  30. package/dist/chunk-4PJTUBWQ.js.map +1 -0
  31. package/dist/{chunk-IJZU752L.js → chunk-YG27NEMX.js} +34 -1
  32. package/dist/chunk-YG27NEMX.js.map +1 -0
  33. package/dist/index.d.ts +15 -0
  34. package/dist/index.js +46 -24
  35. package/dist/index.js.map +1 -1
  36. package/dist/observability-metrics.d.ts +16 -1
  37. package/dist/sandbox-resume.d.ts +4 -1
  38. package/dist/workflow-bundle.js +89 -21
  39. package/dist/workflows/browser-deadline-checkpoint.d.ts +9 -0
  40. package/dist/workflows/scheduled-tasks.d.ts +4 -0
  41. package/dist/workflows.d.ts +1 -0
  42. package/package.json +21 -20
  43. package/src/activities/agent-run-admission.ts +17 -1
  44. package/src/activities/agent-turn/admission.ts +64 -1
  45. package/src/activities/agent-turn/agent-build.ts +24 -3
  46. package/src/activities/agent-turn/claim.ts +69 -15
  47. package/src/activities/agent-turn/claude-usage-observer.ts +33 -1
  48. package/src/activities/agent-turn/compaction-prep.ts +67 -16
  49. package/src/activities/agent-turn/credential-restriction.ts +14 -0
  50. package/src/activities/agent-turn/errors.ts +55 -0
  51. package/src/activities/agent-turn/failure-settlement.ts +26 -6
  52. package/src/activities/agent-turn/final-reply.ts +46 -0
  53. package/src/activities/agent-turn/governance-model.ts +12 -0
  54. package/src/activities/agent-turn/model-call-admission.ts +94 -0
  55. package/src/activities/agent-turn/run-credentials.ts +20 -3
  56. package/src/activities/agent-turn/run.ts +44 -5
  57. package/src/activities/agent-turn/sandbox-establish.ts +9 -5
  58. package/src/activities/agent-turn/session-title.ts +8 -2
  59. package/src/activities/agent-turn/stream-attempt.ts +144 -38
  60. package/src/activities/agent-turn/tool-environment.ts +55 -39
  61. package/src/activities/agent-turn/turn-context.ts +1 -0
  62. package/src/activities/automations.ts +78 -4
  63. package/src/activities/browser-deadline-checkpoint.ts +279 -0
  64. package/src/activities/capabilities.ts +52 -14
  65. package/src/activities/goals.ts +95 -98
  66. package/src/activities/knowledge-indexing.ts +29 -0
  67. package/src/activities/open-suffix-resume.ts +2 -1
  68. package/src/activities/run-credentials.ts +22 -16
  69. package/src/activities/sandbox-lease.ts +22 -0
  70. package/src/activities/scheduled-tasks.ts +172 -38
  71. package/src/activities/site-auth-maintenance.ts +1 -0
  72. package/src/activities/types.ts +4 -0
  73. package/src/activities/workspace-capture.ts +13 -2
  74. package/src/activities/workspace-credential-provider.ts +12 -0
  75. package/src/activities-control.ts +2 -0
  76. package/src/activities.ts +3 -0
  77. package/src/browser-deadline-checkpoint-contract.ts +5 -0
  78. package/src/index.ts +53 -25
  79. package/src/observability-metrics.ts +55 -1
  80. package/src/sandbox-resume.ts +23 -8
  81. package/src/sandbox-routing.ts +4 -2
  82. package/src/workflows/browser-deadline-checkpoint.ts +50 -0
  83. package/src/workflows/scheduled-tasks.ts +26 -13
  84. package/src/workflows.ts +4 -0
  85. package/dist/activities-control-MHNA3CYV.js.map +0 -1
  86. package/dist/activities-turn-FQ5OO2WW.js.map +0 -1
  87. package/dist/chunk-IJZU752L.js.map +0 -1
  88. package/dist/chunk-RZAAGRFQ.js.map +0 -1
@@ -20,6 +20,21 @@ export declare function createActivityTestHarness(dependencies?: ActivityDepende
20
20
  } | null>;
21
21
  reconcileCodexCapacityWait: (input: import("./activities.js").ReconcileCodexCapacityWaitInput) => Promise<import("./activities.js").ReconcileCodexCapacityWaitResult>;
22
22
  maintainBrowserStateArtifacts: () => Promise<import("./activities/browser-state-artifact-reaper.js").MaintainBrowserStateArtifactsResult>;
23
+ listDueBrowserCheckpoints(): Promise<{
24
+ accountId: string;
25
+ workspaceId: string;
26
+ sandboxGroupId: string;
27
+ leaseId: string;
28
+ leaseEpoch: number;
29
+ instanceId: string;
30
+ browserSessionId: string;
31
+ controllerGeneration: string;
32
+ }[]>;
33
+ checkpointBrowserBeforeDeadline(target: import("@opengeni/db").BrowserDeadlineCheckpointTarget): Promise<{
34
+ status: "skipped";
35
+ } | {
36
+ status: "suspended";
37
+ }>;
23
38
  settleAutomationRunFailure: (input: import("./activities.js").DispatchAutomationRunInput) => Promise<void>;
24
39
  dispatchAutomationRun: (input: import("./activities.js").DispatchAutomationRunInput) => Promise<import("./activities.js").DispatchAutomationRunResult>;
25
40
  indexDocument: (input: import("./activities.js").IndexDocumentInput) => Promise<{
@@ -368,6 +383,21 @@ export declare const getCodexCapacityWait: (input: import("./activities.js").Get
368
383
  } | null>;
369
384
  export declare const reconcileCodexCapacityWait: (input: import("./activities.js").ReconcileCodexCapacityWaitInput) => Promise<import("./activities.js").ReconcileCodexCapacityWaitResult>;
370
385
  export declare const prepareSandboxLeaseSweep: () => Promise<import("./activities/sandbox-lease.js").SandboxLeaseSweepPlan>;
386
+ export declare const listDueBrowserCheckpoints: () => Promise<{
387
+ accountId: string;
388
+ workspaceId: string;
389
+ sandboxGroupId: string;
390
+ leaseId: string;
391
+ leaseEpoch: number;
392
+ instanceId: string;
393
+ browserSessionId: string;
394
+ controllerGeneration: string;
395
+ }[]>;
396
+ export declare const checkpointBrowserBeforeDeadline: (target: import("@opengeni/db").BrowserDeadlineCheckpointTarget) => Promise<{
397
+ status: "skipped";
398
+ } | {
399
+ status: "suspended";
400
+ }>;
371
401
  export declare const drainSandboxLease: (input: import("./sandbox-reaper-contract.js").SandboxDrainActivityInput) => Promise<import("./activities/sandbox-lease.js").SandboxDrainActivityResult>;
372
402
  export declare const maintainSandboxLeaseSweep: (input: import("./sandbox-reaper-contract.js").SandboxLeaseSweepMaintenanceInput) => Promise<import("./activities/sandbox-lease.js").SandboxLeaseSweepMaintenanceResult>;
373
403
  export declare const reapSandboxLeases: () => Promise<import("./activities/sandbox-lease.js").ReapSandboxLeasesResult>;
@@ -0,0 +1,2 @@
1
+ export declare const BROWSER_DEADLINE_CHECKPOINT_SWEEP_ID = "opengeni-browser-deadline-checkpoints-v1";
2
+ export declare function browserDeadlineCheckpointTaskQueue(base: string): string;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  observabilityEventBusOptions
3
- } from "./chunk-IJZU752L.js";
3
+ } from "./chunk-YG27NEMX.js";
4
4
 
5
5
  // src/activity-services.ts
6
6
  import {
@@ -1242,7 +1242,8 @@ function createDocumentActivities(services, resolveDocumentServices) {
1242
1242
  // src/activities/goals.ts
1243
1243
  import {
1244
1244
  allowedFirstPartyMcpToolsForSession,
1245
- configuredStaticUsageLimits,
1245
+ configuredStaticUsageLimits as configuredStaticUsageLimits2,
1246
+ isModelAvailableForNewSelection,
1246
1247
  policyProviderIdForModel,
1247
1248
  resolveModelProvider,
1248
1249
  resolveTurnExecutionPolicyV1,
@@ -1253,24 +1254,106 @@ import {
1253
1254
  } from "@opengeni/config";
1254
1255
  import {
1255
1256
  evaluateWorkspaceModelPolicy,
1256
- mergeToolRefs
1257
+ mergeToolRefs,
1258
+ readTurnExecutionPolicyV1 as readTurnExecutionPolicyV12
1257
1259
  } from "@opengeni/contracts";
1258
1260
  import { isCodexBilledModel } from "@opengeni/codex";
1259
1261
  import {
1260
1262
  enqueueSessionWorkflowWakeIfRunnable,
1261
- getBillingBalance,
1262
1263
  getWorkspaceModelPolicy,
1263
1264
  getSessionGoal,
1264
- isCodexBilledTurn,
1265
+ getSessionTurn,
1265
1266
  materializeGoalContinuation,
1266
- requireSession,
1267
- sumUsageQuantity
1267
+ requireSession
1268
1268
  } from "@opengeni/db";
1269
1269
  import {
1270
- modelFundingForAdmission,
1270
+ modelFundingForAdmission as modelFundingForAdmission2,
1271
1271
  resolveCatalogSettings as resolveCatalogSettings2,
1272
1272
  resolveWorkspaceCatalogSettings
1273
1273
  } from "@opengeni/core";
1274
+
1275
+ // src/activities/agent-run-admission.ts
1276
+ import { configuredStaticUsageLimits } from "@opengeni/config";
1277
+ import { modelFundingForAdmission } from "@opengeni/core";
1278
+ import {
1279
+ checkWorkspaceAllowance,
1280
+ getBillingBalance,
1281
+ isCodexBilledTurn,
1282
+ sumUsageQuantity
1283
+ } from "@opengeni/db";
1284
+ async function agentRunAdmissionDenial(services, input) {
1285
+ const codexBilled = await isCodexBilledTurn({
1286
+ db: services.db,
1287
+ settings: services.settings,
1288
+ workspaceId: input.workspaceId,
1289
+ model: input.model
1290
+ });
1291
+ const externallyBilled = modelFundingForAdmission(
1292
+ services.settings,
1293
+ input.model,
1294
+ codexBilled
1295
+ ).fundedWithoutCredits;
1296
+ if (!externallyBilled && (services.settings.billingMode === "stripe" || services.settings.usageLimitsMode === "managed")) {
1297
+ if (services.entitlements) {
1298
+ const decision = await services.entitlements.admitRun({
1299
+ accountId: input.accountId,
1300
+ workspaceId: input.workspaceId,
1301
+ action: "agent_run:create",
1302
+ quantity: input.requestedAgentRuns
1303
+ });
1304
+ if (!decision.allowed) return "insufficient_credits";
1305
+ } else {
1306
+ const balance = await getBillingBalance(services.db, input.accountId);
1307
+ if (balance.balanceMicros <= 0) return "insufficient_credits";
1308
+ }
1309
+ }
1310
+ if (!externallyBilled) {
1311
+ const refusal = await checkWorkspaceAllowance(services.db, {
1312
+ accountId: input.accountId,
1313
+ workspaceId: input.workspaceId,
1314
+ subjectId: input.initiatingHumanSubjectId ?? null
1315
+ });
1316
+ if (refusal) return refusal.code;
1317
+ }
1318
+ if (services.settings.usageLimitsMode !== "static" && services.settings.usageLimitsMode !== "managed") {
1319
+ return null;
1320
+ }
1321
+ const limits = configuredStaticUsageLimits(services.settings);
1322
+ if (!externallyBilled && limits.maxMonthlyCostMicrosPerAccount) {
1323
+ const used = await sumUsageQuantity(services.db, {
1324
+ accountId: input.accountId,
1325
+ eventType: "model.cost",
1326
+ since: startOfUtcMonth()
1327
+ });
1328
+ if (used >= limits.maxMonthlyCostMicrosPerAccount) {
1329
+ return "monthly_model_cost_limit";
1330
+ }
1331
+ }
1332
+ if (limits.maxMonthlyAgentRunsPerWorkspace) {
1333
+ const used = await sumUsageQuantity(services.db, {
1334
+ workspaceId: input.workspaceId,
1335
+ eventType: "agent_run.created",
1336
+ since: startOfUtcMonth()
1337
+ });
1338
+ if (used + input.requestedAgentRuns > limits.maxMonthlyAgentRunsPerWorkspace) {
1339
+ return "monthly_agent_run_limit";
1340
+ }
1341
+ }
1342
+ return null;
1343
+ }
1344
+ function startOfUtcMonth() {
1345
+ const now = /* @__PURE__ */ new Date();
1346
+ return new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), 1));
1347
+ }
1348
+
1349
+ // src/activities/agent-turn/credential-restriction.ts
1350
+ import { readTurnExecutionPolicyV1 } from "@opengeni/contracts";
1351
+ function turnCredentialRestriction(acceptedPolicy, initialSessionMetadata) {
1352
+ const initialPolicy = readTurnExecutionPolicyV1(initialSessionMetadata);
1353
+ return acceptedPolicy.credentialRestriction === "developer_setup" || initialPolicy.kind === "valid" && initialPolicy.policy.credentialRestriction === "developer_setup" ? "developer_setup" : void 0;
1354
+ }
1355
+
1356
+ // src/activities/goals.ts
1274
1357
  function createGoalActivities(services) {
1275
1358
  async function enqueueGoalRetryWake(input) {
1276
1359
  const { db } = await services();
@@ -1293,8 +1376,11 @@ function createGoalActivities(services) {
1293
1376
  if (!existingGoal || existingGoal.status !== "active") {
1294
1377
  return { action: "none" };
1295
1378
  }
1296
- let settings = (await resolveCatalogSettings2(db, catalogSourceSettings)).settings;
1297
1379
  const session = await requireSession(db, input.workspaceId, input.sessionId);
1380
+ if (session.status === "failed" || session.status === "cancelled") {
1381
+ return { action: "none" };
1382
+ }
1383
+ let settings = (await resolveCatalogSettings2(db, catalogSourceSettings)).settings;
1298
1384
  const inheritedContinuationModel = session.model;
1299
1385
  let continuationModel = inheritedContinuationModel;
1300
1386
  const continuationReasoningEffort = session.reasoningEffort;
@@ -1317,25 +1403,7 @@ function createGoalActivities(services) {
1317
1403
  if (!modelPolicyBlocked && session.codexCompactionMode === "remote_v2" && !isCodexBilledModel(continuationModel)) {
1318
1404
  modelPolicyBlocked = `session is locked to Codex remote compaction v2; model "${continuationModel}" is not a Codex subscription model`;
1319
1405
  }
1320
- const isCodexRun = await isCodexBilledTurn({
1321
- db,
1322
- settings,
1323
- workspaceId: input.workspaceId,
1324
- model: continuationModel
1325
- });
1326
- const fundedWithoutCredits = goalContinuationFundedWithoutCredits(
1327
- settings,
1328
- continuationModel,
1329
- isCodexRun
1330
- );
1331
- const budgetBlocked = await goalRunBudgetBlocked(
1332
- settings,
1333
- db,
1334
- input.accountId,
1335
- input.workspaceId,
1336
- fundedWithoutCredits
1337
- );
1338
- const turnExecutionPolicy = resolveTurnExecutionPolicyV1(settings, {
1406
+ const turnExecutionPolicy = modelPolicyBlocked ? void 0 : resolveTurnExecutionPolicyV1(settings, {
1339
1407
  modelId: continuationModel,
1340
1408
  requestedModelId: null,
1341
1409
  modelSource: "continuation",
@@ -1344,6 +1412,14 @@ function createGoalActivities(services) {
1344
1412
  latencyMode: continuationLatencyMode,
1345
1413
  latencyModeSource: "continuation"
1346
1414
  });
1415
+ const continuationPolicy = {
1416
+ model: continuationModel,
1417
+ reasoningEffort: continuationReasoningEffort,
1418
+ latencyMode: continuationLatencyMode,
1419
+ ...turnExecutionPolicy ? { turnExecutionPolicy } : {},
1420
+ tools: withFirstPartyTools(settings, session.tools),
1421
+ sandboxBackend: session.sandboxBackend
1422
+ };
1347
1423
  const decision = await materializeGoalContinuation(db, {
1348
1424
  accountId: input.accountId,
1349
1425
  workspaceId: input.workspaceId,
@@ -1359,15 +1435,34 @@ function createGoalActivities(services) {
1359
1435
  // A model-policy block takes precedence: it is deterministic (a budget
1360
1436
  // pause can clear on its own; a policy pause needs a model/policy change)
1361
1437
  // and rides the same visible-pause channel.
1362
- budgetBlocked: modelPolicyBlocked ?? budgetBlocked,
1363
- policy: {
1364
- model: continuationModel,
1365
- reasoningEffort: continuationReasoningEffort,
1366
- latencyMode: continuationLatencyMode,
1367
- turnExecutionPolicy,
1368
- tools: withFirstPartyTools(settings, session.tools),
1369
- sandboxBackend: session.sandboxBackend
1438
+ admission: async (tx, causalTurn) => {
1439
+ const sourceTurn = causalTurn ? await getSessionTurn(tx, input.workspaceId, causalTurn.id) : null;
1440
+ if (causalTurn && (!sourceTurn || sourceTurn.sessionId !== input.sessionId)) {
1441
+ throw new Error("Goal continuation source turn is unavailable");
1442
+ }
1443
+ const sourcePolicy = readTurnExecutionPolicyV12(sourceTurn?.metadata);
1444
+ if (turnExecutionPolicy) {
1445
+ const credentialRestriction = turnCredentialRestriction(
1446
+ sourcePolicy.kind === "valid" ? sourcePolicy.policy : turnExecutionPolicy,
1447
+ session.metadata
1448
+ );
1449
+ continuationPolicy.turnExecutionPolicy = credentialRestriction ? { ...turnExecutionPolicy, credentialRestriction } : turnExecutionPolicy;
1450
+ }
1451
+ const budgetBlocked = modelPolicyBlocked ? null : await goalRunBudgetBlocked(
1452
+ { ...service, settings, db: tx },
1453
+ {
1454
+ accountId: input.accountId,
1455
+ workspaceId: input.workspaceId,
1456
+ model: continuationModel,
1457
+ initiatingHumanSubjectId: causalTurn?.initiatingHumanSubjectId ?? null
1458
+ }
1459
+ );
1460
+ return {
1461
+ budgetBlocked: modelPolicyBlocked ?? budgetBlocked?.message ?? null,
1462
+ budgetPausedReason: modelPolicyBlocked ? "limits" : budgetBlocked?.pausedReason ?? "limits"
1463
+ };
1370
1464
  },
1465
+ policy: continuationPolicy,
1371
1466
  // Long-wait guidance is only given when `wait_for_input` is actually in this
1372
1467
  // session's effective first-party selection (the same source the worker
1373
1468
  // signs into the delegated token and the API uses to register tools), so
@@ -1403,23 +1498,26 @@ function goalContinuationModelDecision(input) {
1403
1498
  providerId: policyProviderIdForModel(catalogSettings, modelId),
1404
1499
  modelId
1405
1500
  }).allowed;
1406
- if (resolveModelProvider(catalogSettings, input.inheritedModel) && !policyBlocks(input.inheritedModel)) {
1407
- return { model: input.inheritedModel, blocked: null };
1408
- }
1409
1501
  if (!resolveModelProvider(catalogSettings, input.inheritedModel)) {
1410
1502
  return {
1411
1503
  model: input.inheritedModel,
1412
1504
  blocked: `model "${input.inheritedModel}" is no longer in the deployment or workspace catalog; choose an available model before resuming the goal`
1413
1505
  };
1414
1506
  }
1507
+ if (!isModelAvailableForNewSelection(catalogSettings, input.inheritedModel)) {
1508
+ return {
1509
+ model: input.inheritedModel,
1510
+ blocked: `model "${input.inheritedModel}" is retired from new selection; choose an available model before resuming the goal`
1511
+ };
1512
+ }
1513
+ if (!policyBlocks(input.inheritedModel)) {
1514
+ return { model: input.inheritedModel, blocked: null };
1515
+ }
1415
1516
  return {
1416
1517
  model: input.inheritedModel,
1417
1518
  blocked: `workspace model policy blocks model "${input.inheritedModel}"; pick an allowed model or change the workspace model policy`
1418
1519
  };
1419
1520
  }
1420
- function goalContinuationFundedWithoutCredits(settings, model, codexBilled) {
1421
- return modelFundingForAdmission(settings, model, codexBilled).fundedWithoutCredits;
1422
- }
1423
1521
  function goalContinuationPrompt(_goal, _autoContinuation, _cap, options = {}) {
1424
1522
  const waitingGuidance = options.inputWaitAvailable ? [
1425
1523
  "Waiting on child sessions, background commands, or external events:",
@@ -1475,6 +1573,8 @@ function goalContinuationPrompt(_goal, _autoContinuation, _cap, options = {}) {
1475
1573
  "- For document report deliverables (a document the user asked for, or a large report meant to be kept or shared), follow the Documents Skill: create the durable native document first, inspect its relevant final head after the last edit, and provide the returned artifact reference. Declare report requirements through the available goal tools before authoring and satisfy every persisted report requirement with verified artifact delivery evidence before completion. Sandbox paths and raw file IDs do not prove report delivery. If artifact tooling or access is unavailable, keep that deliverable incomplete and state the blocker; never invent proof or silently substitute a local report. Ordinary chat answers, short progress updates, source-code links, and explicitly requested local-file work remain outside this report contract.",
1476
1574
  "",
1477
1575
  "Do not rely on intent, partial progress, memory of earlier work, or a plausible final answer as proof of completion. Call opengeni__goal_complete with concrete evidence only when the full objective is actually achieved and no required work remains.",
1576
+ "Goal evidence is a short proof for the ledger, not the deliverable. After goal_complete succeeds, finish this same turn with the requested user-facing answer, or a concise summary and retained artifact link. Goal completion stops future automatic continuations; it does not send the answer or end this turn. Never compress a report into evidence or omit the final reply.",
1577
+ "Goal progress notes are short human-readable milestone statuses, not raw transcripts or continuation instructions. Keep normal spaces and summarize detail instead of squeezing words into a ledger field. The text and successCriteria fields each allow 8192 UTF-8 bytes, progressNote allows 8192 UTF-8 bytes, rationale allows 2048 UTF-8 bytes, and evidence allows 8192 characters.",
1478
1578
  "",
1479
1579
  ...waitingGuidance,
1480
1580
  ...childNoticeGuidance,
@@ -1494,41 +1594,19 @@ function withFirstPartyTools(settings, tools) {
1494
1594
  }
1495
1595
  return mergeToolRefs(tools, [{ kind: "mcp", id: "opengeni" }]);
1496
1596
  }
1497
- async function goalRunBudgetBlocked(settings, db, accountId, workspaceId, fundedWithoutCredits) {
1498
- if (!fundedWithoutCredits && (settings.billingMode === "stripe" || settings.usageLimitsMode === "managed")) {
1499
- const balance = await getBillingBalance(db, accountId);
1500
- if (balance.balanceMicros <= 0) {
1501
- return "insufficient OpenGeni credits";
1502
- }
1503
- }
1504
- if (settings.usageLimitsMode === "static" || settings.usageLimitsMode === "managed") {
1505
- const limits = configuredStaticUsageLimits(settings);
1506
- if (!fundedWithoutCredits && limits.maxMonthlyCostMicrosPerAccount) {
1507
- const used = await sumUsageQuantity(db, {
1508
- accountId,
1509
- eventType: "model.cost",
1510
- since: startOfUtcMonth()
1511
- });
1512
- if (used >= limits.maxMonthlyCostMicrosPerAccount) {
1513
- return `monthly model cost limit reached (${limits.maxMonthlyCostMicrosPerAccount} micros)`;
1514
- }
1515
- }
1516
- if (limits.maxMonthlyAgentRunsPerWorkspace) {
1517
- const used = await sumUsageQuantity(db, {
1518
- workspaceId,
1519
- eventType: "agent_run.created",
1520
- since: startOfUtcMonth()
1521
- });
1522
- if (used + 1 > limits.maxMonthlyAgentRunsPerWorkspace) {
1523
- return `monthly agent run limit reached (${limits.maxMonthlyAgentRunsPerWorkspace})`;
1524
- }
1525
- }
1526
- }
1527
- return null;
1528
- }
1529
- function startOfUtcMonth() {
1530
- const now = /* @__PURE__ */ new Date();
1531
- return new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), 1));
1597
+ async function goalRunBudgetBlocked(services, input) {
1598
+ const denial = await agentRunAdmissionDenial(services, { ...input, requestedAgentRuns: 1 });
1599
+ if (denial === null) return null;
1600
+ if (denial === "allowance_exhausted") {
1601
+ return { pausedReason: "allowance", message: "OpenGeni usage allowance exhausted" };
1602
+ }
1603
+ const limits = configuredStaticUsageLimits2(services.settings);
1604
+ const messages = {
1605
+ insufficient_credits: "insufficient OpenGeni credits",
1606
+ monthly_model_cost_limit: `monthly model cost limit reached (${limits.maxMonthlyCostMicrosPerAccount} micros)`,
1607
+ monthly_agent_run_limit: `monthly agent run limit reached (${limits.maxMonthlyAgentRunsPerWorkspace})`
1608
+ };
1609
+ return { pausedReason: "limits", message: messages[denial] };
1532
1610
  }
1533
1611
 
1534
1612
  // src/activities/knowledge-source-sync.ts
@@ -5250,9 +5328,9 @@ var WARMING_POLL_INTERVAL_MS = 250;
5250
5328
  async function sleep(ms) {
5251
5329
  await new Promise((resolve) => setTimeout(resolve, ms));
5252
5330
  }
5253
- async function waitForSandboxExecReadiness(established, timeoutMs = MODAL_EXEC_READINESS_TIMEOUT_MS, identity = {}) {
5331
+ async function waitForSandboxExecReadiness(established, timeoutMs = MODAL_EXEC_READINESS_TIMEOUT_MS, identity = {}, signal) {
5254
5332
  try {
5255
- await verifySandboxExecReadiness(established, timeoutMs);
5333
+ await verifySandboxExecReadiness(established, timeoutMs, signal);
5256
5334
  } catch (error) {
5257
5335
  if (error instanceof SandboxExecReadinessError && error.code === "exec_probe_timeout") {
5258
5336
  throw new SandboxExecReadinessTimeoutError(established.backendId, timeoutMs, {
@@ -5830,11 +5908,12 @@ async function resumeBoxForTurnOnce(services, ids, kind, holderId) {
5830
5908
  },
5831
5909
  os,
5832
5910
  // IMAGE IS SHARED STATE (B3): thread the resolved image so the lease stamps it +
5833
- // conflicts on a live box already running a different image. A
5911
+ // conflicts on a live box already running a different required image. A
5834
5912
  // SandboxImageConflictError propagates while another holder is active; a
5835
5913
  // solo change requests a capture-and-drain rotation and this attempt retries
5836
5914
  // after the cold successor can safely stamp the new image.
5837
5915
  ...ids.image ? { image: ids.image } : {},
5916
+ ...ids.imagePolicy ? { imagePolicy: ids.imagePolicy } : {},
5838
5917
  // RIG IS SHARED STATE (M3): thread the frozen rig version so the lease stamps it
5839
5918
  // + conflicts on a live box under a different rig. A SandboxRigConflictError
5840
5919
  // propagates while another holder is active; a solo change uses the same
@@ -6236,9 +6315,14 @@ async function resumeBoxForTurnOnce(services, ids, kind, holderId) {
6236
6315
  sandboxGroupId: ids.sandboxGroupId
6237
6316
  });
6238
6317
  } else {
6239
- await waitForSandboxExecReadiness(established, MODAL_EXEC_READINESS_TIMEOUT_MS, {
6240
- sandboxGroupId: ids.sandboxGroupId
6241
- });
6318
+ await waitForSandboxExecReadiness(
6319
+ established,
6320
+ MODAL_EXEC_READINESS_TIMEOUT_MS,
6321
+ {
6322
+ sandboxGroupId: ids.sandboxGroupId
6323
+ },
6324
+ cancellationSignal
6325
+ );
6242
6326
  }
6243
6327
  await maybeRenewProviderExpiration(true);
6244
6328
  throwIfReleasedOrCancelled();
@@ -6364,9 +6448,14 @@ async function resumeBoxForTurnOnce(services, ids, kind, holderId) {
6364
6448
  if (services.verifyAttachedSandboxReadiness) {
6365
6449
  await services.verifyAttachedSandboxReadiness(established);
6366
6450
  } else {
6367
- await waitForSandboxExecReadiness(established, MODAL_EXEC_READINESS_TIMEOUT_MS, {
6368
- sandboxGroupId: ids.sandboxGroupId
6369
- });
6451
+ await waitForSandboxExecReadiness(
6452
+ established,
6453
+ MODAL_EXEC_READINESS_TIMEOUT_MS,
6454
+ {
6455
+ sandboxGroupId: ids.sandboxGroupId
6456
+ },
6457
+ cancellationSignal
6458
+ );
6370
6459
  }
6371
6460
  providerRenewalTarget = {
6372
6461
  backend: ids.backend,
@@ -6626,7 +6715,7 @@ function afterPersistableHomeMutation(services, ids, home) {
6626
6715
  if (!exactAdmission || typeof exactAdmission.id !== "string" || typeof exactAdmission.workspaceGeneration !== "number" || !("providerBinding" in boundAdmission)) {
6627
6716
  throw new Error("Persistable home mutation settlement lacked its bound admission");
6628
6717
  }
6629
- if (outcome === "resolved" && retainedProcess) {
6718
+ if ((outcome === "resolved" || outcome === "outcome_unknown") && retainedProcess) {
6630
6719
  try {
6631
6720
  await retainWorkspaceProviderCommand(services.db, {
6632
6721
  accountId: fence.accountId,
@@ -6671,6 +6760,8 @@ function afterPersistableHomeMutation(services, ids, home) {
6671
6760
  }
6672
6761
  return;
6673
6762
  }
6763
+ if (outcome === "outcome_unknown")
6764
+ throw new Error("Outcome-unknown command settlement requires its exact retained invocation");
6674
6765
  await verifyWorkspaceMutationSettlement(services.db, {
6675
6766
  accountId: fence.accountId,
6676
6767
  workspaceId: ids.workspaceId,
@@ -8868,8 +8959,10 @@ import {
8868
8959
  isMcpRequestTimeoutError,
8869
8960
  isMcpTransportConnectivityError,
8870
8961
  isModalTaskExecStartPreDispatchUnavailableError,
8962
+ isModalCommandStartOutcomeUnknownError,
8871
8963
  isRoutingMutationOutcomeUnknownError,
8872
8964
  RoutingWorkspaceRootChangedError,
8965
+ ResponsesStreamingTerminalError,
8873
8966
  SandboxMaterializationVerificationError,
8874
8967
  materializationVerificationDiagnostic,
8875
8968
  PROVIDER_QUOTA_EXHAUSTED_CODE,
@@ -9834,6 +9927,7 @@ function shouldRecoverCompactionProviderFailure(error) {
9834
9927
  return agentRunFailurePayload(error).retryable === true;
9835
9928
  }
9836
9929
  function classifyContextWindowOverflowError(error) {
9930
+ if (isProviderSafetyRefusal(error)) return null;
9837
9931
  const fields = collectErrorStrings(error);
9838
9932
  const matched = fields.find(
9839
9933
  (value) => /context[_\s-]*length[_\s-]*exceeded/i.test(value) || /exceeds?\s+(?:the\s+)?context\s+window/i.test(value) || /maximum\s+context\s+length/i.test(value) || /context\s+window[^.]*exceed/i.test(value)
@@ -9879,6 +9973,7 @@ function collectErrorStrings(value, seen = /* @__PURE__ */ new WeakSet()) {
9879
9973
  }
9880
9974
  seen.add(value);
9881
9975
  const out = [];
9976
+ if (value instanceof ResponsesStreamingTerminalError) out.push(value.detail);
9882
9977
  const record = value;
9883
9978
  for (const key of ["message", "code", "type", "name", "param"]) {
9884
9979
  const field = record[key];
@@ -9896,6 +9991,9 @@ function isExactStatuslessUpstreamConnectivityMessage(message) {
9896
9991
  return message.trim().toLowerCase() === STATUSLESS_UPSTREAM_CONNECTIVITY_MESSAGE;
9897
9992
  }
9898
9993
  function providerSafetyRefusalDiagnostic(error) {
9994
+ if (error instanceof ResponsesStreamingTerminalError) {
9995
+ return error.category === "safety" ? error.detail : void 0;
9996
+ }
9899
9997
  return collectErrorStrings(error).find(
9900
9998
  (value) => /^(?:content_policy_violation|content_filter|safety_violation|bio_policy|cyber_policy)$/.test(
9901
9999
  value
@@ -9906,6 +10004,9 @@ function isProviderSafetyRefusal(error) {
9906
10004
  return providerSafetyRefusalDiagnostic(error) !== void 0;
9907
10005
  }
9908
10006
  function isTransientProviderError(error) {
10007
+ if (error instanceof ResponsesStreamingTerminalError) {
10008
+ return error.category === "unavailable";
10009
+ }
9909
10010
  if (isProviderSafetyRefusal(error)) return false;
9910
10011
  const status = typeof error === "object" && error !== null ? Number(
9911
10012
  error.status ?? error.statusCode
@@ -10021,6 +10122,28 @@ function baseAgentRunFailurePayload(error, options = {}) {
10021
10122
  detail: safetyRefusalDiagnostic
10022
10123
  };
10023
10124
  }
10125
+ if (error instanceof ResponsesStreamingTerminalError) {
10126
+ const quota2 = error.category === "unknown" || error.category === "rate_limit" ? classifyProviderQuotaExhaustionError({
10127
+ code: error.code,
10128
+ error: { code: error.code, type: error.type, message: error.detail },
10129
+ retryAfterSeconds: error.retryAfterSeconds
10130
+ }) : null;
10131
+ if (quota2) {
10132
+ return {
10133
+ error: providerQuotaExhaustedMessage(quota2.scope),
10134
+ code: PROVIDER_QUOTA_EXHAUSTED_CODE,
10135
+ retryable: false,
10136
+ quotaScope: quota2.scope,
10137
+ detail: error.detail
10138
+ };
10139
+ }
10140
+ return {
10141
+ error: error.category === "rate_limit" ? "Model provider rate limit hit. Try again in a minute or lower the reasoning effort." : error.category === "unavailable" ? "The model provider is temporarily unavailable. The same turn will retry after a short delay." : "The model provider rejected the response. Automatic retries stopped.",
10142
+ code: error.category === "rate_limit" ? "provider_rate_limited" : error.category === "unavailable" ? "provider_unavailable" : "provider_request_rejected",
10143
+ retryable: error.category === "rate_limit" || error.category === "unavailable",
10144
+ detail: error.detail
10145
+ };
10146
+ }
10024
10147
  const message = error instanceof Error ? error.message : String(error);
10025
10148
  const status = typeof error === "object" && error !== null ? Number(
10026
10149
  error.status ?? error.statusCode
@@ -10049,6 +10172,13 @@ function baseAgentRunFailurePayload(error, options = {}) {
10049
10172
  retryable: true
10050
10173
  };
10051
10174
  }
10175
+ if (isModalCommandStartOutcomeUnknownError(error)) {
10176
+ return {
10177
+ error: "A managed sandbox command may have started, but its acknowledgement was lost. Automatic replay is disabled; inspect the sandbox state before retrying.",
10178
+ code: "sandbox_command_start_outcome_unknown",
10179
+ retryable: false
10180
+ };
10181
+ }
10052
10182
  if (!isRoutingMutationOutcomeUnknownError(error) && isModalTaskExecStartPreDispatchUnavailableError(error)) {
10053
10183
  return {
10054
10184
  error: "The managed sandbox command router was not ready before the command was sent. The same turn will retry after a short delay.",
@@ -10326,7 +10456,9 @@ export {
10326
10456
  signalPendingCodexCapacityWakeTargets,
10327
10457
  armAndReconcileCodexCapacityWait,
10328
10458
  createCodexCapacityActivities,
10459
+ agentRunAdmissionDenial,
10329
10460
  createDocumentActivities,
10461
+ turnCredentialRestriction,
10330
10462
  createGoalActivities,
10331
10463
  withFirstPartyTools,
10332
10464
  createKnowledgeSourceSyncActivities,
@@ -10428,4 +10560,4 @@ export {
10428
10560
  codexUsageLimitFailurePayload,
10429
10561
  CODEX_USAGE_LIMIT_MAX_RESUME_MS
10430
10562
  };
10431
- //# sourceMappingURL=chunk-RZAAGRFQ.js.map
10563
+ //# sourceMappingURL=chunk-4PJTUBWQ.js.map