@opengeni/worker-bundle 1.0.0-canary.1 → 1.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.
- package/dist/activities/agent-run-admission.d.ts +3 -1
- package/dist/activities/agent-turn/admission.d.ts +24 -3
- package/dist/activities/agent-turn/agent-build.d.ts +4 -0
- package/dist/activities/agent-turn/claude-usage-observer.d.ts +58 -0
- package/dist/activities/agent-turn/code-search.d.ts +60 -0
- package/dist/activities/agent-turn/codex-capacity.d.ts +13 -0
- package/dist/activities/agent-turn/codex-plan-entitlement.d.ts +105 -0
- package/dist/activities/agent-turn/codex.d.ts +3 -2
- package/dist/activities/agent-turn/compaction-prep.d.ts +21 -5
- package/dist/activities/agent-turn/credential-leases.d.ts +19 -33
- package/dist/activities/agent-turn/credential-restriction.d.ts +3 -0
- package/dist/activities/agent-turn/errors.d.ts +82 -11
- package/dist/activities/agent-turn/failure-settlement.d.ts +6 -3
- package/dist/activities/agent-turn/final-reply.d.ts +18 -0
- package/dist/activities/agent-turn/finalization-monitor.d.ts +17 -0
- package/dist/activities/agent-turn/finalization.d.ts +4 -2
- package/dist/activities/agent-turn/github-repository-bindings.d.ts +2 -0
- package/dist/activities/agent-turn/governance-model.d.ts +9 -2
- package/dist/activities/agent-turn/history-sink.d.ts +2 -0
- package/dist/activities/agent-turn/history.d.ts +2 -0
- package/dist/activities/agent-turn/input-wait-reply.d.ts +41 -0
- package/dist/activities/agent-turn/media-artifacts.d.ts +5 -3
- package/dist/activities/agent-turn/model-call-admission.d.ts +15 -0
- package/dist/activities/agent-turn/model-usage.d.ts +6 -0
- package/dist/activities/agent-turn/model-wire-dispatch.d.ts +15 -0
- package/dist/activities/agent-turn/optional-repositories.d.ts +59 -0
- package/dist/activities/agent-turn/provider-dispatch-barrier.d.ts +12 -1
- package/dist/activities/agent-turn/quiescence.d.ts +7 -7
- package/dist/activities/agent-turn/recovery-warning.d.ts +9 -0
- package/dist/activities/agent-turn/refresh-credentials.d.ts +6 -0
- package/dist/activities/agent-turn/run-credentials.d.ts +8 -3
- package/dist/activities/agent-turn/sandbox-establish.d.ts +2 -1
- package/dist/activities/agent-turn/sandbox-provision.d.ts +3 -1
- package/dist/activities/agent-turn/sandbox-route.d.ts +3 -20
- package/dist/activities/agent-turn/sandbox-runtime.d.ts +2 -2
- package/dist/activities/agent-turn/session-title.d.ts +34 -2
- package/dist/activities/agent-turn/skill-checkout.d.ts +25 -6
- package/dist/activities/agent-turn/skill-read.d.ts +70 -2
- package/dist/activities/agent-turn/skill-remove.d.ts +14 -0
- package/dist/activities/agent-turn/skill-search.d.ts +3 -1
- package/dist/activities/agent-turn/skill-tools.d.ts +15 -2
- package/dist/activities/agent-turn/skill-transfer.d.ts +18 -6
- package/dist/activities/agent-turn/stream-attempt.d.ts +7 -3
- package/dist/activities/agent-turn/subscription-lease.d.ts +38 -0
- package/dist/activities/agent-turn/tool-environment.d.ts +56 -6
- package/dist/activities/agent-turn/tool-policy.d.ts +43 -0
- package/dist/activities/agent-turn/turn-context.d.ts +29 -0
- package/dist/activities/agent-turn/turn-sandbox-access.d.ts +3 -0
- package/dist/activities/agent-turn/xai-capacity.d.ts +2 -1
- package/dist/activities/automations.d.ts +3 -1
- package/dist/activities/browser-deadline-checkpoint.d.ts +29 -0
- package/dist/activities/codemode-dispatcher.d.ts +9 -2
- package/dist/activities/codex-capacity.d.ts +18 -2
- package/dist/activities/codex-rotation.d.ts +7 -1
- package/dist/activities/context-compaction.d.ts +16 -2
- package/dist/activities/gmail-files.d.ts +32 -0
- package/dist/activities/goals.d.ts +8 -0
- package/dist/activities/knowledge-indexing.d.ts +19 -0
- package/dist/activities/mcp-account-routes.d.ts +3 -0
- package/dist/activities/mcp-credentials.d.ts +12 -13
- package/dist/activities/mcp-operation-authority.d.ts +0 -5
- package/dist/activities/model-call-fact-reconciler.d.ts +34 -0
- package/dist/activities/open-suffix-resume.d.ts +13 -0
- package/dist/activities/parent-wake.d.ts +6 -12
- package/dist/activities/retained-screenshots.d.ts +7 -2
- package/dist/activities/rig-verification.d.ts +2 -3
- package/dist/activities/run-credential-renewal.d.ts +1 -0
- package/dist/activities/run-credentials.d.ts +15 -3
- package/dist/activities/sandbox-images.d.ts +1 -1
- package/dist/activities/sandbox-lease.d.ts +47 -9
- package/dist/activities/scheduled-tasks.d.ts +4 -35
- package/dist/activities/session-state.d.ts +70 -3
- package/dist/activities/types.d.ts +55 -6
- package/dist/activities/workspace-capture.d.ts +2 -0
- package/dist/activities/workspace-credential-provider.d.ts +46 -0
- package/dist/{activities-control-HMFGSKC5.js → activities-control-BNPTRTOE.js} +1896 -418
- package/dist/activities-control-BNPTRTOE.js.map +1 -0
- package/dist/activities-control.d.ts +182 -4
- package/dist/{activities-turn-AP67JADS.js → activities-turn-5LGZOSVU.js} +4476 -1327
- package/dist/activities-turn-5LGZOSVU.js.map +1 -0
- package/dist/activities.d.ts +182 -4
- package/dist/artifact-materializer-entry.js +5 -2
- package/dist/artifact-materializer-entry.js.map +1 -1
- package/dist/artifact-outbox-entry.js +5 -2
- package/dist/artifact-outbox-entry.js.map +1 -1
- package/dist/browser-deadline-checkpoint-contract.d.ts +2 -0
- package/dist/{chunk-A4XQWVZK.js → chunk-3ZTRWDMN.js} +307 -4
- package/dist/chunk-3ZTRWDMN.js.map +1 -0
- package/dist/{chunk-RAMNYSAW.js → chunk-4ER3YXOT.js} +22 -4
- package/dist/chunk-4ER3YXOT.js.map +1 -0
- package/dist/{chunk-CYITU5UH.js → chunk-LJX7Z2KP.js} +1445 -343
- package/dist/chunk-LJX7Z2KP.js.map +1 -0
- package/dist/editable-artifact-materializer-service.d.ts +2 -2
- package/dist/editable-artifact-outbox-service.d.ts +2 -2
- package/dist/host-export-pump.d.ts +3 -1
- package/dist/host-export.d.ts +1 -1
- package/dist/host-export.js +1 -1
- package/dist/http.d.ts +1 -1
- package/dist/index.d.ts +95 -3
- package/dist/index.js +137 -43
- package/dist/index.js.map +1 -1
- package/dist/observability-metrics.d.ts +118 -8
- package/dist/retained-process-diagnostics.d.ts +4 -0
- package/dist/retained-process-retry.d.ts +7 -0
- package/dist/sandbox-resume.d.ts +55 -13
- package/dist/sandbox-routing.d.ts +5 -3
- package/dist/sandbox-snapshot-diagnostics.d.ts +20 -0
- package/dist/session-event-fanout.d.ts +6 -0
- package/dist/warm-capture-holder.d.ts +3 -0
- package/dist/worker-service-lifecycle.d.ts +12 -0
- package/dist/workflow-bundle.js +273 -41
- package/dist/workflows/activities.d.ts +1 -1
- package/dist/workflows/browser-deadline-checkpoint.d.ts +9 -0
- package/dist/workflows/scheduled-tasks.d.ts +4 -0
- package/dist/workflows/session.d.ts +36 -0
- package/dist/workflows.d.ts +1 -0
- package/package.json +21 -19
- package/src/activities/agent-run-admission.ts +17 -1
- package/src/activities/agent-turn/admission.ts +66 -3
- package/src/activities/agent-turn/agent-build.ts +84 -10
- package/src/activities/agent-turn/claim.ts +186 -43
- package/src/activities/agent-turn/claude-usage-observer.ts +221 -0
- package/src/activities/agent-turn/code-search.ts +275 -0
- package/src/activities/agent-turn/codex-capacity.ts +172 -8
- package/src/activities/agent-turn/codex-plan-entitlement.ts +254 -0
- package/src/activities/agent-turn/codex.ts +13 -5
- package/src/activities/agent-turn/compaction-prep.ts +170 -102
- package/src/activities/agent-turn/credential-leases.ts +122 -216
- package/src/activities/agent-turn/credential-restriction.ts +14 -0
- package/src/activities/agent-turn/errors.ts +647 -48
- package/src/activities/agent-turn/failure-settlement.ts +682 -130
- package/src/activities/agent-turn/final-reply.ts +46 -0
- package/src/activities/agent-turn/finalization-monitor.ts +120 -0
- package/src/activities/agent-turn/finalization.ts +146 -43
- package/src/activities/agent-turn/github-repository-bindings.ts +3 -1
- package/src/activities/agent-turn/governance-model.ts +69 -28
- package/src/activities/agent-turn/history-sink.ts +16 -2
- package/src/activities/agent-turn/history.ts +38 -11
- package/src/activities/agent-turn/input-wait-reply.ts +103 -0
- package/src/activities/agent-turn/knowledge-source-tools.ts +2 -0
- package/src/activities/agent-turn/media-artifacts.ts +2 -1
- package/src/activities/agent-turn/model-call-admission.ts +94 -0
- package/src/activities/agent-turn/model-usage.ts +64 -3
- package/src/activities/agent-turn/model-wire-dispatch.ts +27 -0
- package/src/activities/agent-turn/optional-repositories.ts +224 -0
- package/src/activities/agent-turn/provider-dispatch-barrier.ts +22 -0
- package/src/activities/agent-turn/quiescence.ts +10 -7
- package/src/activities/agent-turn/recovery-warning.ts +16 -0
- package/src/activities/agent-turn/refresh-credentials.ts +44 -0
- package/src/activities/agent-turn/run-credentials.ts +116 -55
- package/src/activities/agent-turn/run.ts +320 -93
- package/src/activities/agent-turn/sandbox-establish.ts +84 -8
- package/src/activities/agent-turn/sandbox-provision.ts +3 -1
- package/src/activities/agent-turn/sandbox-route.ts +4 -21
- package/src/activities/agent-turn/sandbox-runtime.ts +343 -18
- package/src/activities/agent-turn/session-title.ts +81 -5
- package/src/activities/agent-turn/skill-checkout.ts +111 -24
- package/src/activities/agent-turn/skill-install.ts +1 -1
- package/src/activities/agent-turn/skill-read.ts +374 -28
- package/src/activities/agent-turn/skill-remove.ts +46 -0
- package/src/activities/agent-turn/skill-save.ts +1 -1
- package/src/activities/agent-turn/skill-search.ts +10 -1
- package/src/activities/agent-turn/skill-selection.ts +4 -0
- package/src/activities/agent-turn/skill-tools.ts +112 -18
- package/src/activities/agent-turn/skill-transfer.ts +68 -23
- package/src/activities/agent-turn/stream-attempt.ts +313 -77
- package/src/activities/agent-turn/subscription-lease.ts +115 -0
- package/src/activities/agent-turn/tool-environment.ts +316 -167
- package/src/activities/agent-turn/tool-policy.ts +80 -1
- package/src/activities/agent-turn/turn-context.ts +35 -0
- package/src/activities/agent-turn/turn-sandbox-access.ts +7 -1
- package/src/activities/agent-turn/xai-capacity.ts +94 -51
- package/src/activities/automations.ts +76 -4
- package/src/activities/browser-deadline-checkpoint.ts +279 -0
- package/src/activities/capabilities.ts +108 -11
- package/src/activities/codemode-dispatcher.ts +36 -8
- package/src/activities/codex-capacity.ts +60 -25
- package/src/activities/codex-rotation.ts +39 -17
- package/src/activities/context-compaction.ts +75 -18
- package/src/activities/gmail-files.ts +88 -0
- package/src/activities/goals.ts +116 -121
- package/src/activities/google-drive-publication.ts +1 -3
- package/src/activities/image-generation-operation.ts +1 -1
- package/src/activities/knowledge-indexing.ts +269 -15
- package/src/activities/knowledge-source-sync.ts +10 -0
- package/src/activities/mcp-account-routes.ts +17 -0
- package/src/activities/mcp-credentials.ts +83 -194
- package/src/activities/mcp-operation-authority.ts +16 -41
- package/src/activities/model-call-fact-reconciler.ts +112 -0
- package/src/activities/open-suffix-resume.ts +15 -2
- package/src/activities/parent-wake.ts +46 -21
- package/src/activities/retained-screenshots.ts +82 -11
- package/src/activities/rig-verification.ts +38 -37
- package/src/activities/run-credential-renewal.ts +13 -1
- package/src/activities/run-credentials.ts +59 -17
- package/src/activities/run-input.ts +25 -16
- package/src/activities/sandbox-images.ts +0 -1
- package/src/activities/sandbox-lease.ts +798 -82
- package/src/activities/scheduled-tasks.ts +550 -178
- package/src/activities/session-state.ts +245 -6
- package/src/activities/site-auth-maintenance.ts +3 -0
- package/src/activities/types.ts +72 -5
- package/src/activities/workflow-wake.ts +2 -17
- package/src/activities/workspace-capture.ts +13 -2
- package/src/activities/workspace-credential-provider.ts +283 -0
- package/src/activities-control.ts +4 -0
- package/src/activities-turn.ts +5 -0
- package/src/activities.ts +13 -0
- package/src/activity-services.ts +16 -4
- package/src/browser-deadline-checkpoint-contract.ts +5 -0
- package/src/editable-artifact-hint-broker.ts +3 -0
- package/src/editable-artifact-materializer-service.ts +7 -3
- package/src/editable-artifact-outbox-service.ts +4 -4
- package/src/github-rest-mcp.ts +1 -2
- package/src/host-export-pump.ts +26 -4
- package/src/host-export.ts +3 -0
- package/src/http.ts +4 -2
- package/src/index.ts +99 -37
- package/src/observability-metrics.ts +510 -5
- package/src/personal-github-git-credentials.ts +2 -1
- package/src/pr-review-credentials.ts +1 -3
- package/src/retained-process-diagnostics.ts +50 -0
- package/src/retained-process-retry.ts +36 -0
- package/src/sandbox-resume.ts +388 -101
- package/src/sandbox-routing.ts +150 -25
- package/src/sandbox-snapshot-diagnostics.ts +112 -0
- package/src/session-event-fanout.ts +23 -0
- package/src/warm-capture-holder.ts +15 -0
- package/src/worker-service-lifecycle.ts +53 -0
- package/src/workflows/activities.ts +16 -1
- package/src/workflows/browser-deadline-checkpoint.ts +50 -0
- package/src/workflows/file-upload-reaper.ts +2 -0
- package/src/workflows/scheduled-tasks.ts +26 -13
- package/src/workflows/session.ts +242 -22
- package/src/workflows.ts +4 -0
- package/dist/activities/agent-turn/knowledge-sources.d.ts +0 -20
- package/dist/activities/packs.d.ts +0 -55
- package/dist/activities-control-HMFGSKC5.js.map +0 -1
- package/dist/activities-turn-AP67JADS.js.map +0 -1
- package/dist/chunk-A4XQWVZK.js.map +0 -1
- package/dist/chunk-CYITU5UH.js.map +0 -1
- package/dist/chunk-RAMNYSAW.js.map +0 -1
- package/src/activities/agent-turn/knowledge-sources.ts +0 -86
- package/src/activities/packs.ts +0 -166
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import type { ObjectStorage } from "@opengeni/storage";
|
|
3
|
+
import type { GmailFileMaterializationRequest } from "@opengeni/runtime/gmail-rest-mcp";
|
|
4
|
+
import type { ConnectorAttachmentMaterializer } from "@opengeni/runtime";
|
|
5
|
+
import type { SandboxChannelAService } from "@opengeni/runtime/sandbox";
|
|
6
|
+
|
|
7
|
+
/** Use the selected filesystem namespace, retaining descriptor confinement and
|
|
8
|
+
* one extra byte to distinguish a complete exact-limit input from truncation. */
|
|
9
|
+
export async function readGmailFileFromChannel(
|
|
10
|
+
channel: Pick<SandboxChannelAService, "fsRead">,
|
|
11
|
+
request: { path: string; maxBytes: number },
|
|
12
|
+
): Promise<Uint8Array> {
|
|
13
|
+
const file = await channel.fsRead({
|
|
14
|
+
path: request.path,
|
|
15
|
+
maxBytes: request.maxBytes + 1,
|
|
16
|
+
encoding: "base64",
|
|
17
|
+
workspaceOnly: true,
|
|
18
|
+
});
|
|
19
|
+
const bytes = Buffer.from(file.content, "base64");
|
|
20
|
+
if (file.truncated || bytes.byteLength > request.maxBytes)
|
|
21
|
+
throw new Error("Gmail file input exceeds the maximum size");
|
|
22
|
+
return bytes;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Gmail returns base64url JSON, while the exact filesystem importer consumes
|
|
26
|
+
* byte streams. Stage only inside the worker; no URL or bytes reach a tool result. */
|
|
27
|
+
export async function materializeGmailFile(
|
|
28
|
+
request: GmailFileMaterializationRequest,
|
|
29
|
+
options: {
|
|
30
|
+
workspaceId: string;
|
|
31
|
+
storage: ObjectStorage;
|
|
32
|
+
downloadStorage: ObjectStorage;
|
|
33
|
+
materialize: ConnectorAttachmentMaterializer;
|
|
34
|
+
onCleanupFailure?: (key: string) => void;
|
|
35
|
+
},
|
|
36
|
+
) {
|
|
37
|
+
if (!(await request.authorizeProviderRequest()))
|
|
38
|
+
throw new Error("Gmail file authority is unavailable");
|
|
39
|
+
const hash = createHash("sha256").update(request.bytes).digest("hex");
|
|
40
|
+
const key = `workspaces/${options.workspaceId}/private-connector-transfers/${crypto.randomUUID()}`;
|
|
41
|
+
try {
|
|
42
|
+
await options.storage.putObject({
|
|
43
|
+
key,
|
|
44
|
+
body: request.bytes,
|
|
45
|
+
contentType: request.mediaType,
|
|
46
|
+
sha256: hash,
|
|
47
|
+
});
|
|
48
|
+
const source = await options.downloadStorage.createGetUrl({ key, expiresInSeconds: 300 });
|
|
49
|
+
const envelope = await options.materialize({
|
|
50
|
+
serverId: request.serverId,
|
|
51
|
+
toolName: request.providerAttachmentId.value.endsWith(":raw")
|
|
52
|
+
? "download_message"
|
|
53
|
+
: "download_attachment",
|
|
54
|
+
operationId: request.operationId,
|
|
55
|
+
connectionId: request.connectionId,
|
|
56
|
+
authorizeProviderRequest: request.authorizeProviderRequest,
|
|
57
|
+
attachments: [
|
|
58
|
+
{
|
|
59
|
+
providerAttachmentId: request.providerAttachmentId,
|
|
60
|
+
fileName: request.fileName,
|
|
61
|
+
mediaType: request.mediaType,
|
|
62
|
+
byteSize: request.bytes.byteLength,
|
|
63
|
+
contentSha256: hash,
|
|
64
|
+
source: { url: source.url, expiresAt: source.expiresAt.toISOString() },
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
});
|
|
68
|
+
return { attachments: envelope.attachments };
|
|
69
|
+
} finally {
|
|
70
|
+
// The transfer object is never a retained workspace File or Knowledge entry.
|
|
71
|
+
let cleaned = false;
|
|
72
|
+
for (let attempt = 0; attempt < 3 && !cleaned; attempt++) {
|
|
73
|
+
try {
|
|
74
|
+
await options.storage.deleteObject(key);
|
|
75
|
+
cleaned = true;
|
|
76
|
+
} catch {
|
|
77
|
+
/* Idempotent storage cleanup must not erase delivery or uncertainty. */
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (!cleaned) {
|
|
81
|
+
try {
|
|
82
|
+
options.onCleanupFailure?.(key);
|
|
83
|
+
} catch {
|
|
84
|
+
/* Observability cannot replace a file result. */
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
package/src/activities/goals.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
allowedFirstPartyMcpToolsForSession,
|
|
3
3
|
configuredStaticUsageLimits,
|
|
4
|
+
isModelAvailableForNewSelection,
|
|
4
5
|
policyProviderIdForModel,
|
|
5
6
|
resolveModelProvider,
|
|
6
7
|
resolveTurnExecutionPolicyV1,
|
|
@@ -13,21 +14,18 @@ import {
|
|
|
13
14
|
import {
|
|
14
15
|
evaluateWorkspaceModelPolicy,
|
|
15
16
|
mergeToolRefs,
|
|
17
|
+
readTurnExecutionPolicyV1,
|
|
16
18
|
type SessionGoal,
|
|
17
19
|
type ToolRef,
|
|
18
20
|
} from "@opengeni/contracts";
|
|
19
21
|
import { isCodexBilledModel } from "@opengeni/codex";
|
|
20
22
|
import {
|
|
21
23
|
enqueueSessionWorkflowWakeIfRunnable,
|
|
22
|
-
getBillingBalance,
|
|
23
|
-
getLatestStartedSessionTurn,
|
|
24
24
|
getWorkspaceModelPolicy,
|
|
25
25
|
getSessionGoal,
|
|
26
|
-
|
|
26
|
+
getSessionTurn,
|
|
27
27
|
materializeGoalContinuation,
|
|
28
28
|
requireSession,
|
|
29
|
-
sumUsageQuantity,
|
|
30
|
-
type Database,
|
|
31
29
|
} from "@opengeni/db";
|
|
32
30
|
import type {
|
|
33
31
|
ControlActivityServices,
|
|
@@ -39,6 +37,8 @@ import {
|
|
|
39
37
|
resolveCatalogSettings,
|
|
40
38
|
resolveWorkspaceCatalogSettings,
|
|
41
39
|
} from "@opengeni/core";
|
|
40
|
+
import { agentRunAdmissionDenial } from "./agent-run-admission";
|
|
41
|
+
import { turnCredentialRestriction } from "./agent-turn/credential-restriction";
|
|
42
42
|
|
|
43
43
|
export function createGoalActivities(services: () => Promise<ControlActivityServices>) {
|
|
44
44
|
async function enqueueGoalRetryWake(input: MaybeContinueGoalInput): Promise<void> {
|
|
@@ -66,25 +66,25 @@ export function createGoalActivities(services: () => Promise<ControlActivityServ
|
|
|
66
66
|
if (!existingGoal || existingGoal.status !== "active") {
|
|
67
67
|
return { action: "none" };
|
|
68
68
|
}
|
|
69
|
-
let settings = (await resolveCatalogSettings(db, catalogSourceSettings)).settings;
|
|
70
69
|
// Loaded before the budget check so the codex-billed predicate and the
|
|
71
70
|
// synthesized turn use the SAME effective policy. An explicit per-turn
|
|
72
71
|
// model can differ from the persisted session default; follow-up goal work
|
|
73
|
-
//
|
|
74
|
-
// Admission-rejected turns
|
|
72
|
+
// follows effective defaults: a started turn or a newer explicit settings
|
|
73
|
+
// boundary. Admission-rejected turns cannot poison that projection.
|
|
75
74
|
// Kept below the goal-less fast path so a non-goal session still skips the
|
|
76
75
|
// reads entirely.
|
|
77
76
|
const session = await requireSession(db, input.workspaceId, input.sessionId);
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
77
|
+
// Terminal sessions retain their goal for human recovery, but cannot
|
|
78
|
+
// continue. Do not validate an obsolete model before the locked guard gets
|
|
79
|
+
// the chance to reject that work; otherwise a deterministic error retries.
|
|
80
|
+
if (session.status === "failed" || session.status === "cancelled") {
|
|
81
|
+
return { action: "none" };
|
|
82
|
+
}
|
|
83
|
+
let settings = (await resolveCatalogSettings(db, catalogSourceSettings)).settings;
|
|
84
|
+
const inheritedContinuationModel = session.model;
|
|
84
85
|
let continuationModel = inheritedContinuationModel;
|
|
85
|
-
const continuationReasoningEffort =
|
|
86
|
-
|
|
87
|
-
const continuationLatencyMode = latestStartedTurn?.latencyMode ?? session.latencyMode;
|
|
86
|
+
const continuationReasoningEffort = session.reasoningEffort;
|
|
87
|
+
const continuationLatencyMode = session.latencyMode;
|
|
88
88
|
const workspaceModelPolicy = await getWorkspaceModelPolicy(db, input.workspaceId);
|
|
89
89
|
if (
|
|
90
90
|
inheritedContinuationModel.startsWith(WORKSPACE_GATEWAY_MODEL_ID_PREFIX) ||
|
|
@@ -116,39 +116,27 @@ export function createGoalActivities(services: () => Promise<ControlActivityServ
|
|
|
116
116
|
) {
|
|
117
117
|
modelPolicyBlocked = `session is locked to Codex remote compaction v2; model "${continuationModel}" is not a Codex subscription model`;
|
|
118
118
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
119
|
+
const turnExecutionPolicy = modelPolicyBlocked
|
|
120
|
+
? undefined
|
|
121
|
+
: resolveTurnExecutionPolicyV1(settings, {
|
|
122
|
+
modelId: continuationModel,
|
|
123
|
+
requestedModelId: null,
|
|
124
|
+
modelSource: "continuation",
|
|
125
|
+
reasoningEffort: continuationReasoningEffort,
|
|
126
|
+
reasoningSource: "continuation",
|
|
127
|
+
latencyMode: continuationLatencyMode,
|
|
128
|
+
latencyModeSource: "continuation",
|
|
129
|
+
});
|
|
130
|
+
const continuationPolicy: NonNullable<
|
|
131
|
+
Parameters<typeof materializeGoalContinuation>[1]["policy"]
|
|
132
|
+
> = {
|
|
126
133
|
model: continuationModel,
|
|
127
|
-
});
|
|
128
|
-
const fundedWithoutCredits = goalContinuationFundedWithoutCredits(
|
|
129
|
-
settings,
|
|
130
|
-
continuationModel,
|
|
131
|
-
isCodexRun,
|
|
132
|
-
);
|
|
133
|
-
// Budget exhaustion pauses the goal visibly instead of failing the
|
|
134
|
-
// session. Computed up front and applied inside the locked decision so a
|
|
135
|
-
// limits pause never consumes continuation budget.
|
|
136
|
-
const budgetBlocked = await goalRunBudgetBlocked(
|
|
137
|
-
settings,
|
|
138
|
-
db,
|
|
139
|
-
input.accountId,
|
|
140
|
-
input.workspaceId,
|
|
141
|
-
fundedWithoutCredits,
|
|
142
|
-
);
|
|
143
|
-
const turnExecutionPolicy = resolveTurnExecutionPolicyV1(settings, {
|
|
144
|
-
modelId: continuationModel,
|
|
145
|
-
requestedModelId: null,
|
|
146
|
-
modelSource: "continuation",
|
|
147
134
|
reasoningEffort: continuationReasoningEffort,
|
|
148
|
-
reasoningSource: "continuation",
|
|
149
135
|
latencyMode: continuationLatencyMode,
|
|
150
|
-
|
|
151
|
-
|
|
136
|
+
...(turnExecutionPolicy ? { turnExecutionPolicy } : {}),
|
|
137
|
+
tools: withFirstPartyTools(settings, session.tools),
|
|
138
|
+
sandboxBackend: session.sandboxBackend,
|
|
139
|
+
};
|
|
152
140
|
const decision = await materializeGoalContinuation(db, {
|
|
153
141
|
accountId: input.accountId,
|
|
154
142
|
workspaceId: input.workspaceId,
|
|
@@ -164,15 +152,45 @@ export function createGoalActivities(services: () => Promise<ControlActivityServ
|
|
|
164
152
|
// A model-policy block takes precedence: it is deterministic (a budget
|
|
165
153
|
// pause can clear on its own; a policy pause needs a model/policy change)
|
|
166
154
|
// and rides the same visible-pause channel.
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
155
|
+
admission: async (tx, causalTurn) => {
|
|
156
|
+
// The materializer selects this exact causal row under its session/goal
|
|
157
|
+
// locks and freezes policy only after admission returns. Never infer
|
|
158
|
+
// credential authority from the generated continuation's payload.
|
|
159
|
+
const sourceTurn = causalTurn
|
|
160
|
+
? await getSessionTurn(tx, input.workspaceId, causalTurn.id)
|
|
161
|
+
: null;
|
|
162
|
+
if (causalTurn && (!sourceTurn || sourceTurn.sessionId !== input.sessionId)) {
|
|
163
|
+
throw new Error("Goal continuation source turn is unavailable");
|
|
164
|
+
}
|
|
165
|
+
const sourcePolicy = readTurnExecutionPolicyV1(sourceTurn?.metadata);
|
|
166
|
+
if (turnExecutionPolicy) {
|
|
167
|
+
const credentialRestriction = turnCredentialRestriction(
|
|
168
|
+
sourcePolicy.kind === "valid" ? sourcePolicy.policy : turnExecutionPolicy,
|
|
169
|
+
session.metadata,
|
|
170
|
+
);
|
|
171
|
+
continuationPolicy.turnExecutionPolicy = credentialRestriction
|
|
172
|
+
? { ...turnExecutionPolicy, credentialRestriction }
|
|
173
|
+
: turnExecutionPolicy;
|
|
174
|
+
}
|
|
175
|
+
const budgetBlocked = modelPolicyBlocked
|
|
176
|
+
? null
|
|
177
|
+
: await goalRunBudgetBlocked(
|
|
178
|
+
{ ...service, settings, db: tx },
|
|
179
|
+
{
|
|
180
|
+
accountId: input.accountId,
|
|
181
|
+
workspaceId: input.workspaceId,
|
|
182
|
+
model: continuationModel,
|
|
183
|
+
initiatingHumanSubjectId: causalTurn?.initiatingHumanSubjectId ?? null,
|
|
184
|
+
},
|
|
185
|
+
);
|
|
186
|
+
return {
|
|
187
|
+
budgetBlocked: modelPolicyBlocked ?? budgetBlocked?.message ?? null,
|
|
188
|
+
budgetPausedReason: modelPolicyBlocked
|
|
189
|
+
? "limits"
|
|
190
|
+
: (budgetBlocked?.pausedReason ?? "limits"),
|
|
191
|
+
};
|
|
175
192
|
},
|
|
193
|
+
policy: continuationPolicy,
|
|
176
194
|
// Long-wait guidance is only given when `wait_for_input` is actually in this
|
|
177
195
|
// session's effective first-party selection (the same source the worker
|
|
178
196
|
// signs into the delegated token and the API uses to register tools), so
|
|
@@ -222,18 +240,21 @@ export function goalContinuationModelDecision(input: {
|
|
|
222
240
|
providerId: policyProviderIdForModel(catalogSettings, modelId),
|
|
223
241
|
modelId,
|
|
224
242
|
}).allowed;
|
|
225
|
-
if (
|
|
226
|
-
resolveModelProvider(catalogSettings, input.inheritedModel) &&
|
|
227
|
-
!policyBlocks(input.inheritedModel)
|
|
228
|
-
) {
|
|
229
|
-
return { model: input.inheritedModel, blocked: null };
|
|
230
|
-
}
|
|
231
243
|
if (!resolveModelProvider(catalogSettings, input.inheritedModel)) {
|
|
232
244
|
return {
|
|
233
245
|
model: input.inheritedModel,
|
|
234
246
|
blocked: `model "${input.inheritedModel}" is no longer in the deployment or workspace catalog; choose an available model before resuming the goal`,
|
|
235
247
|
};
|
|
236
248
|
}
|
|
249
|
+
if (!isModelAvailableForNewSelection(catalogSettings, input.inheritedModel)) {
|
|
250
|
+
return {
|
|
251
|
+
model: input.inheritedModel,
|
|
252
|
+
blocked: `model "${input.inheritedModel}" is retired from new selection; choose an available model before resuming the goal`,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
if (!policyBlocks(input.inheritedModel)) {
|
|
256
|
+
return { model: input.inheritedModel, blocked: null };
|
|
257
|
+
}
|
|
237
258
|
return {
|
|
238
259
|
model: input.inheritedModel,
|
|
239
260
|
blocked: `workspace model policy blocks model "${input.inheritedModel}"; pick an allowed model or change the workspace model policy`,
|
|
@@ -258,8 +279,9 @@ export function goalContinuationPrompt(
|
|
|
258
279
|
? [
|
|
259
280
|
"Waiting on child sessions, background commands, or external events:",
|
|
260
281
|
"- When further progress depends on work already in flight, do not sleep, loop, or poll session or command state repeatedly.",
|
|
261
|
-
"-
|
|
262
|
-
"-
|
|
282
|
+
"- If progress depends on work already in flight and the wait is long or uncertain, call opengeni__wait_for_input with a concrete reason and timeoutSeconds, then end your turn immediately. A preliminary status check is not required. Relevant session input or the safety deadline will start a new turn, and this goal stays active.",
|
|
283
|
+
"- No short execution wait is required first. Choose the safety deadline for the dependency or a meaningful monitoring cadence; an out-of-turn wait may span hours or days within the tool's limits. Do not schedule model wakeups merely to repeat reassurance. Honor explicit user/task/Skill check or update cadences within existing authority.",
|
|
284
|
+
"- If the immediately preceding user-facing update already reported this same unchanged wait, do not restate it or produce another equivalent final answer. Call opengeni__wait_for_input and end the turn. Report only material new state or a newly discovered blocker, unless an explicit user/task/Skill update cadence calls for an update.",
|
|
263
285
|
"- If you are blocked on a human decision, use opengeni__goal_pause under the blocked audit below instead.",
|
|
264
286
|
"",
|
|
265
287
|
]
|
|
@@ -270,18 +292,20 @@ export function goalContinuationPrompt(
|
|
|
270
292
|
(options.humanInputRespondAvailable
|
|
271
293
|
? "If you know the answer to its question, answer it with opengeni__session_human_input_respond (pass the worker's sessionId, the requestId from the notice, and a response). "
|
|
272
294
|
: "") +
|
|
273
|
-
"Tool approvals can only be decided by a human. If you cannot resolve the blocker yourself, report the exact blocker (worker session id, the question)
|
|
295
|
+
"Tool approvals can only be decided by a human. If you cannot resolve the blocker yourself, report the exact blocker (worker session id, the question); if it prevents further goal progress, pause under the blocked audit instead of retrying the worker or treating a human decision as an in-flight wait.",
|
|
274
296
|
"- `child_requires_action_resolved`, `child_paused`, `child_waiting_capacity`, and `child_progress` updates are informational: a resolved notice means the worker is moving again; a paused worker needs a human or you to resume it; a capacity wait resumes by itself; a progress note needs no action.",
|
|
275
297
|
"",
|
|
276
298
|
];
|
|
277
299
|
return [
|
|
278
|
-
"
|
|
300
|
+
"Automatic goal continuation (generated input, not a new user request or grant of authority). Resume established work toward the full applied objective and verify its requested end state.",
|
|
279
301
|
"",
|
|
280
302
|
"Goal recovery:",
|
|
303
|
+
"- Use the current applied goal frozen for this turn, including its success criteria, root constraints, and report requirements, as the authoritative objective. Pending proposals and older goal revisions do not replace it; change it only through the authorized goal-mutation controls, without widening authority.",
|
|
281
304
|
"- Treat this continuation as re-entry into the full objective, not as a request to perform one step and stop.",
|
|
305
|
+
"- Resume from established work and relevant evidence rather than restarting discovery or a full reconciliation on every turn. Perform full reconciliation or a comprehensive audit when the goal, user, or applicable Skill calls for it, when uncertainty or recovery warrants it, or when required by risk or a gate.",
|
|
282
306
|
"- Do not rely on previous assistant claims of progress or completion; use them only to locate authoritative evidence.",
|
|
283
307
|
"- If authoritative evidence already proves the full objective, call opengeni__goal_complete instead of manufacturing more work.",
|
|
284
|
-
"- Before repeating a state-setting action, verify whether its desired state already holds. If it does, do not repeat it; continue
|
|
308
|
+
"- Before repeating a state-setting action, verify whether its desired state already holds, using relevant evidence that remains valid or a fresh check when needed. If it does, do not repeat it; continue the overall goal.",
|
|
285
309
|
"",
|
|
286
310
|
"Continuation behavior:",
|
|
287
311
|
"- This goal persists across turns. A runtime boundary can end one turn without shrinking the objective; the next continuation resumes the same full objective.",
|
|
@@ -291,7 +315,7 @@ export function goalContinuationPrompt(
|
|
|
291
315
|
"- Temporary rough edges are acceptable while the work is moving in the right direction. Completion still requires the requested end state to be true and verified.",
|
|
292
316
|
"",
|
|
293
317
|
"Work from evidence:",
|
|
294
|
-
"Use
|
|
318
|
+
"Use authoritative workspace and external evidence, including prior tool results that remain relevant and valid. Reuse evidence only for the requirement, scope, version, and state it actually establishes; recheck changed, stale, uncertain, or insufficient evidence. Conversation summaries and assistant claims are pointers, not proof. Do not infer progress or evidence validity merely from this continuation. Improve, replace, or remove existing work as needed within authority to satisfy the actual objective.",
|
|
295
319
|
"",
|
|
296
320
|
"Progress visibility:",
|
|
297
321
|
"If a planning tool is available and the next work is meaningfully multi-step, use it to show a concise plan tied to the real objective. Keep the plan current as steps complete or the next best action changes. Skip planning overhead for trivial one-step progress, and do not treat a plan update as a substitute for doing the work.",
|
|
@@ -302,22 +326,26 @@ export function goalContinuationPrompt(
|
|
|
302
326
|
"- Treat alignment as movement toward the requested end state. An edit is aligned only if it makes the requested final state more true; useful-looking behavior that preserves a different end state is misaligned.",
|
|
303
327
|
"",
|
|
304
328
|
"Completion audit:",
|
|
305
|
-
"Before deciding that the goal is achieved, treat completion as unproven and verify it against the actual current state:",
|
|
329
|
+
"Before deciding that the goal is achieved, treat completion as unproven and verify it against the actual current state. This full completion audit is required even when ordinary continuation did not need full reconciliation; reuse still-valid authoritative evidence, but refresh it when the requirement or gate requires a fresh check:",
|
|
306
330
|
"- Derive concrete requirements from the objective and any referenced files, plans, specifications, issues, or user instructions.",
|
|
307
|
-
"- Preserve the
|
|
331
|
+
"- Preserve the applied objective's scope; do not redefine success around the work that already exists.",
|
|
308
332
|
"- For every explicit requirement, named artifact, command, test, gate, invariant, and deliverable, identify and inspect the authoritative evidence that would prove it.",
|
|
309
333
|
"- Match verification scope to requirement scope. Treat uncertain, indirect, incomplete, or missing evidence as not achieved and continue working.",
|
|
310
334
|
"- The audit must prove completion, not merely fail to find obvious remaining work.",
|
|
335
|
+
"- 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.",
|
|
311
336
|
"",
|
|
312
337
|
"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.",
|
|
338
|
+
"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.",
|
|
339
|
+
"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.",
|
|
313
340
|
"",
|
|
314
341
|
...waitingGuidance,
|
|
315
342
|
...childNoticeGuidance,
|
|
316
343
|
"Blocked audit:",
|
|
317
|
-
"-
|
|
318
|
-
"-
|
|
344
|
+
"- Base persistence on evidence, not a fixed number of turns or retries. Investigate recoverable failures and try plausible safe alternatives within current authority when they could materially advance the goal; do not exhaust every imaginable alternative or repeat an unchanged failure without a reason to expect progress.",
|
|
345
|
+
"- A definitive missing permission, required human decision, or external prerequisite with no actionable authorized path can justify pausing immediately. State the concrete blocker, relevant evidence or attempted alternatives, and what must change to resume. Tool approvals remain human-only.",
|
|
346
|
+
"- If progress depends on work already in flight or a meaningful timed recheck, use the available waiting mechanism rather than pausing the goal; continue any independent authorized work first.",
|
|
319
347
|
"- Do not pause merely because the work is hard, slow, uncertain, incomplete, or would benefit from clarification.",
|
|
320
|
-
"-
|
|
348
|
+
"- When no meaningful authorized progress remains and the blocker requires human input or an external change that cannot be handled by an available wait or monitoring mechanism, call opengeni__goal_pause with the concrete blocker instead of repeatedly reporting it while leaving the goal active.",
|
|
321
349
|
"",
|
|
322
350
|
"Do not call opengeni__goal_complete or opengeni__goal_pause unless the corresponding audit above is satisfied.",
|
|
323
351
|
].join("\n");
|
|
@@ -338,55 +366,22 @@ export function withFirstPartyTools(settings: Settings, tools: ToolRef[]): ToolR
|
|
|
338
366
|
}
|
|
339
367
|
|
|
340
368
|
/**
|
|
341
|
-
*
|
|
342
|
-
* readable reason when balance or monthly caps block another agent run.
|
|
369
|
+
* Goals share scheduled admission and pause visibly without synthesizing work.
|
|
343
370
|
*/
|
|
344
|
-
async function goalRunBudgetBlocked(
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
// credit-balance gate and monthly model-cost cap. The agent-run COUNT cap
|
|
353
|
-
// below is a volume quota (not a credit/cost gate) and remains enforced.
|
|
354
|
-
if (
|
|
355
|
-
!fundedWithoutCredits &&
|
|
356
|
-
(settings.billingMode === "stripe" || settings.usageLimitsMode === "managed")
|
|
357
|
-
) {
|
|
358
|
-
const balance = await getBillingBalance(db, accountId);
|
|
359
|
-
if (balance.balanceMicros <= 0) {
|
|
360
|
-
return "insufficient OpenGeni credits";
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
if (settings.usageLimitsMode === "static" || settings.usageLimitsMode === "managed") {
|
|
364
|
-
const limits = configuredStaticUsageLimits(settings);
|
|
365
|
-
if (!fundedWithoutCredits && limits.maxMonthlyCostMicrosPerAccount) {
|
|
366
|
-
const used = await sumUsageQuantity(db, {
|
|
367
|
-
accountId,
|
|
368
|
-
eventType: "model.cost",
|
|
369
|
-
since: startOfUtcMonth(),
|
|
370
|
-
});
|
|
371
|
-
if (used >= limits.maxMonthlyCostMicrosPerAccount) {
|
|
372
|
-
return `monthly model cost limit reached (${limits.maxMonthlyCostMicrosPerAccount} micros)`;
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
if (limits.maxMonthlyAgentRunsPerWorkspace) {
|
|
376
|
-
const used = await sumUsageQuantity(db, {
|
|
377
|
-
workspaceId,
|
|
378
|
-
eventType: "agent_run.created",
|
|
379
|
-
since: startOfUtcMonth(),
|
|
380
|
-
});
|
|
381
|
-
if (used + 1 > limits.maxMonthlyAgentRunsPerWorkspace) {
|
|
382
|
-
return `monthly agent run limit reached (${limits.maxMonthlyAgentRunsPerWorkspace})`;
|
|
383
|
-
}
|
|
384
|
-
}
|
|
371
|
+
export async function goalRunBudgetBlocked(
|
|
372
|
+
services: Parameters<typeof agentRunAdmissionDenial>[0],
|
|
373
|
+
input: Omit<Parameters<typeof agentRunAdmissionDenial>[1], "requestedAgentRuns">,
|
|
374
|
+
): Promise<{ pausedReason: "limits" | "allowance"; message: string } | null> {
|
|
375
|
+
const denial = await agentRunAdmissionDenial(services, { ...input, requestedAgentRuns: 1 });
|
|
376
|
+
if (denial === null) return null;
|
|
377
|
+
if (denial === "allowance_exhausted") {
|
|
378
|
+
return { pausedReason: "allowance", message: "Opengeni usage allowance exhausted" };
|
|
385
379
|
}
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
380
|
+
const limits = configuredStaticUsageLimits(services.settings);
|
|
381
|
+
const messages = {
|
|
382
|
+
insufficient_credits: "insufficient Opengeni credits",
|
|
383
|
+
monthly_model_cost_limit: `monthly model cost limit reached (${limits.maxMonthlyCostMicrosPerAccount} micros)`,
|
|
384
|
+
monthly_agent_run_limit: `monthly agent run limit reached (${limits.maxMonthlyAgentRunsPerWorkspace})`,
|
|
385
|
+
};
|
|
386
|
+
return { pausedReason: "limits", message: messages[denial] };
|
|
392
387
|
}
|
|
@@ -90,9 +90,7 @@ export async function resolveGoogleDrivePublicationTarget(
|
|
|
90
90
|
);
|
|
91
91
|
if (frozen.length !== 1) return null;
|
|
92
92
|
const delegation = frozen[0]!;
|
|
93
|
-
const activated = delegation.userDelegation !== undefined;
|
|
94
93
|
if (
|
|
95
|
-
!activated &&
|
|
96
94
|
!(await ports.getMembership(db, {
|
|
97
95
|
accountId: workspace.accountId,
|
|
98
96
|
workspaceId,
|
|
@@ -101,7 +99,7 @@ export async function resolveGoogleDrivePublicationTarget(
|
|
|
101
99
|
) {
|
|
102
100
|
return null;
|
|
103
101
|
}
|
|
104
|
-
const originWorkspaceId =
|
|
102
|
+
const originWorkspaceId = delegation.originWorkspaceId;
|
|
105
103
|
if (!originWorkspaceId) return null;
|
|
106
104
|
const connection = await ports.getConnection(
|
|
107
105
|
db,
|
|
@@ -36,7 +36,7 @@ export class ImageGenerationRetentionFailedError extends Error {
|
|
|
36
36
|
cause?: unknown,
|
|
37
37
|
) {
|
|
38
38
|
super(
|
|
39
|
-
"The image was generated, but
|
|
39
|
+
"The image was generated, but Opengeni could not save it. The paid provider request was not repeated.",
|
|
40
40
|
cause === undefined ? undefined : { cause },
|
|
41
41
|
);
|
|
42
42
|
this.name = "ImageGenerationRetentionFailedError";
|