audit-tools 0.28.8 → 0.28.10
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/audit-code-wrapper-install-hosts.mjs +133 -27
- package/dist/audit/cli/confirmIntentStep.d.ts +1 -0
- package/dist/audit/cli/confirmIntentStep.d.ts.map +1 -1
- package/dist/audit/cli/confirmIntentStep.js +14 -10
- package/dist/audit/cli/confirmIntentStep.js.map +1 -1
- package/dist/audit/cli/dispatch/quotaPool.d.ts.map +1 -1
- package/dist/audit/cli/dispatch/quotaPool.js +47 -39
- package/dist/audit/cli/dispatch/quotaPool.js.map +1 -1
- package/dist/audit/cli/dispatch.d.ts +15 -1
- package/dist/audit/cli/dispatch.d.ts.map +1 -1
- package/dist/audit/cli/dispatch.js +54 -19
- package/dist/audit/cli/dispatch.js.map +1 -1
- package/dist/audit/cli/hybridDispatch.d.ts +46 -0
- package/dist/audit/cli/hybridDispatch.d.ts.map +1 -0
- package/dist/audit/cli/hybridDispatch.js +77 -0
- package/dist/audit/cli/hybridDispatch.js.map +1 -0
- package/dist/audit/cli/nextStepHelpers.d.ts.map +1 -1
- package/dist/audit/cli/nextStepHelpers.js +119 -2
- package/dist/audit/cli/nextStepHelpers.js.map +1 -1
- package/dist/audit/cli/reviewRun.d.ts +19 -0
- package/dist/audit/cli/reviewRun.d.ts.map +1 -1
- package/dist/audit/cli/reviewRun.js +2 -2
- package/dist/audit/cli/reviewRun.js.map +1 -1
- package/dist/audit/cli/rollingAuditDispatch.d.ts +57 -4
- package/dist/audit/cli/rollingAuditDispatch.d.ts.map +1 -1
- package/dist/audit/cli/rollingAuditDispatch.js +137 -10
- package/dist/audit/cli/rollingAuditDispatch.js.map +1 -1
- package/dist/audit/cli/scoreAuditCommand.d.ts +16 -0
- package/dist/audit/cli/scoreAuditCommand.d.ts.map +1 -0
- package/dist/audit/cli/scoreAuditCommand.js +82 -0
- package/dist/audit/cli/scoreAuditCommand.js.map +1 -0
- package/dist/audit/cli.d.ts.map +1 -1
- package/dist/audit/cli.js +5 -1
- package/dist/audit/cli.js.map +1 -1
- package/dist/audit/orchestrator/designReviewProjection.d.ts +9 -1
- package/dist/audit/orchestrator/designReviewProjection.d.ts.map +1 -1
- package/dist/audit/orchestrator/designReviewProjection.js +19 -1
- package/dist/audit/orchestrator/designReviewProjection.js.map +1 -1
- package/dist/audit/orchestrator/designReviewPrompt.d.ts +2 -0
- package/dist/audit/orchestrator/designReviewPrompt.d.ts.map +1 -1
- package/dist/audit/orchestrator/designReviewPrompt.js +11 -1
- package/dist/audit/orchestrator/designReviewPrompt.js.map +1 -1
- package/dist/audit/orchestrator/executorRunners.js +1 -1
- package/dist/audit/orchestrator/executorRunners.js.map +1 -1
- package/dist/audit/orchestrator/intakeExecutors.d.ts +9 -1
- package/dist/audit/orchestrator/intakeExecutors.d.ts.map +1 -1
- package/dist/audit/orchestrator/intakeExecutors.js +16 -3
- package/dist/audit/orchestrator/intakeExecutors.js.map +1 -1
- package/dist/audit/orchestrator/intentCheckpointExecutor.d.ts.map +1 -1
- package/dist/audit/orchestrator/intentCheckpointExecutor.js +3 -0
- package/dist/audit/orchestrator/intentCheckpointExecutor.js.map +1 -1
- package/dist/audit/orchestrator/intentInterpreter.d.ts +21 -7
- package/dist/audit/orchestrator/intentInterpreter.d.ts.map +1 -1
- package/dist/audit/orchestrator/intentInterpreter.js +30 -11
- package/dist/audit/orchestrator/intentInterpreter.js.map +1 -1
- package/dist/audit/orchestrator/intentScopeDisposition.d.ts +49 -0
- package/dist/audit/orchestrator/intentScopeDisposition.d.ts.map +1 -0
- package/dist/audit/orchestrator/intentScopeDisposition.js +57 -0
- package/dist/audit/orchestrator/intentScopeDisposition.js.map +1 -0
- package/dist/audit/orchestrator/rollingDispatch.d.ts +9 -0
- package/dist/audit/orchestrator/rollingDispatch.d.ts.map +1 -1
- package/dist/audit/orchestrator/rollingDispatch.js +10 -0
- package/dist/audit/orchestrator/rollingDispatch.js.map +1 -1
- package/dist/audit/orchestrator/scope.d.ts +1 -0
- package/dist/audit/orchestrator/scope.d.ts.map +1 -1
- package/dist/audit/orchestrator/scope.js +2 -7
- package/dist/audit/orchestrator/scope.js.map +1 -1
- package/dist/audit/quota/index.d.ts +5 -0
- package/dist/audit/quota/index.d.ts.map +1 -1
- package/dist/audit/reporting/scoreAudit.d.ts +161 -0
- package/dist/audit/reporting/scoreAudit.d.ts.map +1 -0
- package/dist/audit/reporting/scoreAudit.js +224 -0
- package/dist/audit/reporting/scoreAudit.js.map +1 -0
- package/dist/audit/types/activeDispatch.d.ts +29 -1
- package/dist/audit/types/activeDispatch.d.ts.map +1 -1
- package/dist/audit/types/activeDispatch.js.map +1 -1
- package/dist/audit/types/analyzerCapability.d.ts +6 -6
- package/dist/remediate/contractPipeline/changeClassification.d.ts +146 -0
- package/dist/remediate/contractPipeline/changeClassification.d.ts.map +1 -0
- package/dist/remediate/contractPipeline/changeClassification.js +398 -0
- package/dist/remediate/contractPipeline/changeClassification.js.map +1 -0
- package/dist/remediate/contractPipeline/derive.d.ts.map +1 -1
- package/dist/remediate/contractPipeline/derive.js +9 -0
- package/dist/remediate/contractPipeline/derive.js.map +1 -1
- package/dist/remediate/intent/intentOrdering.d.ts +51 -0
- package/dist/remediate/intent/intentOrdering.d.ts.map +1 -0
- package/dist/remediate/intent/intentOrdering.js +150 -0
- package/dist/remediate/intent/intentOrdering.js.map +1 -0
- package/dist/remediate/phases/plan.d.ts.map +1 -1
- package/dist/remediate/phases/plan.js +14 -1
- package/dist/remediate/phases/plan.js.map +1 -1
- package/dist/remediate/providers/index.d.ts +32 -0
- package/dist/remediate/providers/index.d.ts.map +1 -1
- package/dist/remediate/providers/index.js +28 -1
- package/dist/remediate/providers/index.js.map +1 -1
- package/dist/remediate/steps/contractPipeline.d.ts +15 -1
- package/dist/remediate/steps/contractPipeline.d.ts.map +1 -1
- package/dist/remediate/steps/contractPipeline.js +282 -14
- package/dist/remediate/steps/contractPipeline.js.map +1 -1
- package/dist/remediate/steps/dispatch.d.ts +75 -1
- package/dist/remediate/steps/dispatch.d.ts.map +1 -1
- package/dist/remediate/steps/dispatch.js +159 -43
- package/dist/remediate/steps/dispatch.js.map +1 -1
- package/dist/remediate/steps/nextStep.d.ts +53 -2
- package/dist/remediate/steps/nextStep.d.ts.map +1 -1
- package/dist/remediate/steps/nextStep.js +255 -81
- package/dist/remediate/steps/nextStep.js.map +1 -1
- package/dist/remediate/steps/providerNodeDispatch.d.ts +8 -1
- package/dist/remediate/steps/providerNodeDispatch.d.ts.map +1 -1
- package/dist/remediate/steps/providerNodeDispatch.js +7 -2
- package/dist/remediate/steps/providerNodeDispatch.js.map +1 -1
- package/dist/remediate/steps/rollingSession.d.ts +55 -1
- package/dist/remediate/steps/rollingSession.d.ts.map +1 -1
- package/dist/remediate/steps/rollingSession.js +132 -21
- package/dist/remediate/steps/rollingSession.js.map +1 -1
- package/dist/remediate/validation/contractPipelineGates.d.ts +23 -8
- package/dist/remediate/validation/contractPipelineGates.d.ts.map +1 -1
- package/dist/remediate/validation/contractPipelineGates.js +43 -38
- package/dist/remediate/validation/contractPipelineGates.js.map +1 -1
- package/dist/shared/dispatch/coordinator.d.ts +170 -0
- package/dist/shared/dispatch/coordinator.d.ts.map +1 -0
- package/dist/shared/dispatch/coordinator.js +177 -0
- package/dist/shared/dispatch/coordinator.js.map +1 -0
- package/dist/shared/dispatch/hybridDispatch.d.ts +74 -0
- package/dist/shared/dispatch/hybridDispatch.d.ts.map +1 -0
- package/dist/shared/dispatch/hybridDispatch.js +54 -0
- package/dist/shared/dispatch/hybridDispatch.js.map +1 -0
- package/dist/shared/dispatch/settledPools.d.ts +21 -0
- package/dist/shared/dispatch/settledPools.d.ts.map +1 -0
- package/dist/shared/dispatch/settledPools.js +34 -0
- package/dist/shared/dispatch/settledPools.js.map +1 -0
- package/dist/shared/index.d.ts +15 -5
- package/dist/shared/index.d.ts.map +1 -1
- package/dist/shared/index.js +14 -2
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/intent/clauseInterpreter.d.ts +19 -0
- package/dist/shared/intent/clauseInterpreter.d.ts.map +1 -1
- package/dist/shared/intent/clauseInterpreter.js +19 -0
- package/dist/shared/intent/clauseInterpreter.js.map +1 -1
- package/dist/shared/providers/sharedProviderConfirmation.d.ts +134 -0
- package/dist/shared/providers/sharedProviderConfirmation.d.ts.map +1 -0
- package/dist/shared/providers/sharedProviderConfirmation.js +244 -0
- package/dist/shared/providers/sharedProviderConfirmation.js.map +1 -0
- package/dist/shared/quota/apiPool.d.ts +109 -0
- package/dist/shared/quota/apiPool.d.ts.map +1 -0
- package/dist/shared/quota/apiPool.js +183 -0
- package/dist/shared/quota/apiPool.js.map +1 -0
- package/dist/shared/quota/capacity.d.ts +29 -1
- package/dist/shared/quota/capacity.d.ts.map +1 -1
- package/dist/shared/quota/capacity.js +5 -0
- package/dist/shared/quota/capacity.js.map +1 -1
- package/dist/shared/quota/claimRegistry.d.ts +64 -0
- package/dist/shared/quota/claimRegistry.d.ts.map +1 -0
- package/dist/shared/quota/claimRegistry.js +157 -0
- package/dist/shared/quota/claimRegistry.js.map +1 -0
- package/dist/shared/quota/compositeQuotaSource.d.ts +10 -1
- package/dist/shared/quota/compositeQuotaSource.d.ts.map +1 -1
- package/dist/shared/quota/compositeQuotaSource.js +34 -6
- package/dist/shared/quota/compositeQuotaSource.js.map +1 -1
- package/dist/shared/quota/fileLock.d.ts.map +1 -1
- package/dist/shared/quota/fileLock.js +7 -1
- package/dist/shared/quota/fileLock.js.map +1 -1
- package/dist/shared/quota/httpQuotaSource.d.ts +9 -1
- package/dist/shared/quota/httpQuotaSource.d.ts.map +1 -1
- package/dist/shared/quota/httpQuotaSource.js +33 -8
- package/dist/shared/quota/httpQuotaSource.js.map +1 -1
- package/dist/shared/quota/learnedQuotaSource.d.ts +7 -1
- package/dist/shared/quota/learnedQuotaSource.d.ts.map +1 -1
- package/dist/shared/quota/learnedQuotaSource.js +18 -7
- package/dist/shared/quota/learnedQuotaSource.js.map +1 -1
- package/dist/shared/quota/quotaSource.d.ts +41 -0
- package/dist/shared/quota/quotaSource.d.ts.map +1 -1
- package/dist/shared/quota/quotaSource.js +19 -0
- package/dist/shared/quota/quotaSource.js.map +1 -1
- package/dist/shared/types/contractPipeline/obligations.d.ts +42 -0
- package/dist/shared/types/contractPipeline/obligations.d.ts.map +1 -1
- package/dist/shared/types/contractPipeline.d.ts +1 -1
- package/dist/shared/types/contractPipeline.d.ts.map +1 -1
- package/dist/shared/types/contractPipeline.js.map +1 -1
- package/dist/shared/types/intentCheckpoint.d.ts +14 -0
- package/dist/shared/types/intentCheckpoint.d.ts.map +1 -1
- package/dist/shared/types/intentCheckpoint.js +10 -0
- package/dist/shared/types/intentCheckpoint.js.map +1 -1
- package/dist/shared/types/sessionConfig.d.ts +60 -0
- package/dist/shared/types/sessionConfig.d.ts.map +1 -1
- package/dist/shared/types/sessionConfig.js +13 -0
- package/dist/shared/types/sessionConfig.js.map +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { readFile, writeFile, mkdir } from "node:fs/promises";
|
|
2
|
+
import { dirname } from "node:path";
|
|
3
|
+
import { withFileLock, STALE_LOCK_MS } from "./fileLock.js";
|
|
4
|
+
function mintOwnerToken() {
|
|
5
|
+
return `${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
6
|
+
}
|
|
7
|
+
function isClaimRecord(value) {
|
|
8
|
+
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
9
|
+
return false;
|
|
10
|
+
const obj = value;
|
|
11
|
+
return (typeof obj.ownerToken === "string" &&
|
|
12
|
+
typeof obj.poolId === "string" &&
|
|
13
|
+
typeof obj.heartbeatAt === "number" &&
|
|
14
|
+
Number.isFinite(obj.heartbeatAt));
|
|
15
|
+
}
|
|
16
|
+
// Read the registry, degrading ANY malformed/absent state to an empty map. A
|
|
17
|
+
// corrupt registry must never throw into the dispatch loop — at worst a claim is
|
|
18
|
+
// re-granted, which the lock-serialized write then makes consistent again. Only
|
|
19
|
+
// well-formed individual records are retained; junk entries are dropped silently.
|
|
20
|
+
async function readClaimMap(registryPath) {
|
|
21
|
+
let raw;
|
|
22
|
+
try {
|
|
23
|
+
raw = await readFile(registryPath, "utf8");
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return {};
|
|
27
|
+
}
|
|
28
|
+
let parsed;
|
|
29
|
+
try {
|
|
30
|
+
parsed = JSON.parse(raw);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return {};
|
|
34
|
+
}
|
|
35
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed))
|
|
36
|
+
return {};
|
|
37
|
+
const out = {};
|
|
38
|
+
for (const [nodeId, record] of Object.entries(parsed)) {
|
|
39
|
+
if (isClaimRecord(record))
|
|
40
|
+
out[nodeId] = record;
|
|
41
|
+
}
|
|
42
|
+
return out;
|
|
43
|
+
}
|
|
44
|
+
async function writeClaimMap(registryPath, claims) {
|
|
45
|
+
await mkdir(dirname(registryPath), { recursive: true });
|
|
46
|
+
await writeFile(registryPath, `${JSON.stringify(claims, null, 2)}\n`, "utf8");
|
|
47
|
+
}
|
|
48
|
+
function isStale(record, now) {
|
|
49
|
+
return now - record.heartbeatAt > STALE_LOCK_MS;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* File-backed claim registry. The caller owns the path (and may point two
|
|
53
|
+
* coordinators at the same file — that is the whole point). Every mutating op
|
|
54
|
+
* runs its entire read-modify-write inside `withFileLock(registryPath + '.lock')`
|
|
55
|
+
* so concurrent loops are serialized and the single-grant invariant holds.
|
|
56
|
+
*/
|
|
57
|
+
export class ClaimRegistry {
|
|
58
|
+
registryPath;
|
|
59
|
+
now;
|
|
60
|
+
lockPath;
|
|
61
|
+
constructor(registryPath, now = () => Date.now()) {
|
|
62
|
+
this.registryPath = registryPath;
|
|
63
|
+
this.now = now;
|
|
64
|
+
this.lockPath = `${registryPath}.lock`;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Attempt to claim `nodeId` for `poolId`. Granted when the node is unclaimed or
|
|
68
|
+
* the existing claim is stale (heartbeat older than STALE_LOCK_MS). Returns the
|
|
69
|
+
* fresh ownerToken on success, or `{ acquired: false, heldBy }` carrying the
|
|
70
|
+
* live owner's token when another loop holds it.
|
|
71
|
+
*/
|
|
72
|
+
async claim(nodeId, poolId) {
|
|
73
|
+
return withFileLock(this.lockPath, async () => {
|
|
74
|
+
const claims = await readClaimMap(this.registryPath);
|
|
75
|
+
const now = this.now();
|
|
76
|
+
const existing = claims[nodeId];
|
|
77
|
+
if (existing && !isStale(existing, now)) {
|
|
78
|
+
return { acquired: false, heldBy: existing.ownerToken };
|
|
79
|
+
}
|
|
80
|
+
const ownerToken = mintOwnerToken();
|
|
81
|
+
claims[nodeId] = { ownerToken, poolId, heartbeatAt: now };
|
|
82
|
+
await writeClaimMap(this.registryPath, claims);
|
|
83
|
+
return { acquired: true, ownerToken };
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Refresh the heartbeat on a claim we still hold. Token-checked: a no-op if the
|
|
88
|
+
* node is unclaimed or held under a different token. Returns whether the
|
|
89
|
+
* heartbeat was applied. This is how a long-running owner stays "live" and so
|
|
90
|
+
* survives a concurrent `reclaimStale()`.
|
|
91
|
+
*/
|
|
92
|
+
async heartbeat(nodeId, ownerToken) {
|
|
93
|
+
return withFileLock(this.lockPath, async () => {
|
|
94
|
+
const claims = await readClaimMap(this.registryPath);
|
|
95
|
+
const existing = claims[nodeId];
|
|
96
|
+
if (!existing || existing.ownerToken !== ownerToken)
|
|
97
|
+
return false;
|
|
98
|
+
existing.heartbeatAt = this.now();
|
|
99
|
+
await writeClaimMap(this.registryPath, claims);
|
|
100
|
+
return true;
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Release a claim we hold. Token-checked: only the owner can release, so a
|
|
105
|
+
* stale-observation racer can never drop a claim another loop legitimately
|
|
106
|
+
* holds. Returns whether a claim was removed.
|
|
107
|
+
*/
|
|
108
|
+
async release(nodeId, ownerToken) {
|
|
109
|
+
return withFileLock(this.lockPath, async () => {
|
|
110
|
+
const claims = await readClaimMap(this.registryPath);
|
|
111
|
+
const existing = claims[nodeId];
|
|
112
|
+
if (!existing || existing.ownerToken !== ownerToken)
|
|
113
|
+
return false;
|
|
114
|
+
delete claims[nodeId];
|
|
115
|
+
await writeClaimMap(this.registryPath, claims);
|
|
116
|
+
return true;
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Reclaim every claim whose heartbeat is older than STALE_LOCK_MS, returning
|
|
121
|
+
* the freed nodeIds. A claim that was re-heartbeated since the staleness check
|
|
122
|
+
* is — by the same single-lock serialization — observed fresh here and left
|
|
123
|
+
* intact, so a live owner is never clobbered.
|
|
124
|
+
*/
|
|
125
|
+
async reclaimStale() {
|
|
126
|
+
return withFileLock(this.lockPath, async () => {
|
|
127
|
+
const claims = await readClaimMap(this.registryPath);
|
|
128
|
+
const now = this.now();
|
|
129
|
+
const reclaimed = [];
|
|
130
|
+
for (const [nodeId, record] of Object.entries(claims)) {
|
|
131
|
+
if (isStale(record, now)) {
|
|
132
|
+
delete claims[nodeId];
|
|
133
|
+
reclaimed.push(nodeId);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
if (reclaimed.length > 0)
|
|
137
|
+
await writeClaimMap(this.registryPath, claims);
|
|
138
|
+
return reclaimed;
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
/** Snapshot of all current claims, keyed by nodeId. Read under the lock. */
|
|
142
|
+
async listClaims() {
|
|
143
|
+
return withFileLock(this.lockPath, async () => readClaimMap(this.registryPath));
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Whether `nodeId` currently has a LIVE (non-stale) claim. A stale claim reads
|
|
147
|
+
* as not-claimed, since the next `claim()` would grant over it.
|
|
148
|
+
*/
|
|
149
|
+
async isClaimed(nodeId) {
|
|
150
|
+
return withFileLock(this.lockPath, async () => {
|
|
151
|
+
const claims = await readClaimMap(this.registryPath);
|
|
152
|
+
const existing = claims[nodeId];
|
|
153
|
+
return existing !== undefined && !isStale(existing, this.now());
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=claimRegistry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claimRegistry.js","sourceRoot":"","sources":["../../../src/shared/quota/claimRegistry.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { QuotaSource, QuotaUsageSnapshot } from "./quotaSource.js";
|
|
1
|
+
import type { QuotaProbeResult, QuotaSource, QuotaUsageSnapshot } from "./quotaSource.js";
|
|
2
2
|
import { RunLogger } from "../observability/runLog.js";
|
|
3
3
|
export interface BuildQuotaSourceOptions {
|
|
4
4
|
halfLifeHours?: number;
|
|
@@ -17,6 +17,15 @@ export declare class CompositeQuotaSource implements QuotaSource {
|
|
|
17
17
|
private runLogger;
|
|
18
18
|
constructor(sources: QuotaSource[], runLogger?: RunLogger);
|
|
19
19
|
queryCurrentUsage(providerModelKey: string): Promise<QuotaUsageSnapshot | null>;
|
|
20
|
+
/**
|
|
21
|
+
* Probe the cascade with an aggregate status: the first source that returns a
|
|
22
|
+
* snapshot wins (`ok`); otherwise the result is `degraded` when any source
|
|
23
|
+
* that handles this provider was queried and silently degraded (or threw), and
|
|
24
|
+
* `not_applicable` only when no source ever applied. This is what lets a pool
|
|
25
|
+
* record that a live quota reading was expected but lost, instead of treating
|
|
26
|
+
* every empty cascade as "no source configured".
|
|
27
|
+
*/
|
|
28
|
+
probeUsage(providerModelKey: string): Promise<QuotaProbeResult>;
|
|
20
29
|
}
|
|
21
30
|
/**
|
|
22
31
|
* Builds the standard runtime quota snapshot cascade.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compositeQuotaSource.d.ts","sourceRoot":"","sources":["../../../src/shared/quota/compositeQuotaSource.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"compositeQuotaSource.d.ts","sourceRoot":"","sources":["../../../src/shared/quota/compositeQuotaSource.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAO1F,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAEvD,MAAM,WAAW,uBAAuB;IACtC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iBAAiB,CAAC,EAAE,WAAW,EAAE,CAAC;IAClC,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB;;;;OAIG;IACH,WAAW,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC;CACnC;AAED,qBAAa,oBAAqB,YAAW,WAAW;IACtD,QAAQ,CAAC,IAAI,eAAe;IAC5B,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,SAAS,CAAY;gBAEjB,OAAO,EAAE,WAAW,EAAE,EAAE,SAAS,CAAC,EAAE,SAAS;IAKnD,iBAAiB,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAIrF;;;;;;;OAOG;IACG,UAAU,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;CAgCtE;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,uBAA4B,GAAG,WAAW,CAmBnF"}
|
|
@@ -14,15 +14,43 @@ export class CompositeQuotaSource {
|
|
|
14
14
|
this.runLogger = runLogger ?? RunLogger.disabled();
|
|
15
15
|
}
|
|
16
16
|
async queryCurrentUsage(providerModelKey) {
|
|
17
|
+
return (await this.probeUsage(providerModelKey)).snapshot;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Probe the cascade with an aggregate status: the first source that returns a
|
|
21
|
+
* snapshot wins (`ok`); otherwise the result is `degraded` when any source
|
|
22
|
+
* that handles this provider was queried and silently degraded (or threw), and
|
|
23
|
+
* `not_applicable` only when no source ever applied. This is what lets a pool
|
|
24
|
+
* record that a live quota reading was expected but lost, instead of treating
|
|
25
|
+
* every empty cascade as "no source configured".
|
|
26
|
+
*/
|
|
27
|
+
async probeUsage(providerModelKey) {
|
|
28
|
+
let sawDegraded = false;
|
|
17
29
|
for (const source of this.sources) {
|
|
18
30
|
try {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
31
|
+
// Invoke the source directly (not via the swallowing `probeQuotaSource`)
|
|
32
|
+
// so a throw propagates to the catch below, where it is BOTH logged and
|
|
33
|
+
// counted as a degrade — preserving the operator-visible failure event.
|
|
34
|
+
let result;
|
|
35
|
+
if (source.probeUsage) {
|
|
36
|
+
result = await source.probeUsage(providerModelKey);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
// A bare `queryCurrentUsage` source can't distinguish a silent degrade
|
|
40
|
+
// from a non-match, so a null result is `not_applicable`; a throw falls
|
|
41
|
+
// through to the catch and is recorded as a degrade there.
|
|
42
|
+
const snapshot = await source.queryCurrentUsage(providerModelKey);
|
|
43
|
+
result = { snapshot, status: snapshot ? "ok" : "not_applicable" };
|
|
44
|
+
}
|
|
45
|
+
if (result.snapshot)
|
|
46
|
+
return result;
|
|
47
|
+
if (result.status === "degraded")
|
|
48
|
+
sawDegraded = true;
|
|
22
49
|
}
|
|
23
50
|
catch (err) {
|
|
24
|
-
//
|
|
25
|
-
//
|
|
51
|
+
// A throw is a degrade for that source — surface it so operators can
|
|
52
|
+
// detect a persistently failing quota source, then try the next one.
|
|
53
|
+
sawDegraded = true;
|
|
26
54
|
this.runLogger.event({
|
|
27
55
|
kind: "error",
|
|
28
56
|
phase: "quota",
|
|
@@ -30,7 +58,7 @@ export class CompositeQuotaSource {
|
|
|
30
58
|
});
|
|
31
59
|
}
|
|
32
60
|
}
|
|
33
|
-
return null;
|
|
61
|
+
return { snapshot: null, status: sawDegraded ? "degraded" : "not_applicable" };
|
|
34
62
|
}
|
|
35
63
|
}
|
|
36
64
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compositeQuotaSource.js","sourceRoot":"","sources":["../../../src/shared/quota/compositeQuotaSource.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAcvD,MAAM,OAAO,oBAAoB;IACtB,IAAI,GAAG,WAAW,CAAC;IACpB,OAAO,CAAgB;IACvB,SAAS,CAAY;IAE7B,YAAY,OAAsB,EAAE,SAAqB;QACvD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,SAAS,GAAG,SAAS,IAAI,SAAS,CAAC,QAAQ,EAAE,CAAC;IACrD,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,gBAAwB;QAC9C,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAClC,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"compositeQuotaSource.js","sourceRoot":"","sources":["../../../src/shared/quota/compositeQuotaSource.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fileLock.d.ts","sourceRoot":"","sources":["../../../src/shared/quota/fileLock.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fileLock.d.ts","sourceRoot":"","sources":["../../../src/shared/quota/fileLock.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAE5D,eAAO,MAAM,aAAa,QAAS,CAAC;AASpC,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,QAAQ,EAAE,MAAM;CAI7B;AAkGD,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,MAAM,EAChB,SAAS,GAAE,MAA2B,EACtC,MAAM,CAAC,EAAE,SAAS,GACjB,OAAO,CAAC,MAAM,CAAC,CAyDjB;AAED,wBAAsB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAYrF;AAED,wBAAsB,YAAY,CAAC,CAAC,EAClC,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,SAAS,CAAC,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,SAAS,GACjB,OAAO,CAAC,CAAC,CAAC,CAkBZ"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { writeFile, unlink, stat, readFile } from "node:fs/promises";
|
|
1
|
+
import { writeFile, unlink, stat, readFile, mkdir } from "node:fs/promises";
|
|
2
|
+
import { dirname } from "node:path";
|
|
2
3
|
export const STALE_LOCK_MS = 30_000;
|
|
3
4
|
// Lock-acquire retry uses exponential backoff (initial → doubling → max) rather
|
|
4
5
|
// than a fixed poll, so a long contention window costs far fewer wakeups. The
|
|
@@ -116,6 +117,11 @@ export async function acquireLock(lockPath, timeoutMs = DEFAULT_TIMEOUT_MS, logg
|
|
|
116
117
|
const deadline = Date.now() + timeoutMs;
|
|
117
118
|
let lastStaleCheckAt = 0;
|
|
118
119
|
let retryInterval = RETRY_INTERVAL_INITIAL_MS;
|
|
120
|
+
// A lock cannot be created in a directory that does not exist — the `wx` create
|
|
121
|
+
// would ENOENT (not EEXIST), failing the whole acquisition. Ensure the parent dir
|
|
122
|
+
// exists so callers that lock a path before its run dir is materialized (e.g. the
|
|
123
|
+
// A-8 audit hybrid claiming before the review run is set up) just work. Idempotent.
|
|
124
|
+
await mkdir(dirname(lockPath), { recursive: true });
|
|
119
125
|
while (true) {
|
|
120
126
|
try {
|
|
121
127
|
await writeFile(lockPath, token, { flag: "wx" });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fileLock.js","sourceRoot":"","sources":["../../../src/shared/quota/fileLock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"fileLock.js","sourceRoot":"","sources":["../../../src/shared/quota/fileLock.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { QuotaSource, QuotaUsageSnapshot } from "./quotaSource.js";
|
|
1
|
+
import type { QuotaProbeResult, QuotaSource, QuotaUsageSnapshot } from "./quotaSource.js";
|
|
2
2
|
/**
|
|
3
3
|
* Shared scaffolding for PROACTIVE per-provider quota sources (Claude, Codex,
|
|
4
4
|
* Copilot, Antigravity, OpenCode-broker). Each subclass only supplies the
|
|
@@ -62,6 +62,14 @@ export declare abstract class BaseHttpQuotaSource implements QuotaSource {
|
|
|
62
62
|
*/
|
|
63
63
|
protected abstract fetchSnapshot(provider: string, model: string | null, nowMs: number): Promise<QuotaUsageSnapshot | null>;
|
|
64
64
|
queryCurrentUsage(providerModelKey: string): Promise<QuotaUsageSnapshot | null>;
|
|
65
|
+
/**
|
|
66
|
+
* Probe with an explicit status (see {@link QuotaProbeResult}). A non-matching
|
|
67
|
+
* provider key or a network-skipped probe is `not_applicable`; a real query
|
|
68
|
+
* that yields no snapshot (missing creds, 401/5xx, bad payload) is `degraded`
|
|
69
|
+
* — the silent-degrade signal a bare `null` from `queryCurrentUsage` hides.
|
|
70
|
+
* Both paths return through here so the cache and the status stay consistent.
|
|
71
|
+
*/
|
|
72
|
+
probeUsage(providerModelKey: string): Promise<QuotaProbeResult>;
|
|
65
73
|
/** Context for the reusable `fetchXxxUsage` helpers. */
|
|
66
74
|
protected fetchContext(): UsageFetchContext;
|
|
67
75
|
protected shouldSkipNetwork(): boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"httpQuotaSource.d.ts","sourceRoot":"","sources":["../../../src/shared/quota/httpQuotaSource.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"httpQuotaSource.d.ts","sourceRoot":"","sources":["../../../src/shared/quota/httpQuotaSource.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/** A handled provider with a snapshot is `ok`; attempted-but-empty is `degraded`. */
|
|
2
|
+
function classifyProbe(cached) {
|
|
3
|
+
if (cached.snapshot)
|
|
4
|
+
return "ok";
|
|
5
|
+
return cached.attempted ? "degraded" : "not_applicable";
|
|
6
|
+
}
|
|
1
7
|
const DEFAULT_CACHE_TTL_MS = 45_000;
|
|
2
8
|
export class BaseHttpQuotaSource {
|
|
3
9
|
fetchImpl;
|
|
@@ -14,19 +20,38 @@ export class BaseHttpQuotaSource {
|
|
|
14
20
|
this.userAgent = options.userAgent ?? defaultUserAgent;
|
|
15
21
|
}
|
|
16
22
|
async queryCurrentUsage(providerModelKey) {
|
|
23
|
+
return (await this.probeUsage(providerModelKey)).snapshot;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Probe with an explicit status (see {@link QuotaProbeResult}). A non-matching
|
|
27
|
+
* provider key or a network-skipped probe is `not_applicable`; a real query
|
|
28
|
+
* that yields no snapshot (missing creds, 401/5xx, bad payload) is `degraded`
|
|
29
|
+
* — the silent-degrade signal a bare `null` from `queryCurrentUsage` hides.
|
|
30
|
+
* Both paths return through here so the cache and the status stay consistent.
|
|
31
|
+
*/
|
|
32
|
+
async probeUsage(providerModelKey) {
|
|
17
33
|
const { provider, model } = parseProviderModelKey(providerModelKey);
|
|
18
|
-
|
|
19
|
-
|
|
34
|
+
// Gated out for this provider — no I/O, and no signal was ever expected.
|
|
35
|
+
if (!this.handlesProvider(provider)) {
|
|
36
|
+
return { snapshot: null, status: "not_applicable" };
|
|
37
|
+
}
|
|
20
38
|
const nowMs = this.now();
|
|
21
39
|
const cached = this.cache.get(providerModelKey);
|
|
22
40
|
if (cached && nowMs - cached.fetchedAtMs < this.cacheTtlMs) {
|
|
23
|
-
return cached.snapshot;
|
|
41
|
+
return { snapshot: cached.snapshot, status: classifyProbe(cached) };
|
|
42
|
+
}
|
|
43
|
+
// The live probe was intentionally skipped (hermeticity / disabled) — absent
|
|
44
|
+
// by design, not a degrade.
|
|
45
|
+
if (this.shouldSkipNetwork()) {
|
|
46
|
+
const result = { fetchedAtMs: nowMs, snapshot: null, attempted: false };
|
|
47
|
+
this.cache.set(providerModelKey, result);
|
|
48
|
+
return { snapshot: null, status: "not_applicable" };
|
|
24
49
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
this.cache.set(providerModelKey,
|
|
29
|
-
return snapshot;
|
|
50
|
+
// A real query for a handled provider: a null result is a silent degrade.
|
|
51
|
+
const snapshot = await this.fetchSnapshot(provider, model, nowMs);
|
|
52
|
+
const result = { fetchedAtMs: nowMs, snapshot, attempted: true };
|
|
53
|
+
this.cache.set(providerModelKey, result);
|
|
54
|
+
return { snapshot, status: classifyProbe(result) };
|
|
30
55
|
}
|
|
31
56
|
/** Context for the reusable `fetchXxxUsage` helpers. */
|
|
32
57
|
fetchContext() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"httpQuotaSource.js","sourceRoot":"","sources":["../../../src/shared/quota/httpQuotaSource.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"httpQuotaSource.js","sourceRoot":"","sources":["../../../src/shared/quota/httpQuotaSource.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
import type { QuotaSource, QuotaUsageSnapshot } from "./quotaSource.js";
|
|
1
|
+
import type { QuotaProbeResult, QuotaSource, QuotaUsageSnapshot } from "./quotaSource.js";
|
|
2
2
|
export declare class LearnedQuotaSource implements QuotaSource {
|
|
3
3
|
readonly name = "learned";
|
|
4
4
|
private halfLifeHours;
|
|
5
5
|
constructor(halfLifeHours?: number);
|
|
6
6
|
queryCurrentUsage(providerModelKey: string): Promise<QuotaUsageSnapshot | null>;
|
|
7
|
+
/**
|
|
8
|
+
* No learned entry yet is `not_applicable`, never `degraded`: the learned
|
|
9
|
+
* source is the reactive fallback, so the absence of history is the normal
|
|
10
|
+
* cold-start state, not a lost signal.
|
|
11
|
+
*/
|
|
12
|
+
probeUsage(providerModelKey: string): Promise<QuotaProbeResult>;
|
|
7
13
|
}
|
|
8
14
|
//# sourceMappingURL=learnedQuotaSource.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"learnedQuotaSource.d.ts","sourceRoot":"","sources":["../../../src/shared/quota/learnedQuotaSource.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"learnedQuotaSource.d.ts","sourceRoot":"","sources":["../../../src/shared/quota/learnedQuotaSource.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAG1F,qBAAa,kBAAmB,YAAW,WAAW;IACpD,QAAQ,CAAC,IAAI,aAAa;IAE1B,OAAO,CAAC,aAAa,CAAS;gBAElB,aAAa,SAAK;IAIxB,iBAAiB,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAIrF;;;;OAIG;IACG,UAAU,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;CAsBtE"}
|
|
@@ -6,20 +6,31 @@ export class LearnedQuotaSource {
|
|
|
6
6
|
this.halfLifeHours = halfLifeHours;
|
|
7
7
|
}
|
|
8
8
|
async queryCurrentUsage(providerModelKey) {
|
|
9
|
+
return (await this.probeUsage(providerModelKey)).snapshot;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* No learned entry yet is `not_applicable`, never `degraded`: the learned
|
|
13
|
+
* source is the reactive fallback, so the absence of history is the normal
|
|
14
|
+
* cold-start state, not a lost signal.
|
|
15
|
+
*/
|
|
16
|
+
async probeUsage(providerModelKey) {
|
|
9
17
|
const state = await readQuotaState();
|
|
10
18
|
const entry = state.entries[providerModelKey];
|
|
11
19
|
if (!entry)
|
|
12
|
-
return null;
|
|
20
|
+
return { snapshot: null, status: "not_applicable" };
|
|
13
21
|
const maxSafe = computeMaxSafeConcurrency(entry, this.halfLifeHours);
|
|
14
22
|
const isInCooldown = entry.cooldown_until != null &&
|
|
15
23
|
new Date(entry.cooldown_until).getTime() > Date.now();
|
|
16
24
|
return {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
25
|
+
snapshot: {
|
|
26
|
+
remaining_pct: isInCooldown ? 0 : null,
|
|
27
|
+
reset_at: isInCooldown ? entry.cooldown_until : null,
|
|
28
|
+
requests_remaining: maxSafe,
|
|
29
|
+
tokens_remaining: null,
|
|
30
|
+
captured_at: entry.updated_at,
|
|
31
|
+
source: "learned",
|
|
32
|
+
},
|
|
33
|
+
status: "ok",
|
|
23
34
|
};
|
|
24
35
|
}
|
|
25
36
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"learnedQuotaSource.js","sourceRoot":"","sources":["../../../src/shared/quota/learnedQuotaSource.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAEvE,MAAM,OAAO,kBAAkB;IACpB,IAAI,GAAG,SAAS,CAAC;IAElB,aAAa,CAAS;IAE9B,YAAY,aAAa,GAAG,EAAE;QAC5B,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;IACrC,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,gBAAwB;QAC9C,MAAM,KAAK,GAAG,MAAM,cAAc,EAAE,CAAC;QACrC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;QAC9C,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"learnedQuotaSource.js","sourceRoot":"","sources":["../../../src/shared/quota/learnedQuotaSource.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAEvE,MAAM,OAAO,kBAAkB;IACpB,IAAI,GAAG,SAAS,CAAC;IAElB,aAAa,CAAS;IAE9B,YAAY,aAAa,GAAG,EAAE;QAC5B,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;IACrC,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,gBAAwB;QAC9C,OAAO,CAAC,MAAM,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC;IAC5D,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,UAAU,CAAC,gBAAwB;QACvC,MAAM,KAAK,GAAG,MAAM,cAAc,EAAE,CAAC;QACrC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;QAC9C,IAAI,CAAC,KAAK;YAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;QAEhE,MAAM,OAAO,GAAG,yBAAyB,CAAC,KAAK,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QACrE,MAAM,YAAY,GAChB,KAAK,CAAC,cAAc,IAAI,IAAI;YAC5B,IAAI,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAExD,OAAO;YACL,QAAQ,EAAE;gBACR,aAAa,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI;gBACtC,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI;gBACpD,kBAAkB,EAAE,OAAO;gBAC3B,gBAAgB,EAAE,IAAI;gBACtB,WAAW,EAAE,KAAK,CAAC,UAAU;gBAC7B,MAAM,EAAE,SAAS;aAClB;YACD,MAAM,EAAE,IAAI;SACb,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -22,8 +22,49 @@ export declare const QuotaUsageSnapshotSchema: z.ZodObject<{
|
|
|
22
22
|
source: string;
|
|
23
23
|
}>;
|
|
24
24
|
export type QuotaUsageSnapshot = z.infer<typeof QuotaUsageSnapshotSchema>;
|
|
25
|
+
/**
|
|
26
|
+
* Outcome of probing a quota source for one provider/model key, disambiguating
|
|
27
|
+
* the two cases a bare `null` snapshot conflates:
|
|
28
|
+
*
|
|
29
|
+
* - `ok` — a live snapshot was mapped (`snapshot` is non-null).
|
|
30
|
+
* - `degraded` — the source HANDLES this provider and was actually queried,
|
|
31
|
+
* but produced no snapshot (missing/expired creds, 401/5xx,
|
|
32
|
+
* network error, or an unmappable payload). The signal that was
|
|
33
|
+
* *expected* was silently lost — the operator-visible failure
|
|
34
|
+
* mode that `queryCurrentUsage`'s `null` hides.
|
|
35
|
+
* - `not_applicable` — the source does not answer for this provider (gated out
|
|
36
|
+
* with no I/O), or the live probe was intentionally skipped
|
|
37
|
+
* (hermeticity guard / proactive-quota disabled). No signal was
|
|
38
|
+
* ever expected, so its absence is not a degrade.
|
|
39
|
+
*
|
|
40
|
+
* This is the contract behind the `CapacityPool.quotaSignalDegraded` marker: a
|
|
41
|
+
* pool whose probe is `degraded` is dispatching blind where it expected a live
|
|
42
|
+
* quota reading, and that fact is attached to the pool rather than swallowed.
|
|
43
|
+
*/
|
|
44
|
+
export type QuotaProbeStatus = "ok" | "degraded" | "not_applicable";
|
|
45
|
+
export interface QuotaProbeResult {
|
|
46
|
+
snapshot: QuotaUsageSnapshot | null;
|
|
47
|
+
status: QuotaProbeStatus;
|
|
48
|
+
}
|
|
25
49
|
export interface QuotaSource {
|
|
26
50
|
readonly name: string;
|
|
27
51
|
queryCurrentUsage(providerModelKey: string): Promise<QuotaUsageSnapshot | null>;
|
|
52
|
+
/**
|
|
53
|
+
* Like {@link queryCurrentUsage}, but reports WHY the snapshot is null: a
|
|
54
|
+
* source that was queried and silently degraded (`degraded`) vs. one that
|
|
55
|
+
* never applied (`not_applicable`). Optional on the interface so plain
|
|
56
|
+
* `{ name, queryCurrentUsage }` stubs remain valid; {@link probeQuotaSource}
|
|
57
|
+
* derives a best-effort result for sources that don't implement it.
|
|
58
|
+
*/
|
|
59
|
+
probeUsage?(providerModelKey: string): Promise<QuotaProbeResult>;
|
|
28
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Probe a quota source, using its native {@link QuotaSource.probeUsage} when it
|
|
63
|
+
* has one and otherwise deriving a conservative result from
|
|
64
|
+
* {@link QuotaSource.queryCurrentUsage}: a snapshot is `ok`, a thrown error is
|
|
65
|
+
* `degraded` (it was attempted and failed), and a plain `null` is reported as
|
|
66
|
+
* `not_applicable` (a source without `probeUsage` cannot distinguish a silent
|
|
67
|
+
* degrade from a non-match, so it must not over-report a degrade).
|
|
68
|
+
*/
|
|
69
|
+
export declare function probeQuotaSource(source: QuotaSource, providerModelKey: string): Promise<QuotaProbeResult>;
|
|
29
70
|
//# sourceMappingURL=quotaSource.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"quotaSource.d.ts","sourceRoot":"","sources":["../../../src/shared/quota/quotaSource.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;EAS1B,CAAC;AACZ,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"quotaSource.d.ts","sourceRoot":"","sources":["../../../src/shared/quota/quotaSource.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;EAS1B,CAAC;AACZ,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,MAAM,gBAAgB,GAAG,IAAI,GAAG,UAAU,GAAG,gBAAgB,CAAC;AAEpE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACpC,MAAM,EAAE,gBAAgB,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAC;IAChF;;;;;;OAMG;IACH,UAAU,CAAC,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;CAClE;AAED;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,WAAW,EACnB,gBAAgB,EAAE,MAAM,GACvB,OAAO,CAAC,gBAAgB,CAAC,CAQ3B"}
|
|
@@ -9,4 +9,23 @@ export const QuotaUsageSnapshotSchema = z
|
|
|
9
9
|
source: z.string(),
|
|
10
10
|
})
|
|
11
11
|
.strict();
|
|
12
|
+
/**
|
|
13
|
+
* Probe a quota source, using its native {@link QuotaSource.probeUsage} when it
|
|
14
|
+
* has one and otherwise deriving a conservative result from
|
|
15
|
+
* {@link QuotaSource.queryCurrentUsage}: a snapshot is `ok`, a thrown error is
|
|
16
|
+
* `degraded` (it was attempted and failed), and a plain `null` is reported as
|
|
17
|
+
* `not_applicable` (a source without `probeUsage` cannot distinguish a silent
|
|
18
|
+
* degrade from a non-match, so it must not over-report a degrade).
|
|
19
|
+
*/
|
|
20
|
+
export async function probeQuotaSource(source, providerModelKey) {
|
|
21
|
+
if (source.probeUsage)
|
|
22
|
+
return source.probeUsage(providerModelKey);
|
|
23
|
+
try {
|
|
24
|
+
const snapshot = await source.queryCurrentUsage(providerModelKey);
|
|
25
|
+
return { snapshot, status: snapshot ? "ok" : "not_applicable" };
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return { snapshot: null, status: "degraded" };
|
|
29
|
+
}
|
|
30
|
+
}
|
|
12
31
|
//# sourceMappingURL=quotaSource.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"quotaSource.js","sourceRoot":"","sources":["../../../src/shared/quota/quotaSource.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC;KACtC,MAAM,CAAC;IACN,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACpC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC/B,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IAC/C,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IAC7C,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;CACnB,CAAC;KACD,MAAM,EAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"quotaSource.js","sourceRoot":"","sources":["../../../src/shared/quota/quotaSource.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC;KACtC,MAAM,CAAC;IACN,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACpC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC/B,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IAC/C,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IAC7C,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;CACnB,CAAC;KACD,MAAM,EAAE,CAAC;AA0CZ;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,MAAmB,EACnB,gBAAwB;IAExB,IAAI,MAAM,CAAC,UAAU;QAAE,OAAO,MAAM,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC;IAClE,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;QAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,gBAAgB,EAAE,CAAC;IAClE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IAChD,CAAC;AACH,CAAC"}
|