@opengeni/worker-bundle 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/activities/agent-turn/admission.d.ts +3 -2
- package/dist/activities/agent-turn/compaction-prep.d.ts +1 -0
- package/dist/activities/agent-turn/finalization-monitor.d.ts +6 -1
- package/dist/activities/agent-turn/model-usage.d.ts +10 -0
- package/dist/{activities-control-XZAIMFQJ.js → activities-control-QSDPXLLD.js} +5 -5
- package/dist/activities-control-QSDPXLLD.js.map +1 -0
- package/dist/{activities-turn-4EEVNZCC.js → activities-turn-BMY3CDKL.js} +96 -32
- package/dist/activities-turn-BMY3CDKL.js.map +1 -0
- package/dist/{chunk-OT64XARC.js → chunk-JKMG5ZHH.js} +18 -6
- package/dist/{chunk-OT64XARC.js.map → chunk-JKMG5ZHH.js.map} +1 -1
- package/dist/{chunk-3ZTRWDMN.js → chunk-XONQEVAD.js} +1 -1
- package/dist/chunk-XONQEVAD.js.map +1 -0
- package/dist/index.js +2 -2
- package/dist/observability-metrics.d.ts +1 -1
- package/package.json +21 -21
- package/src/activities/agent-turn/admission.ts +11 -5
- package/src/activities/agent-turn/claim.ts +1 -0
- package/src/activities/agent-turn/compaction-prep.ts +20 -1
- package/src/activities/agent-turn/errors.ts +21 -4
- package/src/activities/agent-turn/failure-settlement.ts +9 -1
- package/src/activities/agent-turn/finalization-monitor.ts +14 -1
- package/src/activities/agent-turn/finalization.ts +5 -0
- package/src/activities/agent-turn/model-usage.ts +38 -0
- package/src/activities/agent-turn/run.ts +1 -0
- package/src/activities/agent-turn/stream-attempt.ts +22 -16
- package/src/activities/knowledge-indexing.ts +2 -2
- package/src/observability-metrics.ts +1 -0
- package/dist/activities-control-XZAIMFQJ.js.map +0 -1
- package/dist/activities-turn-4EEVNZCC.js.map +0 -1
- package/dist/chunk-3ZTRWDMN.js.map +0 -1
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
safeDatabaseErrorFacts,
|
|
12
12
|
isRetryableDatabaseTransportFailure,
|
|
13
13
|
isSessionEventPersistenceError,
|
|
14
|
+
DatabaseTransactionError,
|
|
14
15
|
SandboxLeaseTransitionError,
|
|
15
16
|
} from "@opengeni/db";
|
|
16
17
|
import {
|
|
@@ -419,6 +420,12 @@ function retryableDatabaseFailureCode(
|
|
|
419
420
|
const boundaries = new Set<object>();
|
|
420
421
|
const ownDatabaseNodes = new Set<object>();
|
|
421
422
|
const codes = new Set<PostClaimDatabaseRecoveryDetail["code"]>();
|
|
423
|
+
const ownChildren = (node: object): object[] =>
|
|
424
|
+
node instanceof DatabaseTransactionError
|
|
425
|
+
? // Callback failures retained beside a failed rollback supply vetoes,
|
|
426
|
+
// never driver provenance for a provider's connection-looking error.
|
|
427
|
+
[...graph.get(node)!].filter((child) => child === node.cause)
|
|
428
|
+
: [...graph.get(node)!];
|
|
422
429
|
// Ask the canonical transport predicate about ONLY this node's facts. Its
|
|
423
430
|
// recursive search must not pair a DB sibling with an unrelated provider.
|
|
424
431
|
for (const node of graph.keys()) {
|
|
@@ -441,7 +448,11 @@ function retryableDatabaseFailureCode(
|
|
|
441
448
|
: isDatabaseConnectionSqlState(sqlState)
|
|
442
449
|
)
|
|
443
450
|
transports.add(node);
|
|
444
|
-
if (
|
|
451
|
+
if (
|
|
452
|
+
node instanceof DrizzleQueryError ||
|
|
453
|
+
node instanceof DatabaseTransactionError ||
|
|
454
|
+
isSessionEventPersistenceError(node)
|
|
455
|
+
) {
|
|
445
456
|
// Only actual errors raised at our ORM/typed persistence boundary own
|
|
446
457
|
// their driver subtree. A PostgresError name, SDK wrapper or provider
|
|
447
458
|
// socket by itself is never own-client provenance for a running turn.
|
|
@@ -449,7 +460,7 @@ function retryableDatabaseFailureCode(
|
|
|
449
460
|
for (const source of queue) {
|
|
450
461
|
if (ownDatabaseNodes.has(source)) continue;
|
|
451
462
|
ownDatabaseNodes.add(source);
|
|
452
|
-
queue.push(...
|
|
463
|
+
queue.push(...ownChildren(source));
|
|
453
464
|
}
|
|
454
465
|
}
|
|
455
466
|
}
|
|
@@ -460,7 +471,7 @@ function retryableDatabaseFailureCode(
|
|
|
460
471
|
if (seen.has(node)) continue;
|
|
461
472
|
seen.add(node);
|
|
462
473
|
if (transports.has(node)) return true;
|
|
463
|
-
queue.push(...
|
|
474
|
+
queue.push(...ownChildren(node));
|
|
464
475
|
}
|
|
465
476
|
return false;
|
|
466
477
|
};
|
|
@@ -469,7 +480,7 @@ function retryableDatabaseFailureCode(
|
|
|
469
480
|
// order; a deeper transport/reset cannot override it either.
|
|
470
481
|
for (const node of graph.keys()) {
|
|
471
482
|
const record = node as Record<string, unknown>;
|
|
472
|
-
if (node instanceof DrizzleQueryError) {
|
|
483
|
+
if (node instanceof DrizzleQueryError || node instanceof DatabaseTransactionError) {
|
|
473
484
|
boundaries.add(node);
|
|
474
485
|
if (hasOwnTransport(node)) codes.add("db_failure");
|
|
475
486
|
}
|
|
@@ -513,6 +524,12 @@ function retryableDatabaseFailureCode(
|
|
|
513
524
|
}
|
|
514
525
|
|
|
515
526
|
const RUNNING_TURN_DATABASE_TRANSPORT_CODES = new Set([
|
|
527
|
+
// postgres.js reports these for a physically lost connection, including
|
|
528
|
+
// transaction cleanup after its socket has already closed. Own-client
|
|
529
|
+
// provenance and the unknown-outcome veto remain mandatory above.
|
|
530
|
+
"CONNECTION_CLOSED",
|
|
531
|
+
"CONNECTION_DESTROYED",
|
|
532
|
+
"CONNECTION_ENDED",
|
|
516
533
|
"ECONNREFUSED",
|
|
517
534
|
"ECONNRESET",
|
|
518
535
|
"CONNECT_TIMEOUT",
|
|
@@ -277,12 +277,20 @@ export async function settleTurnFailure(deps: TurnFailureDeps): Promise<RunAgent
|
|
|
277
277
|
try {
|
|
278
278
|
return await settleTurnFailureInAttempt(deps);
|
|
279
279
|
} catch (error) {
|
|
280
|
+
if (
|
|
281
|
+
deps.control.activityStatus === "recovering" &&
|
|
282
|
+
error instanceof ApplicationFailure &&
|
|
283
|
+
error.type === "OpenGeniPostClaimDatabaseRecovery"
|
|
284
|
+
)
|
|
285
|
+
throw error;
|
|
280
286
|
// Connectivity can disappear while settling an unrelated run error too.
|
|
281
287
|
// Do not overwrite a possibly committed settlement; the control lane
|
|
282
288
|
// re-reads exact ownership and becomes a stale no-op if it already closed.
|
|
283
289
|
if (deps.attempt.turnId && deps.attempt.triggerEventId) {
|
|
284
290
|
const recovery = postClaimDatabaseRecoveryFailure({
|
|
285
|
-
|
|
291
|
+
// A failed rollback/terminal write must not erase no-replay evidence
|
|
292
|
+
// from the failure we were settling (notably unknown tool effects).
|
|
293
|
+
error: new AggregateError([error, deps.error], "Turn failure settlement failed"),
|
|
286
294
|
turnId: deps.attempt.turnId,
|
|
287
295
|
triggerEventId: deps.attempt.triggerEventId,
|
|
288
296
|
executionGeneration: deps.attempt.executionGeneration,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { turnExecutionTelemetryKey, type Observability } from "@opengeni/observability";
|
|
2
2
|
import type { TurnHeartbeatDetails } from "../../op-journal";
|
|
3
3
|
import { armTurnQuiescenceWatchdog } from "./quiescence";
|
|
4
4
|
|
|
@@ -42,10 +42,21 @@ export function startTurnFinalizationMonitor(input: {
|
|
|
42
42
|
details: TurnHeartbeatDetails;
|
|
43
43
|
heartbeat: (details: TurnHeartbeatDetails) => void;
|
|
44
44
|
requestWorkerDrain: () => void;
|
|
45
|
+
execution?: { workspaceId: string; sessionId: string; attemptId: string };
|
|
45
46
|
timeoutMs?: number;
|
|
46
47
|
slowAfterMs?: number;
|
|
47
48
|
}) {
|
|
48
49
|
const { observability, details } = input;
|
|
50
|
+
const correlation: { correlationId?: string } = {};
|
|
51
|
+
diagnose(() => {
|
|
52
|
+
if (input.execution) {
|
|
53
|
+
correlation.correlationId = turnExecutionTelemetryKey(
|
|
54
|
+
input.execution.workspaceId,
|
|
55
|
+
input.execution.sessionId,
|
|
56
|
+
input.execution.attemptId,
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
49
60
|
if (!initialized.has(observability)) {
|
|
50
61
|
for (const stage of TURN_FINALIZATION_STAGES) {
|
|
51
62
|
diagnose(() => observability.incrementGauge({ ...INFLIGHT, labels: { stage }, amount: 0 }));
|
|
@@ -88,6 +99,7 @@ export function startTurnFinalizationMonitor(input: {
|
|
|
88
99
|
surface: "turn_finalization",
|
|
89
100
|
outcome: "containment",
|
|
90
101
|
reason: next,
|
|
102
|
+
...correlation,
|
|
91
103
|
});
|
|
92
104
|
} catch {
|
|
93
105
|
// Diagnostic failure must never disable physical containment.
|
|
@@ -104,6 +116,7 @@ export function startTurnFinalizationMonitor(input: {
|
|
|
104
116
|
surface: "turn_finalization",
|
|
105
117
|
outcome: "slow",
|
|
106
118
|
reason: next,
|
|
119
|
+
...correlation,
|
|
107
120
|
});
|
|
108
121
|
}),
|
|
109
122
|
input.slowAfterMs ?? 30_000,
|
|
@@ -128,6 +128,11 @@ export async function finalizeTurnAttempt(deps: TurnFinalizationDeps): Promise<v
|
|
|
128
128
|
}
|
|
129
129
|
},
|
|
130
130
|
requestWorkerDrain: deps.requestWorkerDrain,
|
|
131
|
+
execution: {
|
|
132
|
+
workspaceId: deps.input.workspaceId,
|
|
133
|
+
sessionId: deps.input.sessionId,
|
|
134
|
+
attemptId: deps.input.attemptId,
|
|
135
|
+
},
|
|
131
136
|
});
|
|
132
137
|
try {
|
|
133
138
|
monitor.enter("tool_writers");
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { canonicalizeConfiguredModelId } from "@opengeni/config";
|
|
1
2
|
import {
|
|
2
3
|
applyCreditDebitUpToBalance,
|
|
3
4
|
recordUsageEvent,
|
|
@@ -55,6 +56,27 @@ export function modelUsageSourceKey(input: {
|
|
|
55
56
|
return input.dispatchId ? `${input.dispatchId}:${input.positionalKey}` : input.positionalKey;
|
|
56
57
|
}
|
|
57
58
|
|
|
59
|
+
/** Legacy aggregate usage may only debit a policy shared by its completed calls. */
|
|
60
|
+
export function aggregateCreditPolicyRevision(input: {
|
|
61
|
+
responseRevisions: ReadonlySet<number | undefined>;
|
|
62
|
+
lastAdmittedRevision: number | undefined;
|
|
63
|
+
chargesOpenGeniCredits: boolean;
|
|
64
|
+
totalTokens: number | null;
|
|
65
|
+
}): number | undefined {
|
|
66
|
+
if (
|
|
67
|
+
input.chargesOpenGeniCredits &&
|
|
68
|
+
input.responseRevisions.size > 1 &&
|
|
69
|
+
(input.totalTokens ?? 0) > 0
|
|
70
|
+
) {
|
|
71
|
+
throw new Error("Aggregate model usage spans different credit policy revisions");
|
|
72
|
+
}
|
|
73
|
+
// Bind the completed response, even if later preparation changed admission.
|
|
74
|
+
// Older runtimes without response callbacks retain their admitted snapshot.
|
|
75
|
+
return input.responseRevisions.size === 1
|
|
76
|
+
? input.responseRevisions.values().next().value
|
|
77
|
+
: input.lastAdmittedRevision;
|
|
78
|
+
}
|
|
79
|
+
|
|
58
80
|
export function providerContextTokens(
|
|
59
81
|
usage:
|
|
60
82
|
| {
|
|
@@ -209,6 +231,7 @@ export async function processModelResponseTerminalEvent(input: {
|
|
|
209
231
|
externallyBilled: boolean;
|
|
210
232
|
chargesOpenGeniCredits?: boolean;
|
|
211
233
|
countsTowardTokenCap?: boolean;
|
|
234
|
+
creditPolicyRevision?: number | undefined;
|
|
212
235
|
servingCredentialId: string | null;
|
|
213
236
|
priorSessionCredentialId: string | null;
|
|
214
237
|
emittedSourceKeys: Set<string>;
|
|
@@ -231,6 +254,15 @@ export async function processModelResponseTerminalEvent(input: {
|
|
|
231
254
|
if (!terminal) {
|
|
232
255
|
return { status: "not_response" };
|
|
233
256
|
}
|
|
257
|
+
// Some providers mirror a terminal response before normalized usage arrives.
|
|
258
|
+
// Claiming that empty raw mirror would discard the SDK's billable response.
|
|
259
|
+
if (
|
|
260
|
+
!terminal.usage &&
|
|
261
|
+
input.event.type === "raw_model_stream_event" &&
|
|
262
|
+
input.event.data.type !== "response_done"
|
|
263
|
+
) {
|
|
264
|
+
return { status: "not_response" };
|
|
265
|
+
}
|
|
234
266
|
|
|
235
267
|
const responseOrdinal = input.state.responseCount + 1;
|
|
236
268
|
const sourceKey = modelUsageSourceKey({
|
|
@@ -268,6 +300,7 @@ export async function processModelResponseTerminalEvent(input: {
|
|
|
268
300
|
turnId: input.turnId,
|
|
269
301
|
turnAttemptId: input.turnAttemptId,
|
|
270
302
|
model: input.model,
|
|
303
|
+
creditPolicyRevision: input.creditPolicyRevision,
|
|
271
304
|
externallyBilled: input.externallyBilled,
|
|
272
305
|
...(input.chargesOpenGeniCredits !== undefined
|
|
273
306
|
? { chargesOpenGeniCredits: input.chargesOpenGeniCredits }
|
|
@@ -374,6 +407,7 @@ export async function processCompactionModelUsageEvent(input: {
|
|
|
374
407
|
externallyBilled: boolean;
|
|
375
408
|
chargesOpenGeniCredits?: boolean;
|
|
376
409
|
countsTowardTokenCap?: boolean;
|
|
410
|
+
creditPolicyRevision?: number | undefined;
|
|
377
411
|
servingCredentialId: string | null;
|
|
378
412
|
priorSessionCredentialId: string | null;
|
|
379
413
|
emittedSourceKeys: Set<string>;
|
|
@@ -416,6 +450,7 @@ export async function processCompactionModelUsageEvent(input: {
|
|
|
416
450
|
turnId: input.turnId,
|
|
417
451
|
turnAttemptId: input.turnAttemptId,
|
|
418
452
|
model: input.model,
|
|
453
|
+
creditPolicyRevision: input.creditPolicyRevision,
|
|
419
454
|
externallyBilled: input.externallyBilled,
|
|
420
455
|
...(input.chargesOpenGeniCredits !== undefined
|
|
421
456
|
? { chargesOpenGeniCredits: input.chargesOpenGeniCredits }
|
|
@@ -651,6 +686,7 @@ export async function recordModelUsageAndDebitCredits(
|
|
|
651
686
|
externallyBilled: boolean;
|
|
652
687
|
chargesOpenGeniCredits?: boolean;
|
|
653
688
|
countsTowardTokenCap?: boolean;
|
|
689
|
+
creditPolicyRevision?: number | undefined;
|
|
654
690
|
gatewayBilling?: ModelResponseUsage["gatewayBilling"];
|
|
655
691
|
usage?: ModelUsageInput | ModelCallUsageInput | null;
|
|
656
692
|
normalizedUsage?: ModelCallUsageNormalization;
|
|
@@ -842,6 +878,8 @@ export async function recordModelUsageAndDebitCredits(
|
|
|
842
878
|
workspaceId: input.workspaceId,
|
|
843
879
|
type: "model_usage_debit",
|
|
844
880
|
requestedAmountMicros: costMicros,
|
|
881
|
+
modelId: canonicalizeConfiguredModelId(settings, input.model),
|
|
882
|
+
creditPolicyRevision: input.creditPolicyRevision,
|
|
845
883
|
sourceType: "model_response",
|
|
846
884
|
sourceId: `${input.turnId}:${input.sourceKey}`,
|
|
847
885
|
idempotencyKey: `credit:model_usage_debit:${input.turnId}:${input.sourceKey}`,
|
|
@@ -122,6 +122,7 @@ import {
|
|
|
122
122
|
completedToolCallFromSdkEvent,
|
|
123
123
|
} from "./history";
|
|
124
124
|
import {
|
|
125
|
+
aggregateCreditPolicyRevision,
|
|
125
126
|
modelUsageSourceKey,
|
|
126
127
|
recordCompletedModelCallBeforeOwnershipFences,
|
|
127
128
|
TurnEventPublisher,
|
|
@@ -384,6 +385,8 @@ export async function runTurnStreamAttempt(
|
|
|
384
385
|
);
|
|
385
386
|
let parallelSessionTitle: ReturnType<typeof startParallelSessionTitleGeneration> | null = null;
|
|
386
387
|
let parallelSessionTitleFinished = false;
|
|
388
|
+
let creditPolicyRevision: number | undefined;
|
|
389
|
+
let titleCreditPolicyRevision: number | undefined;
|
|
387
390
|
const finishParallelSessionTitle = async (): Promise<void> => {
|
|
388
391
|
if (parallelSessionTitleFinished) return;
|
|
389
392
|
parallelSessionTitleFinished = true;
|
|
@@ -393,6 +396,7 @@ export async function runTurnStreamAttempt(
|
|
|
393
396
|
if (generated.usage) {
|
|
394
397
|
await processSessionTitleModelUsageEvent({
|
|
395
398
|
usage: generated.usage,
|
|
399
|
+
creditPolicyRevision: titleCreditPolicyRevision,
|
|
396
400
|
state: sessionTitleUsageState,
|
|
397
401
|
dispatchId: modelUsageDispatchId,
|
|
398
402
|
settings,
|
|
@@ -595,7 +599,8 @@ export async function runTurnStreamAttempt(
|
|
|
595
599
|
let finalReplyNudged = false;
|
|
596
600
|
const revalidateModelCallAdmission = async () => {
|
|
597
601
|
await historySink.reconcileConversationTruth({ requireDurable: true });
|
|
598
|
-
await ensureRunAllowedBetweenModelCalls({
|
|
602
|
+
creditPolicyRevision = await ensureRunAllowedBetweenModelCalls({
|
|
603
|
+
modelId: resolvedModel?.configured.id ?? turn.model,
|
|
599
604
|
settings,
|
|
600
605
|
db,
|
|
601
606
|
accountId: input.accountId,
|
|
@@ -625,6 +630,7 @@ export async function runTurnStreamAttempt(
|
|
|
625
630
|
signal: runtimeCancellationSignal,
|
|
626
631
|
admit: revalidateModelCallAdmission,
|
|
627
632
|
});
|
|
633
|
+
const responseCreditPolicyRevisions = new Set<number | undefined>();
|
|
628
634
|
const responseCountBeforeStream = modelResponseState.responseCount;
|
|
629
635
|
eventing.batcher = null;
|
|
630
636
|
// The SDK emits every processed call item for one model response before
|
|
@@ -842,7 +848,10 @@ export async function runTurnStreamAttempt(
|
|
|
842
848
|
attempt.modelRequestStarted = true;
|
|
843
849
|
return await runtime.runStream(agent, runInput!, eventing.modelRunSettings, {
|
|
844
850
|
beforeModelRequest: modelCallAdmission.beforeModelRequest,
|
|
845
|
-
onModelResponse:
|
|
851
|
+
onModelResponse: (event) => {
|
|
852
|
+
responseCreditPolicyRevisions.add(creditPolicyRevision);
|
|
853
|
+
return modelCallAdmission.onModelResponse(event);
|
|
854
|
+
},
|
|
846
855
|
signal: runtimeCancellationSignal,
|
|
847
856
|
sandboxEnvironment,
|
|
848
857
|
onModelVisibleContext: async (snapshot) => {
|
|
@@ -1068,6 +1077,7 @@ export async function runTurnStreamAttempt(
|
|
|
1068
1077
|
? await media.retainNativeGeneratedImage(generatedImage)
|
|
1069
1078
|
: null;
|
|
1070
1079
|
const responseResult = await processModelResponseTerminalEvent({
|
|
1080
|
+
creditPolicyRevision,
|
|
1071
1081
|
event: next.value,
|
|
1072
1082
|
state: modelResponseState,
|
|
1073
1083
|
dispatchId: modelUsageDispatchId,
|
|
@@ -1158,21 +1168,9 @@ export async function runTurnStreamAttempt(
|
|
|
1158
1168
|
await historySink.reconcileConversationTruth();
|
|
1159
1169
|
turnLifecycleMetricsFor(observability).progress({ attemptId: input.attemptId });
|
|
1160
1170
|
modelCheckpointMemoryCollector.schedule(observability);
|
|
1161
|
-
await ensureRunAllowedBetweenModelCalls({
|
|
1162
|
-
settings,
|
|
1163
|
-
db,
|
|
1164
|
-
accountId: input.accountId,
|
|
1165
|
-
workspaceId: input.workspaceId,
|
|
1166
|
-
isExternallyBilledTurn: billingState.isExternallyBilledTurn,
|
|
1167
|
-
entitlements,
|
|
1168
|
-
chargesOpenGeniCredits: billingState.chargesOpenGeniCredits,
|
|
1169
|
-
countsTowardTokenCap: billingState.countsTowardTokenCap,
|
|
1170
|
-
initiatingHumanSubjectId: turn.initiatingHumanSubjectId,
|
|
1171
|
-
serializedRunState: () =>
|
|
1172
|
-
media.compactMediaRunState(String(eventing.stream!.state.toString())),
|
|
1173
|
-
});
|
|
1174
1171
|
}
|
|
1175
|
-
// Release
|
|
1172
|
+
// Release after settlement. The producer checks fresh admission before
|
|
1173
|
+
// its next request; a final response keeps the revision it ran under.
|
|
1176
1174
|
modelCallAdmission.settle(next.value);
|
|
1177
1175
|
const durableSdkEvent = generatedImageReceipt
|
|
1178
1176
|
? compactGeneratedImageSdkEvent(next.value, generatedImageReceipt)
|
|
@@ -1561,6 +1559,12 @@ export async function runTurnStreamAttempt(
|
|
|
1561
1559
|
if (!streamSawPerResponseUsage) {
|
|
1562
1560
|
const aggregateUsage = eventing.stream.state.usage;
|
|
1563
1561
|
const normalizedAggregateUsage = normalizeModelCallUsage(aggregateUsage);
|
|
1562
|
+
const aggregatePolicyRevision = aggregateCreditPolicyRevision({
|
|
1563
|
+
responseRevisions: responseCreditPolicyRevisions,
|
|
1564
|
+
lastAdmittedRevision: creditPolicyRevision,
|
|
1565
|
+
chargesOpenGeniCredits: billingState.chargesOpenGeniCredits,
|
|
1566
|
+
totalTokens: normalizedAggregateUsage.totalTokens,
|
|
1567
|
+
});
|
|
1564
1568
|
const aggregateInput = normalizedAggregateUsage.telemetry.inputTokens;
|
|
1565
1569
|
const aggregateSourceKey = modelUsageSourceKey({
|
|
1566
1570
|
responseId: null,
|
|
@@ -1583,6 +1587,7 @@ export async function runTurnStreamAttempt(
|
|
|
1583
1587
|
leaseLostMessage: "Provider credential lease expired during the active turn",
|
|
1584
1588
|
recordUsage: async () => {
|
|
1585
1589
|
const billing = await recordModelUsageAndDebitCredits(settings, db, {
|
|
1590
|
+
creditPolicyRevision: aggregatePolicyRevision,
|
|
1586
1591
|
accountId: input.accountId,
|
|
1587
1592
|
workspaceId: input.workspaceId,
|
|
1588
1593
|
sessionId: input.sessionId,
|
|
@@ -1975,6 +1980,7 @@ export async function runTurnStreamAttempt(
|
|
|
1975
1980
|
turnExecutionPolicy.providerId,
|
|
1976
1981
|
turnExecutionPolicy.latencyMode,
|
|
1977
1982
|
);
|
|
1983
|
+
titleCreditPolicyRevision = creditPolicyRevision;
|
|
1978
1984
|
parallelSessionTitle = startParallelSessionTitleGeneration({
|
|
1979
1985
|
signal: runtimeCancellationSignal,
|
|
1980
1986
|
generate: async (signal) =>
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
creditDebitAttributionMetadata,
|
|
11
11
|
deferKnowledgeIndexJob,
|
|
12
12
|
freezeKnowledgeIndexBillingMode,
|
|
13
|
-
|
|
13
|
+
getSpendableCreditBalance,
|
|
14
14
|
guardPaidKnowledgeIndexPublication,
|
|
15
15
|
knowledgeIndexBillingActivationTime,
|
|
16
16
|
readKnowledgeIndexSource,
|
|
@@ -211,7 +211,7 @@ export function createKnowledgeIndexingActivities(
|
|
|
211
211
|
return;
|
|
212
212
|
}
|
|
213
213
|
if (paid && current.nextIndex === 0) {
|
|
214
|
-
const balance = await
|
|
214
|
+
const balance = await getSpendableCreditBalance(lockedDb, claim.accountId);
|
|
215
215
|
if (balance.balanceMicros <= 0) {
|
|
216
216
|
await waitKnowledgeIndexForFunding(lockedDb, claim);
|
|
217
217
|
result.deferred++;
|
|
@@ -1308,6 +1308,7 @@ export function recordSandboxDeadlineRotationsRequested(
|
|
|
1308
1308
|
export const SANDBOX_COMMAND_CONTAINMENT_OUTCOMES = [
|
|
1309
1309
|
"idle_enrolled",
|
|
1310
1310
|
"deadline_enrolled",
|
|
1311
|
+
"quiescence_enrolled",
|
|
1311
1312
|
"resumed_enrolled",
|
|
1312
1313
|
"not_eligible",
|
|
1313
1314
|
"inspection_failed",
|