@claudexor/budget 1.0.1 → 2.1.1
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/README.md +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/ledger.d.ts +58 -42
- package/dist/ledger.d.ts.map +1 -1
- package/dist/ledger.js +266 -140
- package/dist/ledger.js.map +1 -1
- package/dist/metrics.d.ts +15 -1
- package/dist/metrics.d.ts.map +1 -1
- package/dist/metrics.js +27 -5
- package/dist/metrics.js.map +1 -1
- package/dist/observe.d.ts.map +1 -1
- package/dist/observe.js +31 -11
- package/dist/observe.js.map +1 -1
- package/dist/router.d.ts +20 -12
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +51 -43
- package/dist/router.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @claudexor/budget
|
|
2
2
|
|
|
3
|
-
Internal package of [Claudexor](https://github.com/razzant/claudexor) — Budget governor: pre-call lease reservation, loop detection, 3-tier circuit breaker,
|
|
3
|
+
Internal package of [Claudexor](https://github.com/razzant/claudexor) — Budget governor: pre-call lease reservation, loop detection, 3-tier circuit breaker, routing goals, observed quota.
|
|
4
4
|
|
|
5
5
|
Published as part of the Claudexor toolchain; it follows the monorepo's
|
|
6
6
|
lockstep version and has no separate semver contract. Use the `claudexor`
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export * from "./ledger.js";
|
|
2
2
|
export * from "./router.js";
|
|
3
3
|
export * from "./observe.js";
|
|
4
|
-
export { loadHarnessMetrics, recordHarnessMetric, metricsPath, type HarnessMetric, type HarnessMetrics } from "./metrics.js";
|
|
4
|
+
export { loadHarnessMetrics, recordHarnessMetric, metricsPath, type HarnessMetric, type HarnessMetrics, } from "./metrics.js";
|
|
5
5
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,WAAW,EACX,KAAK,aAAa,EAClB,KAAK,cAAc,GACpB,MAAM,cAAc,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export * from "./ledger.js";
|
|
2
2
|
export * from "./router.js";
|
|
3
3
|
export * from "./observe.js";
|
|
4
|
-
export { loadHarnessMetrics, recordHarnessMetric, metricsPath } from "./metrics.js";
|
|
4
|
+
export { loadHarnessMetrics, recordHarnessMetric, metricsPath, } from "./metrics.js";
|
|
5
5
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,WAAW,GAGZ,MAAM,cAAc,CAAC"}
|
package/dist/ledger.d.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import type { BudgetLease, BudgetObservation, Intent } from "@claudexor/schema";
|
|
1
|
+
import type { BillingKnowledge, BudgetLease, BudgetObservation, CostEvidence, CostKnowledge, CredentialRoute, Intent, PaidBudget, QuotaSnapshot } from "@claudexor/schema";
|
|
2
2
|
export type CircuitTier = "ok" | "soft" | "downgrade" | "hard";
|
|
3
|
-
export
|
|
4
|
-
maxUsd?: number | null;
|
|
5
|
-
}
|
|
3
|
+
export type BudgetTerminal = "exhausted" | "exhausted_overshoot" | "cost_unverifiable" | null;
|
|
6
4
|
export interface CircuitThresholds {
|
|
7
5
|
soft: number;
|
|
8
6
|
downgrade: number;
|
|
@@ -14,69 +12,87 @@ export interface ReserveInput {
|
|
|
14
12
|
intent: Intent;
|
|
15
13
|
harnessId: string;
|
|
16
14
|
modelHint?: string | null;
|
|
17
|
-
maxUsd?: number | null;
|
|
18
15
|
reason?: string[];
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
16
|
+
cost?: CostEvidence;
|
|
17
|
+
}
|
|
18
|
+
export interface BudgetSettlement {
|
|
19
|
+
knowledge: CostKnowledge;
|
|
20
|
+
source: string;
|
|
21
|
+
provenance: string[];
|
|
22
|
+
cashUsd?: number;
|
|
23
|
+
valuationUsd?: number;
|
|
25
24
|
}
|
|
26
25
|
export interface ReserveResult {
|
|
27
26
|
granted: boolean;
|
|
28
27
|
tier: CircuitTier;
|
|
29
28
|
lease?: BudgetLease;
|
|
30
29
|
reason?: string;
|
|
31
|
-
|
|
32
|
-
* breaker already tripped; `estimate_headroom` = the DD-27 wave guard —
|
|
33
|
-
* this slot's estimate does not fit, but already-granted work continues. */
|
|
34
|
-
denied?: "hard_cap" | "estimate_headroom";
|
|
30
|
+
denied?: "hard_cap" | "estimate_headroom" | "finite_zero" | "unknown_paid_in_flight";
|
|
35
31
|
}
|
|
36
32
|
/** Stable fingerprint of a prompt for loop detection. */
|
|
37
33
|
export declare function promptFingerprint(prompt: string): string;
|
|
38
|
-
/**
|
|
39
|
-
* Dollar-based budget ledger with pre-call reservation, prompt-fingerprint loop
|
|
40
|
-
* detection, and a 3-tier circuit breaker (soft-warn -> downgrade -> hard-kill).
|
|
41
|
-
* Sub-ledgers (children) roll their spend up to the parent.
|
|
42
|
-
*/
|
|
34
|
+
/** One root incremental-cash ledger. Nested work receives this same instance. */
|
|
43
35
|
export declare class BudgetLedger {
|
|
44
|
-
private readonly
|
|
36
|
+
private readonly budget;
|
|
45
37
|
private readonly thresholds;
|
|
46
|
-
private readonly
|
|
38
|
+
private readonly deps;
|
|
47
39
|
private readonly leases;
|
|
48
|
-
/** Outstanding USD holds for reserved-but-unsettled leases (amount-bearing). */
|
|
49
40
|
private readonly holds;
|
|
41
|
+
private readonly unknownPaidInFlight;
|
|
50
42
|
private readonly observations;
|
|
43
|
+
private readonly quotaSnapshots;
|
|
51
44
|
private readonly promptCounts;
|
|
52
45
|
private spendUsd;
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
46
|
+
private valuationUsd;
|
|
47
|
+
private overshot;
|
|
48
|
+
private unverifiable;
|
|
49
|
+
constructor(budget?: PaidBudget, thresholds?: CircuitThresholds, deps?: {
|
|
50
|
+
/**
|
|
51
|
+
* Fires after every settle with the CUMULATIVE ledger truth. The ledger
|
|
52
|
+
* is the one owner of "how much real money this run has spent" —
|
|
53
|
+
* subscription-entitled work settles to cash 0 here (W4.3 sol #15), so
|
|
54
|
+
* consumers (run events → UI) render cash without inferring from route
|
|
55
|
+
* labels. Valuation rides along for telemetry, never for the cash fact.
|
|
56
|
+
*/
|
|
57
|
+
onCashSettled?: (cashSpendUsd: number, valuationUsd: number) => void;
|
|
58
|
+
});
|
|
56
59
|
private outstandingHolds;
|
|
60
|
+
private cap;
|
|
57
61
|
tier(): CircuitTier;
|
|
58
|
-
|
|
59
|
-
private remainingHeadroomUsd;
|
|
62
|
+
remainingUsd(): number | null;
|
|
60
63
|
reserve(input: ReserveInput): ReserveResult;
|
|
61
|
-
/**
|
|
62
|
-
* Raise a lease's hold to the cost streamed so far (never lowers it). Call from
|
|
63
|
-
* the usage-event stream so `tier()` reflects in-flight spend mid-attempt.
|
|
64
|
-
*/
|
|
65
64
|
updateHold(leaseId: string, streamedUsd: number): void;
|
|
66
|
-
|
|
67
|
-
private adjustRollupHold;
|
|
68
|
-
private clearHold;
|
|
69
|
-
settle(leaseId: string, actualUsd: number): void;
|
|
65
|
+
settle(leaseId: string, settlement: BudgetSettlement): void;
|
|
70
66
|
cancel(leaseId: string): void;
|
|
71
|
-
private addRollupSpend;
|
|
72
67
|
spend(): number;
|
|
73
|
-
|
|
68
|
+
valuation(): number;
|
|
69
|
+
terminal(): BudgetTerminal;
|
|
70
|
+
observe(observation: BudgetObservation): void;
|
|
71
|
+
/** Seed durable quota projection without collapsing credential identities. */
|
|
72
|
+
observeQuotaSnapshot(snapshot: QuotaSnapshot): void;
|
|
74
73
|
observationsFor(harnessId: string): BudgetObservation[];
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
74
|
+
cooldownActive(harnessId: string, credentialRoute?: CredentialRoute, credentialSubjectId?: string | null, now?: number): boolean;
|
|
75
|
+
/** Binding pacing slack across applicable windows; null means honestly unknown. */
|
|
76
|
+
bindingPaceSlack(harnessId: string, credentialRoute?: CredentialRoute, credentialSubjectId?: string | null, now?: number): number | null;
|
|
77
|
+
/** Fresh snapshots for a harness+route, optionally pinned to ONE credential
|
|
78
|
+
* subject (release wave round-16 #2): when the caller knows the effective
|
|
79
|
+
* subject — a profile id, or null for the engine default — only that
|
|
80
|
+
* subject's windows apply, so profile A's exhaustion never cools profile B
|
|
81
|
+
* or the default. `undefined` = subject unknown, conservative any-subject. */
|
|
82
|
+
private snapshotsFor;
|
|
79
83
|
recordPrompt(fingerprint: string): number;
|
|
80
84
|
isLoop(fingerprint: string, threshold?: number): boolean;
|
|
81
85
|
}
|
|
86
|
+
export declare function routeCostEvidence(input: {
|
|
87
|
+
billing?: BillingKnowledge;
|
|
88
|
+
knowledge?: CostKnowledge;
|
|
89
|
+
source: string;
|
|
90
|
+
provenance: string[];
|
|
91
|
+
estimatedUsd?: number | null;
|
|
92
|
+
}): CostEvidence;
|
|
93
|
+
export declare function attemptCostEvidence(harnessId: string, attemptId: string, estimatedUsd?: number, billing?: BillingKnowledge): CostEvidence;
|
|
94
|
+
export declare function usageCostSettlement(cashUsd: number, estimated: boolean, source: string, provenance: string[]): BudgetSettlement;
|
|
95
|
+
export declare function attemptUsageCostSettlement(cashUsd: number, estimated: boolean, attemptId: string, harnessId: string, authMode?: "local_session" | "api_key" | null): BudgetSettlement;
|
|
96
|
+
export declare function unknownCostSettlement(source: string, cashUsd?: number): BudgetSettlement;
|
|
97
|
+
export declare function isBudgetTerminal(status: string | null): status is Exclude<BudgetTerminal, null>;
|
|
82
98
|
//# sourceMappingURL=ledger.d.ts.map
|
package/dist/ledger.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ledger.d.ts","sourceRoot":"","sources":["../src/ledger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"ledger.d.ts","sourceRoot":"","sources":["../src/ledger.ts"],"names":[],"mappings":"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"}
|
package/dist/ledger.js
CHANGED
|
@@ -1,91 +1,99 @@
|
|
|
1
|
-
import { BudgetLease as BudgetLeaseSchema } from "@claudexor/schema";
|
|
1
|
+
import { BudgetLease as BudgetLeaseSchema, CostEvidence as CostEvidenceSchema, } from "@claudexor/schema";
|
|
2
2
|
import { newId, nowIso, sha256 } from "@claudexor/util";
|
|
3
|
+
const UNKNOWN_COST = {
|
|
4
|
+
knowledge: "unknown",
|
|
5
|
+
billing: "unknown",
|
|
6
|
+
source: "route_preflight",
|
|
7
|
+
provenance: ["route:billing-unknown"],
|
|
8
|
+
estimatedUsd: null,
|
|
9
|
+
};
|
|
3
10
|
/** Stable fingerprint of a prompt for loop detection. */
|
|
4
11
|
export function promptFingerprint(prompt) {
|
|
5
12
|
return sha256(prompt.trim().replace(/\s+/g, " ").toLowerCase());
|
|
6
13
|
}
|
|
7
|
-
/**
|
|
8
|
-
* Dollar-based budget ledger with pre-call reservation, prompt-fingerprint loop
|
|
9
|
-
* detection, and a 3-tier circuit breaker (soft-warn -> downgrade -> hard-kill).
|
|
10
|
-
* Sub-ledgers (children) roll their spend up to the parent.
|
|
11
|
-
*/
|
|
14
|
+
/** One root incremental-cash ledger. Nested work receives this same instance. */
|
|
12
15
|
export class BudgetLedger {
|
|
13
|
-
|
|
16
|
+
budget;
|
|
14
17
|
thresholds;
|
|
15
|
-
|
|
18
|
+
deps;
|
|
16
19
|
leases = new Map();
|
|
17
|
-
/** Outstanding USD holds for reserved-but-unsettled leases (amount-bearing). */
|
|
18
20
|
holds = new Map();
|
|
21
|
+
unknownPaidInFlight = new Set();
|
|
19
22
|
observations = [];
|
|
23
|
+
quotaSnapshots = new Map();
|
|
20
24
|
promptCounts = new Map();
|
|
21
25
|
spendUsd = 0;
|
|
22
|
-
|
|
23
|
-
|
|
26
|
+
valuationUsd = 0;
|
|
27
|
+
overshot = false;
|
|
28
|
+
unverifiable = false;
|
|
29
|
+
constructor(budget = { kind: "unlimited" }, thresholds = { soft: 0.75, downgrade: 0.9, hard: 1 }, deps = {}) {
|
|
30
|
+
this.budget = budget;
|
|
24
31
|
this.thresholds = thresholds;
|
|
25
|
-
this.
|
|
26
|
-
}
|
|
27
|
-
/** Create a child sub-ledger whose spend rolls up to this one. */
|
|
28
|
-
child(limits = {}) {
|
|
29
|
-
return new BudgetLedger(limits, this.thresholds, this);
|
|
32
|
+
this.deps = deps;
|
|
30
33
|
}
|
|
31
34
|
outstandingHolds() {
|
|
32
35
|
let sum = 0;
|
|
33
|
-
for (const
|
|
34
|
-
sum +=
|
|
36
|
+
for (const value of this.holds.values())
|
|
37
|
+
sum += value;
|
|
35
38
|
return sum;
|
|
36
39
|
}
|
|
40
|
+
cap() {
|
|
41
|
+
return this.budget.kind === "finite" ? this.budget.maxUsd : null;
|
|
42
|
+
}
|
|
37
43
|
tier() {
|
|
38
|
-
const cap = this.
|
|
39
|
-
|
|
40
|
-
if (cap === null || cap <= 0)
|
|
41
|
-
return "ok";
|
|
42
|
-
// Settled spend + outstanding in-flight holds: a parallel wave of
|
|
43
|
-
// streaming candidates counts against the cap BEFORE settlement.
|
|
44
|
-
const ratio = (this.spendUsd + this.outstandingHolds()) / cap;
|
|
45
|
-
if (ratio >= this.thresholds.hard)
|
|
46
|
-
return "hard";
|
|
47
|
-
if (ratio >= this.thresholds.downgrade)
|
|
48
|
-
return "downgrade";
|
|
49
|
-
if (ratio >= this.thresholds.soft)
|
|
50
|
-
return "soft";
|
|
44
|
+
const cap = this.cap();
|
|
45
|
+
if (cap === null)
|
|
51
46
|
return "ok";
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
if (
|
|
62
|
-
return
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
47
|
+
if (this.overshot)
|
|
48
|
+
return "hard";
|
|
49
|
+
if (cap === 0)
|
|
50
|
+
return this.spendUsd > 0 || this.outstandingHolds() > 0 ? "hard" : "ok";
|
|
51
|
+
const ratio = (this.spendUsd + this.outstandingHolds()) / cap;
|
|
52
|
+
if (ratio >= this.thresholds.hard)
|
|
53
|
+
return "hard";
|
|
54
|
+
if (ratio >= this.thresholds.downgrade)
|
|
55
|
+
return "downgrade";
|
|
56
|
+
if (ratio >= this.thresholds.soft)
|
|
57
|
+
return "soft";
|
|
58
|
+
return "ok";
|
|
59
|
+
}
|
|
60
|
+
remainingUsd() {
|
|
61
|
+
const cap = this.cap();
|
|
62
|
+
return cap === null ? null : Math.max(0, cap - this.spendUsd - this.outstandingHolds());
|
|
66
63
|
}
|
|
67
64
|
reserve(input) {
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
65
|
+
const cost = CostEvidenceSchema.parse(input.cost ?? UNKNOWN_COST);
|
|
66
|
+
const zeroCash = cost.billing === "proven_zero" || cost.billing === "subscription_entitlement";
|
|
67
|
+
const cap = this.cap();
|
|
68
|
+
if (cap === 0 && !zeroCash) {
|
|
69
|
+
return {
|
|
70
|
+
granted: false,
|
|
71
|
+
tier: "hard",
|
|
72
|
+
denied: "finite_zero",
|
|
73
|
+
reason: "finite(0) admits only proven-zero or subscription-entitlement work",
|
|
74
|
+
};
|
|
71
75
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
76
|
+
if (this.tier() === "hard" && !zeroCash) {
|
|
77
|
+
return { granted: false, tier: "hard", denied: "hard_cap", reason: "budget exhausted" };
|
|
78
|
+
}
|
|
79
|
+
const unknownPaid = !zeroCash && cost.knowledge === "unknown";
|
|
80
|
+
if (cap !== null && cap > 0 && unknownPaid && this.unknownPaidInFlight.size > 0) {
|
|
81
|
+
return {
|
|
82
|
+
granted: false,
|
|
83
|
+
tier: this.tier(),
|
|
84
|
+
denied: "unknown_paid_in_flight",
|
|
85
|
+
reason: "one unknown-cost paid unit is already in flight",
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
const estimate = zeroCash ? 0 : (cost.estimatedUsd ?? 0);
|
|
89
|
+
const headroom = this.remainingUsd();
|
|
90
|
+
if (estimate > 0 && headroom !== null && estimate >= headroom) {
|
|
91
|
+
return {
|
|
92
|
+
granted: false,
|
|
93
|
+
tier: this.tier(),
|
|
94
|
+
denied: "estimate_headroom",
|
|
95
|
+
reason: `insufficient headroom for estimated cost (${estimate.toFixed(2)} USD >= ${headroom.toFixed(2)} USD remaining)`,
|
|
96
|
+
};
|
|
89
97
|
}
|
|
90
98
|
const lease = BudgetLeaseSchema.parse({
|
|
91
99
|
lease_id: newId("lease"),
|
|
@@ -94,119 +102,237 @@ export class BudgetLedger {
|
|
|
94
102
|
intent: input.intent,
|
|
95
103
|
harness_id: input.harnessId,
|
|
96
104
|
model_hint: input.modelHint ?? null,
|
|
97
|
-
|
|
105
|
+
cost,
|
|
98
106
|
reason: input.reason ?? [],
|
|
99
107
|
created_at: nowIso(),
|
|
100
108
|
state: "reserved",
|
|
101
109
|
});
|
|
102
110
|
this.leases.set(lease.lease_id, lease);
|
|
103
|
-
if (
|
|
104
|
-
this.
|
|
105
|
-
|
|
106
|
-
|
|
111
|
+
if (estimate > 0)
|
|
112
|
+
this.holds.set(lease.lease_id, estimate);
|
|
113
|
+
if (unknownPaid && cap !== null)
|
|
114
|
+
this.unknownPaidInFlight.add(lease.lease_id);
|
|
115
|
+
return { granted: true, tier: this.tier(), lease };
|
|
107
116
|
}
|
|
108
|
-
/**
|
|
109
|
-
* Raise a lease's hold to the cost streamed so far (never lowers it). Call from
|
|
110
|
-
* the usage-event stream so `tier()` reflects in-flight spend mid-attempt.
|
|
111
|
-
*/
|
|
112
117
|
updateHold(leaseId, streamedUsd) {
|
|
113
|
-
|
|
118
|
+
const lease = this.leases.get(leaseId);
|
|
119
|
+
if (!lease || lease.state !== "reserved")
|
|
120
|
+
return;
|
|
121
|
+
if (lease.cost.billing === "proven_zero" || lease.cost.billing === "subscription_entitlement")
|
|
114
122
|
return;
|
|
115
123
|
const current = this.holds.get(leaseId) ?? 0;
|
|
116
124
|
if (streamedUsd > current)
|
|
117
|
-
this.
|
|
118
|
-
}
|
|
119
|
-
setHold(leaseId, usd) {
|
|
120
|
-
const prev = this.holds.get(leaseId) ?? 0;
|
|
121
|
-
this.holds.set(leaseId, usd);
|
|
122
|
-
this.parent?.adjustRollupHold(leaseId, usd - prev);
|
|
123
|
-
}
|
|
124
|
-
adjustRollupHold(leaseId, deltaUsd) {
|
|
125
|
-
const key = `child:${leaseId}`;
|
|
126
|
-
const prev = this.holds.get(key) ?? 0;
|
|
127
|
-
const next = Math.max(0, prev + deltaUsd);
|
|
128
|
-
if (next === 0)
|
|
129
|
-
this.holds.delete(key);
|
|
130
|
-
else
|
|
131
|
-
this.holds.set(key, next);
|
|
132
|
-
this.parent?.adjustRollupHold(leaseId, deltaUsd);
|
|
133
|
-
}
|
|
134
|
-
clearHold(leaseId) {
|
|
135
|
-
const held = this.holds.get(leaseId) ?? 0;
|
|
136
|
-
this.holds.delete(leaseId);
|
|
137
|
-
if (held > 0)
|
|
138
|
-
this.parent?.adjustRollupHold(leaseId, -held);
|
|
125
|
+
this.holds.set(leaseId, streamedUsd);
|
|
139
126
|
}
|
|
140
|
-
settle(leaseId,
|
|
127
|
+
settle(leaseId, settlement) {
|
|
141
128
|
const lease = this.leases.get(leaseId);
|
|
142
|
-
// Fail loudly: settling a lease this ledger never granted would attribute
|
|
143
|
-
// spend to nothing (a bookkeeping bug, not a runtime race).
|
|
144
129
|
if (!lease)
|
|
145
130
|
throw new Error(`cannot settle unknown lease: ${leaseId}`);
|
|
146
|
-
// Idempotent for the spend add: a duplicate settle (success path followed
|
|
147
|
-
// by a late error handler) must never double-count real spend. DECIDED
|
|
148
|
-
// TRADEOFF: this no-op can also mask a genuine double-settle bug — spend
|
|
149
|
-
// correctness wins because the duplicate-settle race is a real runtime
|
|
150
|
-
// path (terminal handler + error handler), while a masked bug still
|
|
151
|
-
// surfaces in the rollup totals a test would assert on.
|
|
152
131
|
if (lease.state !== "reserved")
|
|
153
132
|
return;
|
|
154
133
|
lease.state = "settled";
|
|
155
|
-
this.
|
|
156
|
-
this.
|
|
157
|
-
|
|
134
|
+
this.holds.delete(leaseId);
|
|
135
|
+
this.unknownPaidInFlight.delete(leaseId);
|
|
136
|
+
const zeroCash = lease.cost.billing === "proven_zero" || lease.cost.billing === "subscription_entitlement";
|
|
137
|
+
const cashUsd = zeroCash ? 0 : Math.max(0, settlement.cashUsd ?? 0);
|
|
138
|
+
this.spendUsd += cashUsd;
|
|
139
|
+
this.valuationUsd += Math.max(0, settlement.valuationUsd ?? (zeroCash ? (settlement.cashUsd ?? 0) : 0));
|
|
140
|
+
if (this.budget.kind === "finite") {
|
|
141
|
+
if (!zeroCash && settlement.knowledge === "unknown")
|
|
142
|
+
this.unverifiable = true;
|
|
143
|
+
if (this.spendUsd > this.budget.maxUsd)
|
|
144
|
+
this.overshot = true;
|
|
145
|
+
}
|
|
146
|
+
this.deps.onCashSettled?.(this.spendUsd, this.valuationUsd);
|
|
158
147
|
}
|
|
159
148
|
cancel(leaseId) {
|
|
160
149
|
const lease = this.leases.get(leaseId);
|
|
161
|
-
if (lease)
|
|
150
|
+
if (lease?.state === "reserved")
|
|
162
151
|
lease.state = "cancelled";
|
|
163
|
-
this.
|
|
164
|
-
|
|
165
|
-
addRollupSpend(usd) {
|
|
166
|
-
this.spendUsd += usd;
|
|
167
|
-
this.parent?.addRollupSpend(usd);
|
|
152
|
+
this.holds.delete(leaseId);
|
|
153
|
+
this.unknownPaidInFlight.delete(leaseId);
|
|
168
154
|
}
|
|
169
155
|
spend() {
|
|
170
156
|
return this.spendUsd;
|
|
171
157
|
}
|
|
172
|
-
|
|
173
|
-
this.
|
|
158
|
+
valuation() {
|
|
159
|
+
return this.valuationUsd;
|
|
160
|
+
}
|
|
161
|
+
terminal() {
|
|
162
|
+
if (this.overshot)
|
|
163
|
+
return "exhausted_overshoot";
|
|
164
|
+
if (this.unverifiable)
|
|
165
|
+
return "cost_unverifiable";
|
|
166
|
+
return this.tier() === "hard" ? "exhausted" : null;
|
|
167
|
+
}
|
|
168
|
+
observe(observation) {
|
|
169
|
+
this.observations.push(observation);
|
|
170
|
+
}
|
|
171
|
+
/** Seed durable quota projection without collapsing credential identities. */
|
|
172
|
+
observeQuotaSnapshot(snapshot) {
|
|
173
|
+
const subject = snapshot.subject;
|
|
174
|
+
const key = [
|
|
175
|
+
subject.harness,
|
|
176
|
+
subject.credential_route,
|
|
177
|
+
subject.subject_id ?? "",
|
|
178
|
+
snapshot.source,
|
|
179
|
+
].join("\0");
|
|
180
|
+
this.quotaSnapshots.set(key, snapshot);
|
|
174
181
|
}
|
|
175
182
|
observationsFor(harnessId) {
|
|
176
|
-
return this.observations.filter((
|
|
183
|
+
return this.observations.filter((observation) => observation.harness_id === harnessId);
|
|
177
184
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
185
|
+
cooldownActive(harnessId, credentialRoute, credentialSubjectId, now = Date.now()) {
|
|
186
|
+
// Live observations are subject- AND route-scoped like snapshots
|
|
187
|
+
// (rounds 17-18): a profiled or API-key rate-limit must never cool the
|
|
188
|
+
// same harness's other subjects or its healthy other route. `undefined`
|
|
189
|
+
// caller subject/route = conservative any; a LEGACY observation without
|
|
190
|
+
// a route stamp stays conservative (applies to every route).
|
|
191
|
+
const liveObservation = this.observationsFor(harnessId).some((observation) => {
|
|
192
|
+
if (credentialSubjectId !== undefined &&
|
|
193
|
+
(observation.subject_id ?? null) !== credentialSubjectId)
|
|
194
|
+
return false;
|
|
195
|
+
if (credentialRoute !== undefined &&
|
|
196
|
+
observation.credential_route !== undefined &&
|
|
197
|
+
observation.credential_route !== credentialRoute)
|
|
198
|
+
return false;
|
|
199
|
+
if (!observation.cooldown_until)
|
|
182
200
|
return false;
|
|
183
|
-
const
|
|
184
|
-
return Number.isFinite(
|
|
201
|
+
const time = Date.parse(observation.cooldown_until);
|
|
202
|
+
return Number.isFinite(time) && time > now;
|
|
185
203
|
});
|
|
204
|
+
if (liveObservation)
|
|
205
|
+
return true;
|
|
206
|
+
if (!credentialRoute)
|
|
207
|
+
return false;
|
|
208
|
+
return this.snapshotsFor(harnessId, credentialRoute, credentialSubjectId).some((snapshot) => snapshot.constraints.some((constraint) => {
|
|
209
|
+
const cooldown = constraint.cooldown_until
|
|
210
|
+
? Date.parse(constraint.cooldown_until)
|
|
211
|
+
: Number.NaN;
|
|
212
|
+
const reset = constraint.resets_at ? Date.parse(constraint.resets_at) : Number.NaN;
|
|
213
|
+
return ((Number.isFinite(cooldown) && cooldown > now) ||
|
|
214
|
+
(constraint.used_ratio !== null &&
|
|
215
|
+
constraint.used_ratio >= 1 &&
|
|
216
|
+
Number.isFinite(reset) &&
|
|
217
|
+
reset > now));
|
|
218
|
+
}));
|
|
219
|
+
}
|
|
220
|
+
/** Binding pacing slack across applicable windows; null means honestly unknown. */
|
|
221
|
+
bindingPaceSlack(harnessId, credentialRoute, credentialSubjectId, now = Date.now()) {
|
|
222
|
+
const latest = new Map();
|
|
223
|
+
for (const observation of this.observationsFor(harnessId)) {
|
|
224
|
+
if (observation.kind !== "quota_constraint" || !observation.constraint_id)
|
|
225
|
+
continue;
|
|
226
|
+
// Subject- and route-scoped like cooldowns (rounds 17-18); the latest
|
|
227
|
+
// key includes route+subject so two routes' same-named windows never
|
|
228
|
+
// overwrite each other.
|
|
229
|
+
if (credentialSubjectId !== undefined &&
|
|
230
|
+
(observation.subject_id ?? null) !== credentialSubjectId)
|
|
231
|
+
continue;
|
|
232
|
+
if (credentialRoute !== undefined &&
|
|
233
|
+
observation.credential_route !== undefined &&
|
|
234
|
+
observation.credential_route !== credentialRoute)
|
|
235
|
+
continue;
|
|
236
|
+
latest.set(`${observation.credential_route ?? ""}\0${observation.subject_id ?? ""}\0${observation.constraint_id}`, observation);
|
|
237
|
+
}
|
|
238
|
+
const slacks = [];
|
|
239
|
+
for (const observation of latest.values()) {
|
|
240
|
+
if (typeof observation.used_ratio !== "number" ||
|
|
241
|
+
typeof observation.window_seconds !== "number" ||
|
|
242
|
+
!observation.resets_at)
|
|
243
|
+
continue;
|
|
244
|
+
const resetMs = Date.parse(observation.resets_at);
|
|
245
|
+
if (!Number.isFinite(resetMs) || resetMs <= now)
|
|
246
|
+
continue;
|
|
247
|
+
const remaining = Math.min(1, Math.max(0, (resetMs - now) / 1000 / observation.window_seconds));
|
|
248
|
+
const elapsedFraction = 1 - remaining;
|
|
249
|
+
slacks.push(elapsedFraction - observation.used_ratio);
|
|
250
|
+
}
|
|
251
|
+
if (credentialRoute) {
|
|
252
|
+
for (const snapshot of this.snapshotsFor(harnessId, credentialRoute, credentialSubjectId)) {
|
|
253
|
+
for (const constraint of snapshot.constraints) {
|
|
254
|
+
if (typeof constraint.used_ratio !== "number" ||
|
|
255
|
+
typeof constraint.window_seconds !== "number" ||
|
|
256
|
+
!constraint.resets_at)
|
|
257
|
+
continue;
|
|
258
|
+
const resetMs = Date.parse(constraint.resets_at);
|
|
259
|
+
if (!Number.isFinite(resetMs) || resetMs <= now)
|
|
260
|
+
continue;
|
|
261
|
+
const remaining = Math.min(1, Math.max(0, (resetMs - now) / 1000 / constraint.window_seconds));
|
|
262
|
+
slacks.push(1 - remaining - constraint.used_ratio);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return slacks.length > 0 ? Math.min(...slacks) : null;
|
|
186
267
|
}
|
|
187
|
-
/**
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
268
|
+
/** Fresh snapshots for a harness+route, optionally pinned to ONE credential
|
|
269
|
+
* subject (release wave round-16 #2): when the caller knows the effective
|
|
270
|
+
* subject — a profile id, or null for the engine default — only that
|
|
271
|
+
* subject's windows apply, so profile A's exhaustion never cools profile B
|
|
272
|
+
* or the default. `undefined` = subject unknown, conservative any-subject. */
|
|
273
|
+
snapshotsFor(harnessId, credentialRoute, credentialSubjectId) {
|
|
274
|
+
return [...this.quotaSnapshots.values()].filter((snapshot) => snapshot.freshness === "fresh" &&
|
|
275
|
+
snapshot.subject.harness === harnessId &&
|
|
276
|
+
snapshot.subject.credential_route === credentialRoute &&
|
|
277
|
+
(credentialSubjectId === undefined ||
|
|
278
|
+
(snapshot.subject.subject_id ?? null) === credentialSubjectId));
|
|
196
279
|
}
|
|
197
280
|
recordPrompt(fingerprint) {
|
|
198
|
-
const
|
|
199
|
-
this.promptCounts.set(fingerprint,
|
|
200
|
-
return
|
|
281
|
+
const count = (this.promptCounts.get(fingerprint) ?? 0) + 1;
|
|
282
|
+
this.promptCounts.set(fingerprint, count);
|
|
283
|
+
return count;
|
|
201
284
|
}
|
|
202
285
|
isLoop(fingerprint, threshold = 3) {
|
|
203
286
|
return (this.promptCounts.get(fingerprint) ?? 0) >= threshold;
|
|
204
287
|
}
|
|
205
288
|
}
|
|
206
|
-
function
|
|
207
|
-
return {
|
|
289
|
+
export function routeCostEvidence(input) {
|
|
290
|
+
return CostEvidenceSchema.parse({
|
|
291
|
+
billing: input.billing ?? "unknown",
|
|
292
|
+
knowledge: input.knowledge ?? "unknown",
|
|
293
|
+
source: input.source,
|
|
294
|
+
provenance: input.provenance,
|
|
295
|
+
estimatedUsd: input.estimatedUsd ?? null,
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
export function attemptCostEvidence(harnessId, attemptId, estimatedUsd, billing = "unknown") {
|
|
299
|
+
return routeCostEvidence({
|
|
300
|
+
source: "route-preflight",
|
|
301
|
+
provenance: [`harness:${harnessId}`, `attempt:${attemptId}`, `billing:${billing}`],
|
|
302
|
+
billing,
|
|
303
|
+
knowledge: estimatedUsd === undefined ? "unknown" : "estimated",
|
|
304
|
+
estimatedUsd: estimatedUsd ?? null,
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
export function usageCostSettlement(cashUsd, estimated, source, provenance) {
|
|
308
|
+
return cashUsd > 0
|
|
309
|
+
? { knowledge: estimated ? "estimated" : "exact", source, provenance, cashUsd }
|
|
310
|
+
: { knowledge: "unknown", source: `${source}-missing`, provenance };
|
|
311
|
+
}
|
|
312
|
+
export function attemptUsageCostSettlement(cashUsd, estimated, attemptId, harnessId, authMode) {
|
|
313
|
+
if (authMode === "local_session" && estimated) {
|
|
314
|
+
return {
|
|
315
|
+
knowledge: "unknown",
|
|
316
|
+
source: "harness-token-valuation",
|
|
317
|
+
provenance: [`attempt:${attemptId}`, `harness:${harnessId}`, "route:vendor_native"],
|
|
318
|
+
valuationUsd: cashUsd,
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
return usageCostSettlement(cashUsd, estimated, "harness-usage", [
|
|
322
|
+
`attempt:${attemptId}`,
|
|
323
|
+
`harness:${harnessId}`,
|
|
324
|
+
...(authMode ? [`route:${authMode}`] : []),
|
|
325
|
+
]);
|
|
326
|
+
}
|
|
327
|
+
export function unknownCostSettlement(source, cashUsd) {
|
|
328
|
+
return {
|
|
329
|
+
knowledge: "unknown",
|
|
330
|
+
source,
|
|
331
|
+
provenance: [`orchestrator:${source}`],
|
|
332
|
+
...(cashUsd === undefined ? {} : { cashUsd }),
|
|
333
|
+
};
|
|
208
334
|
}
|
|
209
|
-
function
|
|
210
|
-
return
|
|
335
|
+
export function isBudgetTerminal(status) {
|
|
336
|
+
return (status === "exhausted" || status === "exhausted_overshoot" || status === "cost_unverifiable");
|
|
211
337
|
}
|
|
212
338
|
//# sourceMappingURL=ledger.js.map
|
package/dist/ledger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ledger.js","sourceRoot":"","sources":["../src/ledger.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ledger.js","sourceRoot":"","sources":["../src/ledger.ts"],"names":[],"mappings":"AAWA,OAAO,EACL,WAAW,IAAI,iBAAiB,EAChC,YAAY,IAAI,kBAAkB,GACnC,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAqCxD,MAAM,YAAY,GAAiB;IACjC,SAAS,EAAE,SAAS;IACpB,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,iBAAiB;IACzB,UAAU,EAAE,CAAC,uBAAuB,CAAC;IACrC,YAAY,EAAE,IAAI;CACnB,CAAC;AAEF,yDAAyD;AACzD,MAAM,UAAU,iBAAiB,CAAC,MAAc;IAC9C,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AAClE,CAAC;AAED,iFAAiF;AACjF,MAAM,OAAO,YAAY;IAaJ;IACA;IACA;IAdF,MAAM,GAAG,IAAI,GAAG,EAAuB,CAAC;IACxC,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;IAClC,mBAAmB,GAAG,IAAI,GAAG,EAAU,CAAC;IACxC,YAAY,GAAwB,EAAE,CAAC;IACvC,cAAc,GAAG,IAAI,GAAG,EAAyB,CAAC;IAClD,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAC;IAClD,QAAQ,GAAG,CAAC,CAAC;IACb,YAAY,GAAG,CAAC,CAAC;IACjB,QAAQ,GAAG,KAAK,CAAC;IACjB,YAAY,GAAG,KAAK,CAAC;IAE7B,YACmB,SAAqB,EAAE,IAAI,EAAE,WAAW,EAAE,EAC1C,aAAgC,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,EACvE,OASb,EAAE;QAXW,WAAM,GAAN,MAAM,CAAoC;QAC1C,eAAU,GAAV,UAAU,CAA6D;QACvE,SAAI,GAAJ,IAAI,CASf;IACL,CAAC;IAEI,gBAAgB;QACtB,IAAI,GAAG,GAAG,CAAC,CAAC;QACZ,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;YAAE,GAAG,IAAI,KAAK,CAAC;QACtD,OAAO,GAAG,CAAC;IACb,CAAC;IAEO,GAAG;QACT,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;IACnE,CAAC;IAED,IAAI;QACF,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,IAAI,GAAG,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QAC9B,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO,MAAM,CAAC;QACjC,IAAI,GAAG,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC,QAAQ,GAAG,CAAC,IAAI,IAAI,CAAC,gBAAgB,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;QACvF,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC,GAAG,GAAG,CAAC;QAC9D,IAAI,KAAK,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI;YAAE,OAAO,MAAM,CAAC;QACjD,IAAI,KAAK,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS;YAAE,OAAO,WAAW,CAAC;QAC3D,IAAI,KAAK,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI;YAAE,OAAO,MAAM,CAAC;QACjD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,YAAY;QACV,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,OAAO,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC;IAC1F,CAAC;IAED,OAAO,CAAC,KAAmB;QACzB,MAAM,IAAI,GAAG,kBAAkB,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,IAAI,YAAY,CAAC,CAAC;QAClE,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,KAAK,aAAa,IAAI,IAAI,CAAC,OAAO,KAAK,0BAA0B,CAAC;QAC/F,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC3B,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,IAAI,EAAE,MAAM;gBACZ,MAAM,EAAE,aAAa;gBACrB,MAAM,EAAE,oEAAoE;aAC7E,CAAC;QACJ,CAAC;QACD,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;YACxC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,kBAAkB,EAAE,CAAC;QAC1F,CAAC;QACD,MAAM,WAAW,GAAG,CAAC,QAAQ,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,CAAC;QAC9D,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,GAAG,CAAC,IAAI,WAAW,IAAI,IAAI,CAAC,mBAAmB,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YAChF,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE;gBACjB,MAAM,EAAE,wBAAwB;gBAChC,MAAM,EAAE,iDAAiD;aAC1D,CAAC;QACJ,CAAC;QACD,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,CAAC,CAAC;QACzD,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QACrC,IAAI,QAAQ,GAAG,CAAC,IAAI,QAAQ,KAAK,IAAI,IAAI,QAAQ,IAAI,QAAQ,EAAE,CAAC;YAC9D,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE;gBACjB,MAAM,EAAE,mBAAmB;gBAC3B,MAAM,EAAE,6CAA6C,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,iBAAiB;aACxH,CAAC;QACJ,CAAC;QACD,MAAM,KAAK,GAAG,iBAAiB,CAAC,KAAK,CAAC;YACpC,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC;YACxB,OAAO,EAAE,KAAK,CAAC,MAAM;YACrB,UAAU,EAAE,KAAK,CAAC,SAAS;YAC3B,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,UAAU,EAAE,KAAK,CAAC,SAAS;YAC3B,UAAU,EAAE,KAAK,CAAC,SAAS,IAAI,IAAI;YACnC,IAAI;YACJ,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,EAAE;YAC1B,UAAU,EAAE,MAAM,EAAE;YACpB,KAAK,EAAE,UAAU;SAClB,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QACvC,IAAI,QAAQ,GAAG,CAAC;YAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC3D,IAAI,WAAW,IAAI,GAAG,KAAK,IAAI;YAAE,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC9E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC;IACrD,CAAC;IAED,UAAU,CAAC,OAAe,EAAE,WAAmB;QAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACvC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,KAAK,UAAU;YAAE,OAAO;QACjD,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,KAAK,aAAa,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,KAAK,0BAA0B;YAC3F,OAAO;QACT,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC7C,IAAI,WAAW,GAAG,OAAO;YAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IAClE,CAAC;IAED,MAAM,CAAC,OAAe,EAAE,UAA4B;QAClD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACvC,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,OAAO,EAAE,CAAC,CAAC;QACvE,IAAI,KAAK,CAAC,KAAK,KAAK,UAAU;YAAE,OAAO;QACvC,KAAK,CAAC,KAAK,GAAG,SAAS,CAAC;QACxB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC3B,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACzC,MAAM,QAAQ,GACZ,KAAK,CAAC,IAAI,CAAC,OAAO,KAAK,aAAa,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,KAAK,0BAA0B,CAAC;QAC5F,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC;QACpE,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC;QACzB,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,GAAG,CAC3B,CAAC,EACD,UAAU,CAAC,YAAY,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CACtE,CAAC;QACF,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAClC,IAAI,CAAC,QAAQ,IAAI,UAAU,CAAC,SAAS,KAAK,SAAS;gBAAE,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;YAC9E,IAAI,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM;gBAAE,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QAC/D,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;IAC9D,CAAC;IAED,MAAM,CAAC,OAAe;QACpB,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACvC,IAAI,KAAK,EAAE,KAAK,KAAK,UAAU;YAAE,KAAK,CAAC,KAAK,GAAG,WAAW,CAAC;QAC3D,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC3B,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC3C,CAAC;IAED,KAAK;QACH,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAED,QAAQ;QACN,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO,qBAAqB,CAAC;QAChD,IAAI,IAAI,CAAC,YAAY;YAAE,OAAO,mBAAmB,CAAC;QAClD,OAAO,IAAI,CAAC,IAAI,EAAE,KAAK,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC;IACrD,CAAC;IAED,OAAO,CAAC,WAA8B;QACpC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACtC,CAAC;IAED,8EAA8E;IAC9E,oBAAoB,CAAC,QAAuB;QAC1C,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC;QACjC,MAAM,GAAG,GAAG;YACV,OAAO,CAAC,OAAO;YACf,OAAO,CAAC,gBAAgB;YACxB,OAAO,CAAC,UAAU,IAAI,EAAE;YACxB,QAAQ,CAAC,MAAM;SAChB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACb,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IACzC,CAAC;IAED,eAAe,CAAC,SAAiB;QAC/B,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,WAAW,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC;IACzF,CAAC;IAED,cAAc,CACZ,SAAiB,EACjB,eAAiC,EACjC,mBAAmC,EACnC,MAAc,IAAI,CAAC,GAAG,EAAE;QAExB,iEAAiE;QACjE,uEAAuE;QACvE,wEAAwE;QACxE,wEAAwE;QACxE,6DAA6D;QAC7D,MAAM,eAAe,GAAG,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,EAAE;YAC3E,IACE,mBAAmB,KAAK,SAAS;gBACjC,CAAC,WAAW,CAAC,UAAU,IAAI,IAAI,CAAC,KAAK,mBAAmB;gBAExD,OAAO,KAAK,CAAC;YACf,IACE,eAAe,KAAK,SAAS;gBAC7B,WAAW,CAAC,gBAAgB,KAAK,SAAS;gBAC1C,WAAW,CAAC,gBAAgB,KAAK,eAAe;gBAEhD,OAAO,KAAK,CAAC;YAEf,IAAI,CAAC,WAAW,CAAC,cAAc;gBAAE,OAAO,KAAK,CAAC;YAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC;YACpD,OAAO,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,GAAG,CAAC;QAC7C,CAAC,CAAC,CAAC;QACH,IAAI,eAAe;YAAE,OAAO,IAAI,CAAC;QACjC,IAAI,CAAC,eAAe;YAAE,OAAO,KAAK,CAAC;QACnC,OAAO,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,eAAe,EAAE,mBAAmB,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAC1F,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,EAAE;YACvC,MAAM,QAAQ,GAAG,UAAU,CAAC,cAAc;gBACxC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,cAAc,CAAC;gBACvC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;YACf,MAAM,KAAK,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;YACnF,OAAO,CACL,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,QAAQ,GAAG,GAAG,CAAC;gBAC7C,CAAC,UAAU,CAAC,UAAU,KAAK,IAAI;oBAC7B,UAAU,CAAC,UAAU,IAAI,CAAC;oBAC1B,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;oBACtB,KAAK,GAAG,GAAG,CAAC,CACf,CAAC;QACJ,CAAC,CAAC,CACH,CAAC;IACJ,CAAC;IAED,mFAAmF;IACnF,gBAAgB,CACd,SAAiB,EACjB,eAAiC,EACjC,mBAAmC,EACnC,MAAc,IAAI,CAAC,GAAG,EAAE;QAExB,MAAM,MAAM,GAAG,IAAI,GAAG,EAA6B,CAAC;QACpD,KAAK,MAAM,WAAW,IAAI,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,EAAE,CAAC;YAC1D,IAAI,WAAW,CAAC,IAAI,KAAK,kBAAkB,IAAI,CAAC,WAAW,CAAC,aAAa;gBAAE,SAAS;YACpF,sEAAsE;YACtE,qEAAqE;YACrE,wBAAwB;YACxB,IACE,mBAAmB,KAAK,SAAS;gBACjC,CAAC,WAAW,CAAC,UAAU,IAAI,IAAI,CAAC,KAAK,mBAAmB;gBAExD,SAAS;YACX,IACE,eAAe,KAAK,SAAS;gBAC7B,WAAW,CAAC,gBAAgB,KAAK,SAAS;gBAC1C,WAAW,CAAC,gBAAgB,KAAK,eAAe;gBAEhD,SAAS;YACX,MAAM,CAAC,GAAG,CACR,GAAG,WAAW,CAAC,gBAAgB,IAAI,EAAE,KAAK,WAAW,CAAC,UAAU,IAAI,EAAE,KAAK,WAAW,CAAC,aAAa,EAAE,EACtG,WAAW,CACZ,CAAC;QACJ,CAAC;QACD,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,KAAK,MAAM,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;YAC1C,IACE,OAAO,WAAW,CAAC,UAAU,KAAK,QAAQ;gBAC1C,OAAO,WAAW,CAAC,cAAc,KAAK,QAAQ;gBAC9C,CAAC,WAAW,CAAC,SAAS;gBAEtB,SAAS;YACX,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;YAClD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,IAAI,GAAG;gBAAE,SAAS;YAC1D,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CACxB,CAAC,EACD,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,OAAO,GAAG,GAAG,CAAC,GAAG,IAAI,GAAG,WAAW,CAAC,cAAc,CAAC,CACjE,CAAC;YACF,MAAM,eAAe,GAAG,CAAC,GAAG,SAAS,CAAC;YACtC,MAAM,CAAC,IAAI,CAAC,eAAe,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;QACxD,CAAC;QACD,IAAI,eAAe,EAAE,CAAC;YACpB,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,eAAe,EAAE,mBAAmB,CAAC,EAAE,CAAC;gBAC1F,KAAK,MAAM,UAAU,IAAI,QAAQ,CAAC,WAAW,EAAE,CAAC;oBAC9C,IACE,OAAO,UAAU,CAAC,UAAU,KAAK,QAAQ;wBACzC,OAAO,UAAU,CAAC,cAAc,KAAK,QAAQ;wBAC7C,CAAC,UAAU,CAAC,SAAS;wBAErB,SAAS;oBACX,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;oBACjD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,IAAI,GAAG;wBAAE,SAAS;oBAC1D,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CACxB,CAAC,EACD,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,OAAO,GAAG,GAAG,CAAC,GAAG,IAAI,GAAG,UAAU,CAAC,cAAc,CAAC,CAChE,CAAC;oBACF,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;gBACrD,CAAC;YACH,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACxD,CAAC;IAED;;;;kFAI8E;IACtE,YAAY,CAClB,SAAiB,EACjB,eAAgC,EAChC,mBAAmC;QAEnC,OAAO,CAAC,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAC7C,CAAC,QAAQ,EAAE,EAAE,CACX,QAAQ,CAAC,SAAS,KAAK,OAAO;YAC9B,QAAQ,CAAC,OAAO,CAAC,OAAO,KAAK,SAAS;YACtC,QAAQ,CAAC,OAAO,CAAC,gBAAgB,KAAK,eAAe;YACrD,CAAC,mBAAmB,KAAK,SAAS;gBAChC,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,IAAI,IAAI,CAAC,KAAK,mBAAmB,CAAC,CACnE,CAAC;IACJ,CAAC;IAED,YAAY,CAAC,WAAmB;QAC9B,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QAC5D,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;QAC1C,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,CAAC,WAAmB,EAAE,SAAS,GAAG,CAAC;QACvC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,SAAS,CAAC;IAChE,CAAC;CACF;AAED,MAAM,UAAU,iBAAiB,CAAC,KAMjC;IACC,OAAO,kBAAkB,CAAC,KAAK,CAAC;QAC9B,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,SAAS;QACnC,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,SAAS;QACvC,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,YAAY,EAAE,KAAK,CAAC,YAAY,IAAI,IAAI;KACzC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,SAAiB,EACjB,SAAiB,EACjB,YAAqB,EACrB,UAA4B,SAAS;IAErC,OAAO,iBAAiB,CAAC;QACvB,MAAM,EAAE,iBAAiB;QACzB,UAAU,EAAE,CAAC,WAAW,SAAS,EAAE,EAAE,WAAW,SAAS,EAAE,EAAE,WAAW,OAAO,EAAE,CAAC;QAClF,OAAO;QACP,SAAS,EAAE,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW;QAC/D,YAAY,EAAE,YAAY,IAAI,IAAI;KACnC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,OAAe,EACf,SAAkB,EAClB,MAAc,EACd,UAAoB;IAEpB,OAAO,OAAO,GAAG,CAAC;QAChB,CAAC,CAAC,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE;QAC/E,CAAC,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,UAAU,EAAE,UAAU,EAAE,CAAC;AACxE,CAAC;AAED,MAAM,UAAU,0BAA0B,CACxC,OAAe,EACf,SAAkB,EAClB,SAAiB,EACjB,SAAiB,EACjB,QAA6C;IAE7C,IAAI,QAAQ,KAAK,eAAe,IAAI,SAAS,EAAE,CAAC;QAC9C,OAAO;YACL,SAAS,EAAE,SAAS;YACpB,MAAM,EAAE,yBAAyB;YACjC,UAAU,EAAE,CAAC,WAAW,SAAS,EAAE,EAAE,WAAW,SAAS,EAAE,EAAE,qBAAqB,CAAC;YACnF,YAAY,EAAE,OAAO;SACtB,CAAC;IACJ,CAAC;IACD,OAAO,mBAAmB,CAAC,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE;QAC9D,WAAW,SAAS,EAAE;QACtB,WAAW,SAAS,EAAE;QACtB,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;KAC3C,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,MAAc,EAAE,OAAgB;IACpE,OAAO;QACL,SAAS,EAAE,SAAS;QACpB,MAAM;QACN,UAAU,EAAE,CAAC,gBAAgB,MAAM,EAAE,CAAC;QACtC,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC;KAC9C,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAqB;IACpD,OAAO,CACL,MAAM,KAAK,WAAW,IAAI,MAAM,KAAK,qBAAqB,IAAI,MAAM,KAAK,mBAAmB,CAC7F,CAAC;AACJ,CAAC"}
|
package/dist/metrics.d.ts
CHANGED
|
@@ -2,13 +2,27 @@ export interface HarnessMetric {
|
|
|
2
2
|
avg_cost_usd: number | null;
|
|
3
3
|
avg_duration_ms: number | null;
|
|
4
4
|
samples: number;
|
|
5
|
+
/**
|
|
6
|
+
* Auth route the harness's LAST settled attempt actually ran under
|
|
7
|
+
* (adapter-disclosed route evidence, not a manifest capability guess).
|
|
8
|
+
* Economy routing may consume settled cost as evidence; no quality prior is
|
|
9
|
+
* inferred. Null until any attempt disclosed a route.
|
|
10
|
+
*/
|
|
11
|
+
last_auth_mode: "local_session" | "api_key" | null;
|
|
5
12
|
}
|
|
6
13
|
export type HarnessMetrics = Record<string, HarnessMetric>;
|
|
7
14
|
export declare function metricsPath(configDir: string): string;
|
|
8
15
|
export declare function loadHarnessMetrics(configDir: string): HarnessMetrics;
|
|
9
|
-
/**
|
|
16
|
+
/**
|
|
17
|
+
* Record one settled attempt (EMA update; atomic tmp+rename write).
|
|
18
|
+
* `authMode` is route evidence and updates independently of the performance
|
|
19
|
+
* sample: an auth-only record (no cost/duration) refreshes `last_auth_mode`
|
|
20
|
+
* WITHOUT counting a sample, so errored attempts can still disclose the route
|
|
21
|
+
* they burned without earning a flattering latency average.
|
|
22
|
+
*/
|
|
10
23
|
export declare function recordHarnessMetric(configDir: string, harnessId: string, sample: {
|
|
11
24
|
costUsd?: number | null;
|
|
12
25
|
durationMs?: number | null;
|
|
26
|
+
authMode?: "local_session" | "api_key" | null;
|
|
13
27
|
}): void;
|
|
14
28
|
//# sourceMappingURL=metrics.d.ts.map
|
package/dist/metrics.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,OAAO,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,cAAc,EAAE,eAAe,GAAG,SAAS,GAAG,IAAI,CAAC;CACpD;AAED,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AAM3D,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,CAiCpE;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE;IACN,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,CAAC,EAAE,eAAe,GAAG,SAAS,GAAG,IAAI,CAAC;CAC/C,GACA,IAAI,CAmCN"}
|
package/dist/metrics.js
CHANGED
|
@@ -24,8 +24,15 @@ export function loadHarnessMetrics(configDir) {
|
|
|
24
24
|
const m = v;
|
|
25
25
|
out[id] = {
|
|
26
26
|
avg_cost_usd: typeof m.avg_cost_usd === "number" && m.avg_cost_usd >= 0 ? m.avg_cost_usd : null,
|
|
27
|
-
avg_duration_ms: typeof m.avg_duration_ms === "number" && m.avg_duration_ms >= 0
|
|
28
|
-
|
|
27
|
+
avg_duration_ms: typeof m.avg_duration_ms === "number" && m.avg_duration_ms >= 0
|
|
28
|
+
? m.avg_duration_ms
|
|
29
|
+
: null,
|
|
30
|
+
samples: typeof m.samples === "number" && m.samples > 0
|
|
31
|
+
? Math.min(m.samples, MAX_SAMPLES_COUNTED)
|
|
32
|
+
: 0,
|
|
33
|
+
last_auth_mode: m.last_auth_mode === "local_session" || m.last_auth_mode === "api_key"
|
|
34
|
+
? m.last_auth_mode
|
|
35
|
+
: null,
|
|
29
36
|
};
|
|
30
37
|
}
|
|
31
38
|
return out;
|
|
@@ -34,10 +41,21 @@ export function loadHarnessMetrics(configDir) {
|
|
|
34
41
|
return {};
|
|
35
42
|
}
|
|
36
43
|
}
|
|
37
|
-
/**
|
|
44
|
+
/**
|
|
45
|
+
* Record one settled attempt (EMA update; atomic tmp+rename write).
|
|
46
|
+
* `authMode` is route evidence and updates independently of the performance
|
|
47
|
+
* sample: an auth-only record (no cost/duration) refreshes `last_auth_mode`
|
|
48
|
+
* WITHOUT counting a sample, so errored attempts can still disclose the route
|
|
49
|
+
* they burned without earning a flattering latency average.
|
|
50
|
+
*/
|
|
38
51
|
export function recordHarnessMetric(configDir, harnessId, sample) {
|
|
39
52
|
const all = loadHarnessMetrics(configDir);
|
|
40
|
-
const prev = all[harnessId] ?? {
|
|
53
|
+
const prev = all[harnessId] ?? {
|
|
54
|
+
avg_cost_usd: null,
|
|
55
|
+
avg_duration_ms: null,
|
|
56
|
+
samples: 0,
|
|
57
|
+
last_auth_mode: null,
|
|
58
|
+
};
|
|
41
59
|
const ema = (old, next) => {
|
|
42
60
|
if (typeof next !== "number" || !Number.isFinite(next) || next < 0)
|
|
43
61
|
return old;
|
|
@@ -45,10 +63,14 @@ export function recordHarnessMetric(configDir, harnessId, sample) {
|
|
|
45
63
|
return next;
|
|
46
64
|
return old * (1 - EMA_ALPHA) + next * EMA_ALPHA;
|
|
47
65
|
};
|
|
66
|
+
const isPerfSample = typeof sample.costUsd === "number" || typeof sample.durationMs === "number";
|
|
48
67
|
all[harnessId] = {
|
|
49
68
|
avg_cost_usd: ema(prev.avg_cost_usd, sample.costUsd),
|
|
50
69
|
avg_duration_ms: ema(prev.avg_duration_ms, sample.durationMs),
|
|
51
|
-
samples: Math.min(prev.samples + 1, MAX_SAMPLES_COUNTED),
|
|
70
|
+
samples: isPerfSample ? Math.min(prev.samples + 1, MAX_SAMPLES_COUNTED) : prev.samples,
|
|
71
|
+
last_auth_mode: sample.authMode === "local_session" || sample.authMode === "api_key"
|
|
72
|
+
? sample.authMode
|
|
73
|
+
: prev.last_auth_mode,
|
|
52
74
|
};
|
|
53
75
|
const path = metricsPath(configDir);
|
|
54
76
|
try {
|
package/dist/metrics.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metrics.js","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"metrics.js","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"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"}
|
package/dist/observe.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"observe.d.ts","sourceRoot":"","sources":["../src/observe.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAKzE;;;;;;GAMG;AACH;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,GAAG,iBAAiB,EAAE,
|
|
1
|
+
{"version":3,"file":"observe.d.ts","sourceRoot":"","sources":["../src/observe.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAKzE;;;;;;GAMG;AACH;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,GAAG,iBAAiB,EAAE,CA0C9F"}
|
package/dist/observe.js
CHANGED
|
@@ -15,34 +15,54 @@ const DEFAULT_COOLDOWN_MS = 5 * 60 * 1000;
|
|
|
15
15
|
*/
|
|
16
16
|
export function observationsFromEvent(harnessId, ev) {
|
|
17
17
|
const out = [];
|
|
18
|
+
// The credential subject rides EVERY observation (round-17 #2): a profiled
|
|
19
|
+
// run's rate-limit/quota signal belongs to that profile's account, and an
|
|
20
|
+
// unstamped observation would penalize the whole harness — profile B and
|
|
21
|
+
// the engine default included.
|
|
22
|
+
const subject = {
|
|
23
|
+
...(ev.credential_route ? { credential_route: ev.credential_route } : {}),
|
|
24
|
+
subject_id: ev.credential_profile_id ?? null,
|
|
25
|
+
};
|
|
18
26
|
if (ev.type === "usage" && typeof ev.usage?.cost_usd === "number" && ev.usage.cost_usd > 0) {
|
|
19
27
|
// Token-derived costs (e.g. codex) are honest estimates -> "observed"; only
|
|
20
28
|
// natively-reported costs (e.g. claude) are "exact".
|
|
21
29
|
const quality = ev.usage.estimated ? "observed" : "exact";
|
|
22
|
-
out.push({ harness_id: harnessId, ts: nowIso(), quality, kind: "spend", usd: ev.usage.cost_usd });
|
|
23
|
-
}
|
|
24
|
-
if (ev.quota) {
|
|
25
|
-
// The CLI's own machine-readable window record (codex rollout
|
|
26
|
-
// token_count.rate_limits) -> "native" quality used_percent observation.
|
|
27
30
|
out.push({
|
|
28
31
|
harness_id: harnessId,
|
|
32
|
+
...subject,
|
|
29
33
|
ts: nowIso(),
|
|
30
|
-
quality
|
|
31
|
-
kind: "
|
|
32
|
-
|
|
33
|
-
resets_at: ev.quota.resets_at ?? null,
|
|
34
|
+
quality,
|
|
35
|
+
kind: "spend",
|
|
36
|
+
usd: ev.usage.cost_usd,
|
|
34
37
|
});
|
|
35
38
|
}
|
|
39
|
+
if (ev.quota) {
|
|
40
|
+
for (const constraint of ev.quota.constraints) {
|
|
41
|
+
out.push({
|
|
42
|
+
harness_id: harnessId,
|
|
43
|
+
...subject,
|
|
44
|
+
ts: nowIso(),
|
|
45
|
+
quality: "native",
|
|
46
|
+
kind: "quota_constraint",
|
|
47
|
+
constraint_id: constraint.id,
|
|
48
|
+
used_ratio: constraint.used_ratio,
|
|
49
|
+
window_seconds: constraint.window_seconds,
|
|
50
|
+
resets_at: constraint.resets_at,
|
|
51
|
+
cooldown_until: constraint.cooldown_until,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
36
55
|
const single = singleObservationFromEvent(harnessId, ev);
|
|
37
56
|
if (single)
|
|
38
|
-
out.push(single);
|
|
57
|
+
out.push({ ...single, ...subject });
|
|
39
58
|
return out;
|
|
40
59
|
}
|
|
41
60
|
function singleObservationFromEvent(harnessId, ev) {
|
|
42
61
|
if (ev.rate_limit) {
|
|
43
62
|
const resets = ev.rate_limit.resets_at ?? null;
|
|
44
63
|
const delay = ev.rate_limit.retry_delay_ms ?? null;
|
|
45
|
-
const cooldownUntil = resets ??
|
|
64
|
+
const cooldownUntil = resets ??
|
|
65
|
+
new Date(Date.now() + (typeof delay === "number" && delay > 0 ? delay : DEFAULT_COOLDOWN_MS)).toISOString();
|
|
46
66
|
return {
|
|
47
67
|
harness_id: harnessId,
|
|
48
68
|
ts: nowIso(),
|
package/dist/observe.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"observe.js","sourceRoot":"","sources":["../src/observe.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEzC,MAAM,mBAAmB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAE1C;;;;;;GAMG;AACH;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,SAAiB,EAAE,EAAgB;IACvE,MAAM,GAAG,GAAwB,EAAE,CAAC;IACpC,IAAI,EAAE,CAAC,IAAI,KAAK,OAAO,IAAI,OAAO,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,QAAQ,IAAI,EAAE,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,EAAE,CAAC;QAC3F,4EAA4E;QAC5E,qDAAqD;QACrD,MAAM,OAAO,GAAG,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC;QAC1D,GAAG,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"observe.js","sourceRoot":"","sources":["../src/observe.ts"],"names":[],"mappings":"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"}
|
package/dist/router.d.ts
CHANGED
|
@@ -1,22 +1,30 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { BillingKnowledge, CredentialRoute, EffortHint, Intent, PaidFallback, QualityTierSet, RoutingGoal } from "@claudexor/schema";
|
|
2
2
|
import type { BudgetLedger } from "./ledger.js";
|
|
3
3
|
export interface RouterCandidate {
|
|
4
4
|
harnessId: string;
|
|
5
|
-
providerFamily: ProviderFamily;
|
|
6
5
|
available: boolean;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
model?: string;
|
|
7
|
+
effort?: EffortHint;
|
|
8
|
+
billingKnowledge?: BillingKnowledge;
|
|
9
|
+
incrementalCostUsd?: number | null;
|
|
10
|
+
credentialRoute?: CredentialRoute;
|
|
11
|
+
/** Effective credential subject for quota filtering (release wave round-16
|
|
12
|
+
* #2): a profile id, null for the engine default, undefined when unknown
|
|
13
|
+
* (conservative any-subject matching). Profile A's cooldown must never
|
|
14
|
+
* exclude profile B or the default on the same harness+route. */
|
|
15
|
+
credentialSubjectId?: string | null;
|
|
12
16
|
}
|
|
13
17
|
export interface RouteContext {
|
|
14
|
-
|
|
18
|
+
goal: RoutingGoal;
|
|
19
|
+
paidFallback: PaidFallback;
|
|
20
|
+
intent: Intent;
|
|
21
|
+
qualityTiers: QualityTierSet;
|
|
15
22
|
ledger: BudgetLedger;
|
|
16
|
-
/** Provider families already used (penalized, to encourage cross-family diversity). */
|
|
17
|
-
diversityAgainst?: ProviderFamily[];
|
|
18
23
|
}
|
|
19
|
-
export declare
|
|
20
|
-
|
|
24
|
+
export declare class RoutingPreflightError extends Error {
|
|
25
|
+
readonly code = "routing_preflight_refused";
|
|
26
|
+
}
|
|
27
|
+
/** Order candidates transparently; lower tuple values win. Unknown quota remains eligible. */
|
|
28
|
+
export declare function rankHarnesses(candidates: RouterCandidate[], ctx: RouteContext): RouterCandidate[];
|
|
21
29
|
export declare function selectHarness(candidates: RouterCandidate[], ctx: RouteContext): RouterCandidate | null;
|
|
22
30
|
//# sourceMappingURL=router.d.ts.map
|
package/dist/router.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,UAAU,EACV,MAAM,EACN,YAAY,EACZ,cAAc,EACd,WAAW,EACZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC;;;qEAGiE;IACjE,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,WAAW,CAAC;IAClB,YAAY,EAAE,YAAY,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,cAAc,CAAC;IAC7B,MAAM,EAAE,YAAY,CAAC;CACtB;AAED,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,QAAQ,CAAC,IAAI,+BAA+B;CAC7C;AAqCD,8FAA8F;AAC9F,wBAAgB,aAAa,CAAC,UAAU,EAAE,eAAe,EAAE,EAAE,GAAG,EAAE,YAAY,GAAG,eAAe,EAAE,CAmCjG;AAED,wBAAgB,aAAa,CAC3B,UAAU,EAAE,eAAe,EAAE,EAC7B,GAAG,EAAE,YAAY,GAChB,eAAe,GAAG,IAAI,CAExB"}
|
package/dist/router.js
CHANGED
|
@@ -1,48 +1,56 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
case "cheapest":
|
|
4
|
-
return { quality: 0.5, cost: 2.0, latency: 1.0, preferSubscription: 1, preferApi: 1 };
|
|
5
|
-
case "strongest":
|
|
6
|
-
return { quality: 2.0, cost: 0.2, latency: 0.5, preferSubscription: 1, preferApi: 1 };
|
|
7
|
-
case "burn":
|
|
8
|
-
return { quality: 2.0, cost: 0.0, latency: 0.2, preferSubscription: 1, preferApi: 1 };
|
|
9
|
-
case "subscription-first":
|
|
10
|
-
return { quality: 1.0, cost: 0.5, latency: 0.5, preferSubscription: 1.6, preferApi: 0.6 };
|
|
11
|
-
case "api-overflow":
|
|
12
|
-
return { quality: 1.0, cost: 0.8, latency: 0.5, preferSubscription: 0.6, preferApi: 1.6 };
|
|
13
|
-
default:
|
|
14
|
-
return { quality: 1.0, cost: 0.7, latency: 0.5, preferSubscription: 1.1, preferApi: 1.0 };
|
|
15
|
-
}
|
|
1
|
+
export class RoutingPreflightError extends Error {
|
|
2
|
+
code = "routing_preflight_refused";
|
|
16
3
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const diversity = ctx.diversityAgainst?.includes(c.providerFamily) ? 0.5 : 1;
|
|
24
|
-
const authPref = c.authMode === "local_session" ? w.preferSubscription : c.authMode === "api_key" ? w.preferApi : 1;
|
|
25
|
-
const conserve = (ctx.portfolio === "conserve-claude" && c.providerFamily === "anthropic") ||
|
|
26
|
-
(ctx.portfolio === "conserve-codex" && c.providerFamily === "openai")
|
|
27
|
-
? 0.4
|
|
28
|
-
: 1;
|
|
29
|
-
const cost = Math.max(0.0001, c.costPerCall ?? 0.01);
|
|
30
|
-
const latency = Math.max(0.1, (c.latencyMs ?? 1000) / 1000);
|
|
31
|
-
const costFactor = cost ** w.cost;
|
|
32
|
-
const latencyFactor = latency ** w.latency;
|
|
33
|
-
return (quality * headroom * diversity * authPref * conserve) / (costFactor * latencyFactor);
|
|
4
|
+
function tierIndex(candidate, ctx) {
|
|
5
|
+
const tiers = ctx.qualityTiers[ctx.intent] ?? [];
|
|
6
|
+
const index = tiers.findIndex((tier) => tier.some((route) => route.harness === candidate.harnessId &&
|
|
7
|
+
route.model === candidate.model &&
|
|
8
|
+
route.effort === candidate.effort));
|
|
9
|
+
return index < 0 ? null : index;
|
|
34
10
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
11
|
+
function isIncrementalPaid(candidate) {
|
|
12
|
+
return !["proven_zero", "subscription_entitlement"].includes(candidate.billingKnowledge ?? "unknown");
|
|
13
|
+
}
|
|
14
|
+
function eligible(candidates, ctx) {
|
|
15
|
+
const ready = candidates.filter((candidate) => candidate.available &&
|
|
16
|
+
!ctx.ledger.cooldownActive(candidate.harnessId, candidate.credentialRoute, candidate.credentialSubjectId));
|
|
17
|
+
const free = ready.filter((candidate) => !isIncrementalPaid(candidate));
|
|
18
|
+
if (ctx.paidFallback === "never")
|
|
19
|
+
return free;
|
|
20
|
+
if (ctx.paidFallback === "when_unavailable" && free.length > 0)
|
|
21
|
+
return free;
|
|
22
|
+
return ready;
|
|
23
|
+
}
|
|
24
|
+
/** Order candidates transparently; lower tuple values win. Unknown quota remains eligible. */
|
|
25
|
+
export function rankHarnesses(candidates, ctx) {
|
|
26
|
+
const routes = eligible(candidates, ctx);
|
|
27
|
+
if (ctx.goal === "quality" && routes.every((candidate) => tierIndex(candidate, ctx) === null)) {
|
|
28
|
+
throw new RoutingPreflightError(`quality routing requires a comparable user-declared tier for intent '${ctx.intent}'`);
|
|
45
29
|
}
|
|
46
|
-
return
|
|
30
|
+
return routes.toSorted((a, b) => {
|
|
31
|
+
const aTier = tierIndex(a, ctx) ?? Number.MAX_SAFE_INTEGER;
|
|
32
|
+
const bTier = tierIndex(b, ctx) ?? Number.MAX_SAFE_INTEGER;
|
|
33
|
+
if (ctx.goal === "quality")
|
|
34
|
+
return aTier - bTier;
|
|
35
|
+
if (ctx.goal === "economy") {
|
|
36
|
+
const aPaid = isIncrementalPaid(a) ? 1 : 0;
|
|
37
|
+
const bPaid = isIncrementalPaid(b) ? 1 : 0;
|
|
38
|
+
const paidOrder = aPaid - bPaid;
|
|
39
|
+
if (paidOrder !== 0)
|
|
40
|
+
return paidOrder;
|
|
41
|
+
const aCost = a.incrementalCostUsd ?? Number.POSITIVE_INFINITY;
|
|
42
|
+
const bCost = b.incrementalCostUsd ?? Number.POSITIVE_INFINITY;
|
|
43
|
+
return aCost - bCost || aTier - bTier;
|
|
44
|
+
}
|
|
45
|
+
const aSlack = ctx.ledger.bindingPaceSlack(a.harnessId, a.credentialRoute, a.credentialSubjectId);
|
|
46
|
+
const bSlack = ctx.ledger.bindingPaceSlack(b.harnessId, b.credentialRoute, b.credentialSubjectId);
|
|
47
|
+
if (aSlack !== null || bSlack !== null) {
|
|
48
|
+
return (bSlack ?? Number.NEGATIVE_INFINITY) - (aSlack ?? Number.NEGATIVE_INFINITY);
|
|
49
|
+
}
|
|
50
|
+
return aTier - bTier;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
export function selectHarness(candidates, ctx) {
|
|
54
|
+
return rankHarnesses(candidates, ctx)[0] ?? null;
|
|
47
55
|
}
|
|
48
56
|
//# sourceMappingURL=router.js.map
|
package/dist/router.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.js","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@claudexor/budget",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "2.1.1",
|
|
4
4
|
"license": "MIT",
|
|
5
|
-
"description": "Budget governor: pre-call
|
|
5
|
+
"description": "Budget governor: pre-call leases, circuit breaker, evidence-based routing goals, and multi-window quota pacing.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./dist/index.js",
|
|
8
8
|
"types": "./dist/index.d.ts",
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
"dist"
|
|
17
17
|
],
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@claudexor/schema": "1.
|
|
20
|
-
"@claudexor/util": "1.
|
|
19
|
+
"@claudexor/schema": "2.1.1",
|
|
20
|
+
"@claudexor/util": "2.1.1"
|
|
21
21
|
},
|
|
22
22
|
"repository": {
|
|
23
23
|
"type": "git",
|