@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
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { withDirectModelProviders } from "@opengeni/config";
|
|
2
|
+
import { loadDirectModelProviderConnection } from "@opengeni/db";
|
|
3
|
+
import { FILESYSTEM_DISCONTINUITY_PROTOCOL } from "./recovery-warning";
|
|
1
4
|
import {
|
|
2
5
|
applySessionTurnSettlement,
|
|
3
6
|
claimSessionWorkForAttempt,
|
|
@@ -14,9 +17,11 @@ import {
|
|
|
14
17
|
type SessionTurnForExecution,
|
|
15
18
|
} from "@opengeni/db";
|
|
16
19
|
import { appendAndPublishTurnEventsFenced, publishDurableSessionEvents } from "@opengeni/events";
|
|
20
|
+
import { linkCurrentSpanToAdmission, turnExecutionTelemetryKey } from "@opengeni/observability";
|
|
17
21
|
import { deliverChildRequiresActionToParent } from "../parent-wake";
|
|
18
22
|
import {
|
|
19
23
|
assertTurnExecutionPolicyMatchesConfigV1,
|
|
24
|
+
settingsForAcceptedSubscriptionTurn,
|
|
20
25
|
resolveTurnExecutionPolicyV1,
|
|
21
26
|
type Settings,
|
|
22
27
|
} from "@opengeni/config";
|
|
@@ -47,18 +52,22 @@ import {
|
|
|
47
52
|
recordSessionEventAppendPhase,
|
|
48
53
|
recordSessionEventPublishLatency,
|
|
49
54
|
recordTurnStartupPhase,
|
|
55
|
+
measureTurnStartupPhase,
|
|
50
56
|
recordTurnStartupMilestone,
|
|
51
57
|
turnLifecycleMetricsFor,
|
|
52
58
|
} from "../../observability-metrics";
|
|
53
59
|
import { createTurnCredentialLeases } from "./credential-leases";
|
|
54
60
|
import { createTurnMediaArtifacts } from "./media-artifacts";
|
|
55
61
|
import { readTurnExecutionPolicyV1 } from "@opengeni/contracts";
|
|
62
|
+
import { turnCredentialRestriction } from "./credential-restriction";
|
|
56
63
|
|
|
57
64
|
import {
|
|
58
65
|
credentialSubjectIdForTurnInitiator,
|
|
59
66
|
turnExecutionPolicyBillingIdentity,
|
|
60
67
|
legacyTurnExecutionPolicyInput,
|
|
61
68
|
ensureRunAllowed,
|
|
69
|
+
AllowanceExhaustedError,
|
|
70
|
+
type AllowanceRefusal,
|
|
62
71
|
} from "./admission";
|
|
63
72
|
import { providerRecoveryCountFromMetadata, isWorkerShutdownCancellation } from "./errors";
|
|
64
73
|
import { throwIfTurnOperationCancelled, waitForTurnOperation } from "./sandbox-provision";
|
|
@@ -178,8 +187,17 @@ export async function claimTurnAttempt(deps: ClaimTurnDeps): Promise<ClaimTurnOu
|
|
|
178
187
|
acknowledgeLostAttemptOwnership,
|
|
179
188
|
} = deps;
|
|
180
189
|
|
|
181
|
-
const deploymentCatalogSettings = (
|
|
182
|
-
|
|
190
|
+
const deploymentCatalogSettings = (
|
|
191
|
+
await measureTurnStartupPhase(
|
|
192
|
+
observability,
|
|
193
|
+
{
|
|
194
|
+
phase: "claim_catalog_read",
|
|
195
|
+
provider: "unresolved",
|
|
196
|
+
backend: "unresolved",
|
|
197
|
+
},
|
|
198
|
+
() => resolveCatalogSettings(db, catalogSourceSettings),
|
|
199
|
+
)
|
|
200
|
+
).settings;
|
|
183
201
|
|
|
184
202
|
const validatePendingSystemUpdateAuthority: NonNullable<
|
|
185
203
|
ClaimSessionWorkForAttemptInput["validatePendingSystemUpdateAuthority"]
|
|
@@ -191,15 +209,25 @@ export async function claimTurnAttempt(deps: ClaimTurnDeps): Promise<ClaimTurnOu
|
|
|
191
209
|
sessionId: input.sessionId,
|
|
192
210
|
update,
|
|
193
211
|
});
|
|
194
|
-
const claim = await
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
212
|
+
const claim = await measureTurnStartupPhase(
|
|
213
|
+
observability,
|
|
214
|
+
{
|
|
215
|
+
phase: "claim_atomic",
|
|
216
|
+
provider: "unresolved",
|
|
217
|
+
backend: "unresolved",
|
|
218
|
+
},
|
|
219
|
+
() =>
|
|
220
|
+
claimSessionWorkForAttempt(db, input.workspaceId, {
|
|
221
|
+
filesystemDiscontinuityProtocol: FILESYSTEM_DISCONTINUITY_PROTOCOL,
|
|
222
|
+
sessionId: input.sessionId,
|
|
223
|
+
workflowId: input.workflowId,
|
|
224
|
+
workflowRunId: input.workflowRunId,
|
|
225
|
+
attemptId: input.attemptId,
|
|
226
|
+
dispatchId,
|
|
227
|
+
trigger: input.trigger,
|
|
228
|
+
validatePendingSystemUpdateAuthority,
|
|
229
|
+
}),
|
|
230
|
+
);
|
|
203
231
|
if (claim.action === "unclaimed") {
|
|
204
232
|
control.activityStatus = "unclaimed";
|
|
205
233
|
return { exit: { status: "unclaimed", reason: claim.reason } };
|
|
@@ -209,6 +237,21 @@ export async function claimTurnAttempt(deps: ClaimTurnDeps): Promise<ClaimTurnOu
|
|
|
209
237
|
attempt.dispatchId = dispatchId;
|
|
210
238
|
attempt.executionGeneration = turn.executionGeneration;
|
|
211
239
|
attempt.providerRecoveryCount = providerRecoveryCountFromMetadata(turn.metadata);
|
|
240
|
+
const authRecovery = turn.metadata?.claudeAuthRecovery;
|
|
241
|
+
attempt.claudeAuthRecovery =
|
|
242
|
+
authRecovery &&
|
|
243
|
+
typeof authRecovery === "object" &&
|
|
244
|
+
"credentialId" in authRecovery &&
|
|
245
|
+
typeof authRecovery.credentialId === "string" &&
|
|
246
|
+
"credentialVersion" in authRecovery &&
|
|
247
|
+
typeof authRecovery.credentialVersion === "number" &&
|
|
248
|
+
Number.isSafeInteger(authRecovery.credentialVersion) &&
|
|
249
|
+
authRecovery.credentialVersion > 0
|
|
250
|
+
? {
|
|
251
|
+
credentialId: authRecovery.credentialId,
|
|
252
|
+
credentialVersion: authRecovery.credentialVersion,
|
|
253
|
+
}
|
|
254
|
+
: undefined;
|
|
212
255
|
attempt.triggerEventId = turn.triggerEventId;
|
|
213
256
|
// The durable attempt UUID is stable for a Temporal retry of this activity
|
|
214
257
|
// input and freshly generated for worker-death redispatch/continue-as-new.
|
|
@@ -223,25 +266,42 @@ export async function claimTurnAttempt(deps: ClaimTurnDeps): Promise<ClaimTurnOu
|
|
|
223
266
|
// Therefore every failure with no turnId came from the one atomic claim
|
|
224
267
|
// transaction and can be classified without conflating ordinary runtime
|
|
225
268
|
// or transport failures with admission failures.
|
|
226
|
-
const session = await requireSession(db, input.workspaceId, input.sessionId);
|
|
227
269
|
let installedApiIntegrations: readonly ApiIntegrationRuntime[] = [];
|
|
228
270
|
const credentialSubjectId = credentialSubjectIdForTurnInitiator(turn);
|
|
229
271
|
const fileAuthoritySubjectId = turn.initiatingHumanSubjectId ?? null;
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
:
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
onResolvedApiIntegrations: (integrations) => {
|
|
241
|
-
installedApiIntegrations = integrations;
|
|
272
|
+
// Both are fresh scoped reads on the root pool after exact claim ownership.
|
|
273
|
+
// Neither consumes the other's result; retain the capability helper's own
|
|
274
|
+
// subject/delegation authority and await both before credential/policy gates.
|
|
275
|
+
const [session, mcpSettings] = await Promise.all([
|
|
276
|
+
measureTurnStartupPhase(
|
|
277
|
+
observability,
|
|
278
|
+
{
|
|
279
|
+
phase: "claim_session_read",
|
|
280
|
+
provider: "unresolved",
|
|
281
|
+
backend: turn.sandboxBackend,
|
|
242
282
|
},
|
|
243
|
-
|
|
244
|
-
|
|
283
|
+
() => requireSession(db, input.workspaceId, input.sessionId),
|
|
284
|
+
),
|
|
285
|
+
measureTurnStartupPhase(
|
|
286
|
+
observability,
|
|
287
|
+
{
|
|
288
|
+
phase: "claim_capability_settings",
|
|
289
|
+
provider: "unresolved",
|
|
290
|
+
backend: turn.sandboxBackend,
|
|
291
|
+
},
|
|
292
|
+
() =>
|
|
293
|
+
settingsWithEnabledCapabilityMcpServers(db, input.workspaceId, deploymentCatalogSettings, {
|
|
294
|
+
...(credentialSubjectId
|
|
295
|
+
? { subjectId: credentialSubjectId }
|
|
296
|
+
: {
|
|
297
|
+
personalConnectionDelegations: turn.personalConnectionDelegations,
|
|
298
|
+
}),
|
|
299
|
+
onResolvedApiIntegrations: (integrations) => {
|
|
300
|
+
installedApiIntegrations = integrations;
|
|
301
|
+
},
|
|
302
|
+
}),
|
|
303
|
+
),
|
|
304
|
+
]);
|
|
245
305
|
// Read the active-credential flag once for the runtime capability overlay.
|
|
246
306
|
// Accepted billing/provider identity comes from the turn policy below,
|
|
247
307
|
// never from this mutable health snapshot.
|
|
@@ -249,6 +309,7 @@ export async function claimTurnAttempt(deps: ClaimTurnDeps): Promise<ClaimTurnOu
|
|
|
249
309
|
db,
|
|
250
310
|
mcpSettings,
|
|
251
311
|
input.workspaceId,
|
|
312
|
+
turn.id,
|
|
252
313
|
);
|
|
253
314
|
const codexSettings = await settingsWithCodexCredential(
|
|
254
315
|
db,
|
|
@@ -273,21 +334,42 @@ export async function claimTurnAttempt(deps: ClaimTurnDeps): Promise<ClaimTurnOu
|
|
|
273
334
|
gatewaySettings,
|
|
274
335
|
claimedPolicy.kind === "valid" ? claimedPolicy.policy.productModelId : turn.model,
|
|
275
336
|
);
|
|
276
|
-
|
|
337
|
+
let capabilitySettings = await settingsWithOrganizationProviderCredentials(
|
|
277
338
|
db,
|
|
278
339
|
input.accountId,
|
|
279
340
|
input.workspaceId,
|
|
280
341
|
workspaceProviderSettings,
|
|
281
342
|
claimedPolicy.kind === "valid" ? claimedPolicy.policy.productModelId : turn.model,
|
|
282
343
|
);
|
|
344
|
+
const selectedDirectConnection = await loadDirectModelProviderConnection(
|
|
345
|
+
db,
|
|
346
|
+
capabilitySettings,
|
|
347
|
+
input.workspaceId,
|
|
348
|
+
claimedPolicy.kind === "valid" ? claimedPolicy.policy.productModelId : (turn.model ?? ""),
|
|
349
|
+
);
|
|
350
|
+
// Execution only needs the selected customer connection. Ordinary turns
|
|
351
|
+
// must not load or install unrelated workspace provider configurations.
|
|
352
|
+
if (selectedDirectConnection) {
|
|
353
|
+
capabilitySettings = withDirectModelProviders(capabilitySettings, [selectedDirectConnection]);
|
|
354
|
+
}
|
|
283
355
|
const codexAppsCredentialId = capabilitySettings.codexConnectedAppsEnabled
|
|
284
356
|
? await resolveCodexAppsCredentialIdForRun(db, input.workspaceId)
|
|
285
357
|
: null;
|
|
286
|
-
|
|
287
|
-
const policyForAbsent =
|
|
358
|
+
const candidatePolicy =
|
|
288
359
|
claimedPolicy.kind === "valid"
|
|
289
360
|
? claimedPolicy.policy
|
|
290
361
|
: resolveTurnExecutionPolicyV1(capabilitySettings, legacyTurnExecutionPolicyInput(turn));
|
|
362
|
+
// This context is frozen by the accepted-turn writer from the exact source
|
|
363
|
+
// turn. Its reserved restriction field cannot come from public service JSON.
|
|
364
|
+
const credentialRestriction =
|
|
365
|
+
claimedPolicy.kind === "absent"
|
|
366
|
+
? turn.initiatorContext?.credentialRestriction === "developer_setup"
|
|
367
|
+
? "developer_setup"
|
|
368
|
+
: turnCredentialRestriction(candidatePolicy, session.metadata)
|
|
369
|
+
: undefined;
|
|
370
|
+
const policyForAbsent = credentialRestriction
|
|
371
|
+
? { ...candidatePolicy, credentialRestriction }
|
|
372
|
+
: candidatePolicy;
|
|
291
373
|
const installedPolicy = await installOrReadTurnExecutionPolicyForAttempt(db, {
|
|
292
374
|
accountId: input.accountId,
|
|
293
375
|
workspaceId: input.workspaceId,
|
|
@@ -300,6 +382,16 @@ export async function claimTurnAttempt(deps: ClaimTurnDeps): Promise<ClaimTurnOu
|
|
|
300
382
|
if (!installedPolicy.accepted) {
|
|
301
383
|
throw new TurnAttemptFencedError(`turn execution policy was fenced: ${installedPolicy.reason}`);
|
|
302
384
|
}
|
|
385
|
+
capabilitySettings = settingsForAcceptedSubscriptionTurn(
|
|
386
|
+
capabilitySettings,
|
|
387
|
+
installedPolicy.policy,
|
|
388
|
+
{
|
|
389
|
+
modelId: turn.model,
|
|
390
|
+
reasoningEffort: turn.reasoningEffort,
|
|
391
|
+
latencyMode: turn.latencyMode,
|
|
392
|
+
},
|
|
393
|
+
);
|
|
394
|
+
runtime.configure(capabilitySettings);
|
|
303
395
|
const verifiedExecutionPolicy = assertTurnExecutionPolicyMatchesConfigV1(
|
|
304
396
|
capabilitySettings,
|
|
305
397
|
installedPolicy.policy,
|
|
@@ -317,10 +409,14 @@ export async function claimTurnAttempt(deps: ClaimTurnDeps): Promise<ClaimTurnOu
|
|
|
317
409
|
billingState.countsTowardTokenCap = billingIdentity.countsTowardTokenCap;
|
|
318
410
|
billingState.isCodexTurn = billingIdentity.codexSubscription;
|
|
319
411
|
billingState.isXaiTurn = billingIdentity.xaiSubscription;
|
|
412
|
+
billingState.isClaudeTurn =
|
|
413
|
+
verifiedExecutionPolicy.provider.kind === "claude-subscription-workspace" ||
|
|
414
|
+
verifiedExecutionPolicy.provider.kind === "claude-subscription-organization";
|
|
320
415
|
const trigger = await getSessionEvent(db, input.workspaceId, attempt.triggerEventId);
|
|
321
416
|
if (!trigger) {
|
|
322
417
|
throw new Error(`Trigger event not found: ${attempt.triggerEventId}`);
|
|
323
418
|
}
|
|
419
|
+
if (trigger.type === "user.message") linkCurrentSpanToAdmission(trigger.id);
|
|
324
420
|
const humanInputResume = await getHumanInputResumeForEvent(
|
|
325
421
|
db,
|
|
326
422
|
input.workspaceId,
|
|
@@ -336,6 +432,7 @@ export async function claimTurnAttempt(deps: ClaimTurnDeps): Promise<ClaimTurnOu
|
|
|
336
432
|
attempt.triggerType = trigger.type;
|
|
337
433
|
const attachPendingUpdatesAfterOpenSuffix = async (): Promise<boolean> => {
|
|
338
434
|
const attached = await claimSessionWorkForAttempt(db, input.workspaceId, {
|
|
435
|
+
filesystemDiscontinuityProtocol: FILESYSTEM_DISCONTINUITY_PROTOCOL,
|
|
339
436
|
sessionId: input.sessionId,
|
|
340
437
|
workflowId: input.workflowId,
|
|
341
438
|
workflowRunId: input.workflowRunId,
|
|
@@ -352,20 +449,27 @@ export async function claimTurnAttempt(deps: ClaimTurnDeps): Promise<ClaimTurnOu
|
|
|
352
449
|
// bypass OpenGeni credit/token gates)
|
|
353
450
|
// AND the optional host `entitlements` port (when bound, its admitRun replaces
|
|
354
451
|
// the local credit read). Unset port → today's local-ledger path.
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
452
|
+
let allowanceRefusal: AllowanceRefusal | null = null;
|
|
453
|
+
try {
|
|
454
|
+
await waitForTurnOperation(
|
|
455
|
+
ensureRunAllowed(
|
|
456
|
+
capabilitySettings,
|
|
457
|
+
db,
|
|
458
|
+
input.accountId,
|
|
459
|
+
input.workspaceId,
|
|
460
|
+
billingState.isExternallyBilledTurn,
|
|
461
|
+
entitlements,
|
|
462
|
+
billingState.chargesOpenGeniCredits,
|
|
463
|
+
billingState.countsTowardTokenCap,
|
|
464
|
+
turn.initiatingHumanSubjectId,
|
|
465
|
+
),
|
|
466
|
+
cancellationSignal,
|
|
467
|
+
undefined,
|
|
468
|
+
);
|
|
469
|
+
} catch (error) {
|
|
470
|
+
if (!(error instanceof AllowanceExhaustedError)) throw error;
|
|
471
|
+
allowanceRefusal = error.refusal;
|
|
472
|
+
}
|
|
369
473
|
// Setup (variableSet load, MCP connects, sandbox restore) does not
|
|
370
474
|
// stream and so never observes cancellation on its own; these explicit
|
|
371
475
|
// checks let a graceful shutdown checkpoint the turn before the worker is
|
|
@@ -387,6 +491,7 @@ export async function claimTurnAttempt(deps: ClaimTurnDeps): Promise<ClaimTurnOu
|
|
|
387
491
|
turnId: attempt.turnId,
|
|
388
492
|
opAcks: {},
|
|
389
493
|
};
|
|
494
|
+
eventing.heartbeatDetails = heartbeatDetails;
|
|
390
495
|
const opJournal = makeTurnOpJournal(activityContext, heartbeatDetails);
|
|
391
496
|
eventing.heartbeatTimer = startActivityHeartbeat(activityContext, heartbeatDetails);
|
|
392
497
|
let producerSeq = 0;
|
|
@@ -497,6 +602,9 @@ export async function claimTurnAttempt(deps: ClaimTurnDeps): Promise<ClaimTurnOu
|
|
|
497
602
|
...(inputSettlement.suppressGoalContinuation !== undefined
|
|
498
603
|
? { suppressGoalContinuation: inputSettlement.suppressGoalContinuation }
|
|
499
604
|
: {}),
|
|
605
|
+
...(inputSettlement.allowanceGoalPause
|
|
606
|
+
? { allowanceGoalPause: inputSettlement.allowanceGoalPause }
|
|
607
|
+
: {}),
|
|
500
608
|
events: inputs,
|
|
501
609
|
...(runState ? { runState } : {}),
|
|
502
610
|
...(compactionRequestFailure ? { compactionRequestFailure } : {}),
|
|
@@ -547,12 +655,47 @@ export async function claimTurnAttempt(deps: ClaimTurnDeps): Promise<ClaimTurnOu
|
|
|
547
655
|
throwIfTurnCancelled();
|
|
548
656
|
recordTurnStartupPhase(observability, {
|
|
549
657
|
phase: "claim_and_policy",
|
|
658
|
+
executionCorrelationId: turnExecutionTelemetryKey(
|
|
659
|
+
input.workspaceId,
|
|
660
|
+
input.sessionId,
|
|
661
|
+
input.attemptId,
|
|
662
|
+
),
|
|
550
663
|
provider: turnExecutionPolicy.providerId,
|
|
551
664
|
backend: turn.sandboxBackend,
|
|
552
665
|
outcome: "completed",
|
|
553
666
|
durationSeconds: (performance.now() - activityStarted) / 1_000,
|
|
554
667
|
});
|
|
555
668
|
const turnStartSettlementStartedAt = performance.now();
|
|
669
|
+
if (allowanceRefusal) {
|
|
670
|
+
// Claim has frozen the exact human, but no provider or sandbox has started.
|
|
671
|
+
// Use the same terminal valve as a post-response stop, retaining a usable
|
|
672
|
+
// session and a visible typed refusal instead of manufacturing a failure.
|
|
673
|
+
if (
|
|
674
|
+
!(await eventing.settle({
|
|
675
|
+
events: [
|
|
676
|
+
{ type: "usage.exhausted", payload: allowanceRefusal },
|
|
677
|
+
{
|
|
678
|
+
type: "turn.completed",
|
|
679
|
+
payload: {
|
|
680
|
+
output: "",
|
|
681
|
+
segmentLimit: "budget_exhausted",
|
|
682
|
+
...allowanceRefusal,
|
|
683
|
+
},
|
|
684
|
+
},
|
|
685
|
+
{ type: "session.status.changed", payload: { status: "idle" } },
|
|
686
|
+
],
|
|
687
|
+
turnStatus: "completed",
|
|
688
|
+
sessionStatus: "idle",
|
|
689
|
+
activeTurnId: null,
|
|
690
|
+
allowanceGoalPause: { rationale: allowanceRefusal.message },
|
|
691
|
+
}))
|
|
692
|
+
) {
|
|
693
|
+
return { exit: claimedResult({ status: "cancelled" }) };
|
|
694
|
+
}
|
|
695
|
+
control.turnMetricOutcome = "completed";
|
|
696
|
+
control.activityStatus = "idle";
|
|
697
|
+
return { exit: claimedResult({ status: "idle" }) };
|
|
698
|
+
}
|
|
556
699
|
if (
|
|
557
700
|
!(await eventing.settle({
|
|
558
701
|
events: [
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import {
|
|
3
|
+
emptyClaudeUsage,
|
|
4
|
+
mergeClaudeUsage,
|
|
5
|
+
parseClaudeUsageHeaders,
|
|
6
|
+
type parseModelProvidersJson,
|
|
7
|
+
type ClaudeUsageObservation,
|
|
8
|
+
} from "@opengeni/config";
|
|
9
|
+
|
|
10
|
+
type Scope = "workspace" | "organization";
|
|
11
|
+
type ClaudeRequestCredential = {
|
|
12
|
+
token: string;
|
|
13
|
+
connectionId: string;
|
|
14
|
+
credentialVersion: number;
|
|
15
|
+
};
|
|
16
|
+
export class ClaudeSubscriptionConnectionUnavailable extends Error {
|
|
17
|
+
readonly status = 409;
|
|
18
|
+
readonly code = "claude_subscription_connection_changed";
|
|
19
|
+
constructor() {
|
|
20
|
+
super(
|
|
21
|
+
"Claude connection changed or was disconnected. Start a new turn with the current connection.",
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export type CapturedClaudeUsage = {
|
|
26
|
+
scope: Scope;
|
|
27
|
+
token: string;
|
|
28
|
+
expectedConnectionId: string;
|
|
29
|
+
expectedCredentialVersion: number;
|
|
30
|
+
observation?: ClaudeUsageObservation;
|
|
31
|
+
responseStatus?: number;
|
|
32
|
+
upstreamModelId?: string;
|
|
33
|
+
requestId?: string;
|
|
34
|
+
refresh?: { status: "reconnect"; checkedAt: string };
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/** Capture the exact credential before requests; replacement fences late responses. */
|
|
38
|
+
export async function createClaudeUsageObserver(
|
|
39
|
+
providers: ReturnType<typeof parseModelProvidersJson>,
|
|
40
|
+
latest: Map<string, CapturedClaudeUsage>,
|
|
41
|
+
readCredential: (scope: Scope) => Promise<{
|
|
42
|
+
token: string;
|
|
43
|
+
connectionId: string;
|
|
44
|
+
credentialVersion: number;
|
|
45
|
+
} | null>,
|
|
46
|
+
) {
|
|
47
|
+
const managedProviderIds = new Set(
|
|
48
|
+
providers
|
|
49
|
+
.filter(
|
|
50
|
+
(provider) =>
|
|
51
|
+
provider.kind === "claude-subscription-workspace" ||
|
|
52
|
+
provider.kind === "claude-subscription-organization",
|
|
53
|
+
)
|
|
54
|
+
.map((provider) => provider.id),
|
|
55
|
+
);
|
|
56
|
+
const bindings = await Promise.all(
|
|
57
|
+
providers
|
|
58
|
+
.filter(
|
|
59
|
+
(provider) =>
|
|
60
|
+
provider.kind === "claude-subscription-workspace" ||
|
|
61
|
+
provider.kind === "claude-subscription-organization",
|
|
62
|
+
)
|
|
63
|
+
.map(async (provider) => {
|
|
64
|
+
const scope: Scope =
|
|
65
|
+
provider.kind === "claude-subscription-workspace" ? "workspace" : "organization";
|
|
66
|
+
const binding = provider.anthropic?.credentialBinding;
|
|
67
|
+
if (binding && provider.apiKey)
|
|
68
|
+
return [
|
|
69
|
+
provider.id,
|
|
70
|
+
{
|
|
71
|
+
scope,
|
|
72
|
+
token: provider.apiKey,
|
|
73
|
+
expectedConnectionId: binding.connectionId,
|
|
74
|
+
expectedCredentialVersion: binding.credentialVersion,
|
|
75
|
+
},
|
|
76
|
+
] as const;
|
|
77
|
+
const credential = await readCredential(scope).catch(() => null);
|
|
78
|
+
if (!credential || credential.token !== provider.apiKey) return null;
|
|
79
|
+
return [
|
|
80
|
+
provider.id,
|
|
81
|
+
{
|
|
82
|
+
scope,
|
|
83
|
+
token: credential.token,
|
|
84
|
+
expectedConnectionId: credential.connectionId,
|
|
85
|
+
expectedCredentialVersion: credential.credentialVersion,
|
|
86
|
+
},
|
|
87
|
+
] as const;
|
|
88
|
+
}),
|
|
89
|
+
);
|
|
90
|
+
const captured = new Map(bindings.filter((binding) => binding !== null));
|
|
91
|
+
let anonymousReceipt = 0;
|
|
92
|
+
const observeBinding = (
|
|
93
|
+
binding:
|
|
94
|
+
| Pick<
|
|
95
|
+
CapturedClaudeUsage,
|
|
96
|
+
"scope" | "token" | "expectedConnectionId" | "expectedCredentialVersion"
|
|
97
|
+
>
|
|
98
|
+
| undefined,
|
|
99
|
+
response: Response,
|
|
100
|
+
upstreamModelId?: string,
|
|
101
|
+
requestToken?: string | null,
|
|
102
|
+
) => {
|
|
103
|
+
if (requestToken === null) return;
|
|
104
|
+
if (!binding) return;
|
|
105
|
+
const { scope, ...capturedIdentity } = binding;
|
|
106
|
+
const identity = { ...capturedIdentity, token: requestToken ?? capturedIdentity.token };
|
|
107
|
+
// Same-generation OAuth renewal can overlap an older request. Never attach
|
|
108
|
+
// its authentication failure to the newly renewed token or merge the two.
|
|
109
|
+
const tokenKey = createHash("sha256").update(identity.token).digest("hex");
|
|
110
|
+
const rawRequestId = response.headers.get("request-id");
|
|
111
|
+
const requestId = rawRequestId && rawRequestId.length <= 256 ? rawRequestId : undefined;
|
|
112
|
+
// Retain exact physical responses, including HTTP 200 streams which can
|
|
113
|
+
// terminate with typed authentication/rate-limit errors. Parallel titles
|
|
114
|
+
// must never overwrite the serving request receipt.
|
|
115
|
+
const receiptKey =
|
|
116
|
+
requestId ??
|
|
117
|
+
(response.status === 401 || response.status === 429
|
|
118
|
+
? `anonymous-${++anonymousReceipt}`
|
|
119
|
+
: "aggregate");
|
|
120
|
+
const captureKey = `${receiptKey}:${scope}:${identity.expectedConnectionId}:${identity.expectedCredentialVersion}:${tokenKey}:${upstreamModelId ?? "unknown"}`;
|
|
121
|
+
const previous = latest.get(captureKey);
|
|
122
|
+
let observation = parseClaudeUsageHeaders(response.headers, new Date(), upstreamModelId);
|
|
123
|
+
if (observation && previous?.observation) {
|
|
124
|
+
const merged = mergeClaudeUsage(
|
|
125
|
+
mergeClaudeUsage(emptyClaudeUsage(binding.expectedCredentialVersion), previous.observation),
|
|
126
|
+
observation,
|
|
127
|
+
);
|
|
128
|
+
observation = {
|
|
129
|
+
windows: merged.windows,
|
|
130
|
+
observedAt: merged.observedAt!,
|
|
131
|
+
source: merged.source!,
|
|
132
|
+
requestStatus: merged.requestStatus ?? null,
|
|
133
|
+
requestRestrictions: merged.requestRestrictions ?? [],
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
if (requestId || observation || response.status === 401 || response.status === 429)
|
|
137
|
+
latest.set(captureKey, {
|
|
138
|
+
scope,
|
|
139
|
+
responseStatus: response.status,
|
|
140
|
+
...(response.headers.get("request-id") && response.headers.get("request-id")!.length <= 256
|
|
141
|
+
? { requestId: response.headers.get("request-id")! }
|
|
142
|
+
: {}),
|
|
143
|
+
...(upstreamModelId ? { upstreamModelId } : {}),
|
|
144
|
+
...identity,
|
|
145
|
+
...(previous?.observation && !observation ? { observation: previous.observation } : {}),
|
|
146
|
+
...(observation ? { observation } : {}),
|
|
147
|
+
...(response.status === 401
|
|
148
|
+
? { refresh: { status: "reconnect", checkedAt: new Date().toISOString() } }
|
|
149
|
+
: {}),
|
|
150
|
+
});
|
|
151
|
+
};
|
|
152
|
+
const observe = (
|
|
153
|
+
providerId: string,
|
|
154
|
+
response: Response,
|
|
155
|
+
upstreamModelId?: string,
|
|
156
|
+
requestToken?: string | null,
|
|
157
|
+
) => observeBinding(captured.get(providerId), response, upstreamModelId, requestToken);
|
|
158
|
+
const prepareRequestWithObserver = async (
|
|
159
|
+
providerId: string,
|
|
160
|
+
headers: Headers,
|
|
161
|
+
resolve: (binding: {
|
|
162
|
+
scope: Scope;
|
|
163
|
+
expectedConnectionId: string;
|
|
164
|
+
expectedCredentialVersion: number;
|
|
165
|
+
}) => Promise<ClaudeRequestCredential | null>,
|
|
166
|
+
) => {
|
|
167
|
+
if (!managedProviderIds.has(providerId)) return { headers, observe };
|
|
168
|
+
const binding = captured.get(providerId);
|
|
169
|
+
if (!binding) throw new ClaudeSubscriptionConnectionUnavailable();
|
|
170
|
+
const credential = await resolve({
|
|
171
|
+
scope: binding.scope,
|
|
172
|
+
expectedConnectionId: binding.expectedConnectionId,
|
|
173
|
+
expectedCredentialVersion: binding.expectedCredentialVersion,
|
|
174
|
+
});
|
|
175
|
+
if (
|
|
176
|
+
!credential ||
|
|
177
|
+
credential.connectionId !== binding.expectedConnectionId ||
|
|
178
|
+
credential.credentialVersion !== binding.expectedCredentialVersion
|
|
179
|
+
)
|
|
180
|
+
throw new ClaudeSubscriptionConnectionUnavailable();
|
|
181
|
+
const dispatched = Object.freeze({ ...binding, token: credential.token });
|
|
182
|
+
captured.set(providerId, dispatched);
|
|
183
|
+
headers.set("authorization", `Bearer ${credential.token}`);
|
|
184
|
+
headers.delete("x-api-key");
|
|
185
|
+
return {
|
|
186
|
+
headers,
|
|
187
|
+
observe: (
|
|
188
|
+
_providerId: string,
|
|
189
|
+
response: Response,
|
|
190
|
+
upstreamModelId?: string,
|
|
191
|
+
requestToken?: string | null,
|
|
192
|
+
) => observeBinding(dispatched, response, upstreamModelId, requestToken),
|
|
193
|
+
};
|
|
194
|
+
};
|
|
195
|
+
return Object.assign(observe, {
|
|
196
|
+
prepareRequestWithObserver,
|
|
197
|
+
async prepareRequest(...args: Parameters<typeof prepareRequestWithObserver>) {
|
|
198
|
+
return (await prepareRequestWithObserver(...args)).headers;
|
|
199
|
+
},
|
|
200
|
+
binding(providerId: string) {
|
|
201
|
+
const binding = captured.get(providerId);
|
|
202
|
+
return binding ? { ...binding } : undefined;
|
|
203
|
+
},
|
|
204
|
+
renew(
|
|
205
|
+
providerId: string,
|
|
206
|
+
credential: {
|
|
207
|
+
token: string;
|
|
208
|
+
connectionId: string;
|
|
209
|
+
credentialVersion: number;
|
|
210
|
+
},
|
|
211
|
+
) {
|
|
212
|
+
const binding = captured.get(providerId);
|
|
213
|
+
if (
|
|
214
|
+
binding &&
|
|
215
|
+
binding.expectedConnectionId === credential.connectionId &&
|
|
216
|
+
binding.expectedCredentialVersion === credential.credentialVersion
|
|
217
|
+
)
|
|
218
|
+
captured.set(providerId, { ...binding, token: credential.token });
|
|
219
|
+
},
|
|
220
|
+
});
|
|
221
|
+
}
|