offrouter-core 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/audit.d.ts +51 -2
- package/dist/audit.d.ts.map +1 -1
- package/dist/audit.js +60 -3
- package/dist/audit.js.map +1 -1
- package/dist/config.d.ts +26 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +160 -1
- package/dist/config.js.map +1 -1
- package/dist/delegation.d.ts +40 -0
- package/dist/delegation.d.ts.map +1 -1
- package/dist/delegation.js +169 -8
- package/dist/delegation.js.map +1 -1
- package/dist/index.d.ts +27 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -7
- package/dist/index.js.map +1 -1
- package/dist/llm-judge.d.ts +41 -0
- package/dist/llm-judge.d.ts.map +1 -0
- package/dist/llm-judge.js +159 -0
- package/dist/llm-judge.js.map +1 -0
- package/dist/policy.d.ts +77 -0
- package/dist/policy.d.ts.map +1 -1
- package/dist/policy.js +81 -0
- package/dist/policy.js.map +1 -1
- package/dist/provider-health.d.ts +129 -0
- package/dist/provider-health.d.ts.map +1 -0
- package/dist/provider-health.js +423 -0
- package/dist/provider-health.js.map +1 -0
- package/dist/providers/catalog-data.d.ts +7 -0
- package/dist/providers/catalog-data.d.ts.map +1 -1
- package/dist/providers/catalog-data.js +140 -53
- package/dist/providers/catalog-data.js.map +1 -1
- package/dist/providers/catalog.d.ts +3 -3
- package/dist/providers/catalog.d.ts.map +1 -1
- package/dist/providers/catalog.js +1 -0
- package/dist/providers/catalog.js.map +1 -1
- package/dist/proxy/anthropic-mapper.d.ts +585 -0
- package/dist/proxy/anthropic-mapper.d.ts.map +1 -0
- package/dist/proxy/anthropic-mapper.js +539 -0
- package/dist/proxy/anthropic-mapper.js.map +1 -0
- package/dist/proxy/anthropic-server.d.ts +24 -0
- package/dist/proxy/anthropic-server.d.ts.map +1 -0
- package/dist/proxy/anthropic-server.js +606 -0
- package/dist/proxy/anthropic-server.js.map +1 -0
- package/dist/proxy/classify.d.ts +17 -0
- package/dist/proxy/classify.d.ts.map +1 -0
- package/dist/proxy/classify.js +65 -0
- package/dist/proxy/classify.js.map +1 -0
- package/dist/proxy/responses-mapper.d.ts +15 -0
- package/dist/proxy/responses-mapper.d.ts.map +1 -1
- package/dist/proxy/responses-mapper.js +9 -2
- package/dist/proxy/responses-mapper.js.map +1 -1
- package/dist/proxy/responses-server.d.ts.map +1 -1
- package/dist/proxy/responses-server.js +14 -1
- package/dist/proxy/responses-server.js.map +1 -1
- package/dist/router.d.ts +36 -2
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +158 -23
- package/dist/router.js.map +1 -1
- package/dist/schemas.d.ts +115 -34
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +35 -0
- package/dist/schemas.js.map +1 -1
- package/dist/secret-scan.d.ts +40 -0
- package/dist/secret-scan.d.ts.map +1 -0
- package/dist/secret-scan.js +125 -0
- package/dist/secret-scan.js.map +1 -0
- package/dist/secrets.d.ts +77 -6
- package/dist/secrets.d.ts.map +1 -1
- package/dist/secrets.js +356 -32
- package/dist/secrets.js.map +1 -1
- package/dist/spend.d.ts +122 -0
- package/dist/spend.d.ts.map +1 -0
- package/dist/spend.js +279 -0
- package/dist/spend.js.map +1 -0
- package/dist/task-classifier.d.ts +45 -0
- package/dist/task-classifier.d.ts.map +1 -0
- package/dist/task-classifier.js +153 -0
- package/dist/task-classifier.js.map +1 -0
- package/dist/types.d.ts +46 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/usage-file.d.ts +2 -6
- package/dist/usage-file.d.ts.map +1 -1
- package/dist/usage-file.js +64 -6
- package/dist/usage-file.js.map +1 -1
- package/dist/usage.d.ts +64 -10
- package/dist/usage.d.ts.map +1 -1
- package/dist/usage.js +79 -5
- package/dist/usage.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { chmod, mkdir, readFile, rename, unlink, writeFile } from "node:fs/promises";
|
|
2
|
+
/** Failures older than this window stop counting toward the score. */
|
|
3
|
+
export declare const FAILURE_DECAY_MS: number;
|
|
4
|
+
/** Baseline score for unknown / never-seen provider+model pairs. */
|
|
5
|
+
export declare const NEUTRAL_HEALTH_SCORE = 0;
|
|
6
|
+
/** Penalty applied per recent (non-decayed) failure. Dominates the score. */
|
|
7
|
+
export declare const FAILURE_PENALTY = 100;
|
|
8
|
+
/** Small bonus per recent success; capped so successes can't bury failures. */
|
|
9
|
+
export declare const SUCCESS_BONUS = 1;
|
|
10
|
+
/** Max successes counted toward the bonus (prevents long-run inflation). */
|
|
11
|
+
export declare const MAX_SUCCESS_BONUS_COUNT = 20;
|
|
12
|
+
/**
|
|
13
|
+
* EWMA smoothing factor for latency (0..1). Higher = more weight on the
|
|
14
|
+
* newest sample. 0.3 is a conservative default.
|
|
15
|
+
*/
|
|
16
|
+
export declare const LATENCY_EWMA_ALPHA = 0.3;
|
|
17
|
+
/**
|
|
18
|
+
* Latency tie-break coefficient. Subtracted as
|
|
19
|
+
* (ewmaLatencyMs / LATENCY_TIEBREAK_MS) * LATENCY_TIEBREAK_WEIGHT
|
|
20
|
+
* so a 1s difference moves the score by ~0.01 — never enough to override a
|
|
21
|
+
* failure penalty.
|
|
22
|
+
*/
|
|
23
|
+
export declare const LATENCY_TIEBREAK_MS = 1000;
|
|
24
|
+
export declare const LATENCY_TIEBREAK_WEIGHT = 0.01;
|
|
25
|
+
/** Successes older than this window stop contributing the success bonus. */
|
|
26
|
+
export declare const SUCCESS_DECAY_MS: number;
|
|
27
|
+
export interface OutcomeInput {
|
|
28
|
+
ok: boolean;
|
|
29
|
+
/** Observed end-to-end latency in milliseconds, when known. */
|
|
30
|
+
latencyMs?: number;
|
|
31
|
+
/** Override clock for tests. Defaults to Date.now(). */
|
|
32
|
+
at?: Date | number;
|
|
33
|
+
}
|
|
34
|
+
export interface ProviderModelHealth {
|
|
35
|
+
providerId: string;
|
|
36
|
+
modelId: string;
|
|
37
|
+
successCount: number;
|
|
38
|
+
failureCount: number;
|
|
39
|
+
/** Epoch ms of the most recent failure, if any. */
|
|
40
|
+
lastFailureAt?: number;
|
|
41
|
+
/** Epoch ms of the most recent success, if any. */
|
|
42
|
+
lastSuccessAt?: number;
|
|
43
|
+
/** Exponentially-weighted moving average of observed latency, ms. */
|
|
44
|
+
ewmaLatencyMs?: number;
|
|
45
|
+
/**
|
|
46
|
+
* Epoch-ms timestamps of recent failures still inside the decay window.
|
|
47
|
+
* Pruned lazily on read/score.
|
|
48
|
+
*/
|
|
49
|
+
recentFailureAts: number[];
|
|
50
|
+
/**
|
|
51
|
+
* Epoch-ms timestamps of recent successes still inside the decay window.
|
|
52
|
+
* Pruned lazily on read/score.
|
|
53
|
+
*/
|
|
54
|
+
recentSuccessAts: number[];
|
|
55
|
+
updatedAt: number;
|
|
56
|
+
}
|
|
57
|
+
/** Narrow surface the router/delegation depend on. */
|
|
58
|
+
export interface ProviderHealthTracker {
|
|
59
|
+
recordOutcome(providerId: string, modelId: string, outcome: OutcomeInput): void;
|
|
60
|
+
healthScore(providerId: string, modelId: string): number;
|
|
61
|
+
get(providerId: string, modelId: string): ProviderModelHealth | undefined;
|
|
62
|
+
/** Optional async flush for file-backed trackers. No-op in memory. */
|
|
63
|
+
flush?(): Promise<void>;
|
|
64
|
+
}
|
|
65
|
+
export interface InMemoryProviderHealthTrackerOptions {
|
|
66
|
+
now?: () => number;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Pure scoring function over a (possibly missing) health record.
|
|
70
|
+
* Exported for unit tests so they can pin the formula without a tracker.
|
|
71
|
+
*/
|
|
72
|
+
export declare function scoreHealthRecord(record: ProviderModelHealth | undefined, nowMs: number): number;
|
|
73
|
+
export declare class InMemoryProviderHealthTracker implements ProviderHealthTracker {
|
|
74
|
+
#private;
|
|
75
|
+
constructor(options?: InMemoryProviderHealthTrackerOptions);
|
|
76
|
+
recordOutcome(providerId: string, modelId: string, outcome: OutcomeInput): void;
|
|
77
|
+
healthScore(providerId: string, modelId: string): number;
|
|
78
|
+
get(providerId: string, modelId: string): ProviderModelHealth | undefined;
|
|
79
|
+
/** Snapshot of all known records (for persistence / tests). */
|
|
80
|
+
list(): ProviderModelHealth[];
|
|
81
|
+
/** Replace internal state (used by file-backed load). */
|
|
82
|
+
loadRecords(records: Iterable<ProviderModelHealth>): void;
|
|
83
|
+
toJSON(): Record<string, unknown>;
|
|
84
|
+
}
|
|
85
|
+
export interface FileProviderHealthTrackerFileSystem {
|
|
86
|
+
mkdir: typeof mkdir;
|
|
87
|
+
readFile: typeof readFile;
|
|
88
|
+
rename: typeof rename;
|
|
89
|
+
unlink: typeof unlink;
|
|
90
|
+
writeFile: typeof writeFile;
|
|
91
|
+
chmod: typeof chmod;
|
|
92
|
+
}
|
|
93
|
+
export interface FileProviderHealthTrackerOptions {
|
|
94
|
+
/** Absolute path (typically `$OFFROUTER_HOME/state/provider-health.json`). */
|
|
95
|
+
filePath: string;
|
|
96
|
+
fileSystem?: Partial<FileProviderHealthTrackerFileSystem>;
|
|
97
|
+
now?: () => number;
|
|
98
|
+
/** Flush to disk after every recordOutcome. Default true. */
|
|
99
|
+
autoSave?: boolean;
|
|
100
|
+
}
|
|
101
|
+
interface PersistedHealthDocument {
|
|
102
|
+
version: 1;
|
|
103
|
+
records: ProviderModelHealth[];
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Parse a persisted health document leniently. Missing/corrupt => empty.
|
|
107
|
+
*/
|
|
108
|
+
export declare function parseHealthDocument(raw: string): PersistedHealthDocument;
|
|
109
|
+
/**
|
|
110
|
+
* File-backed tracker. Mirrors FileUsageStore safety:
|
|
111
|
+
* - atomic write via temp + rename
|
|
112
|
+
* - chmod 0600 on POSIX
|
|
113
|
+
* - missing/corrupt file => empty state, never throws on load
|
|
114
|
+
*/
|
|
115
|
+
export declare class FileProviderHealthTracker implements ProviderHealthTracker {
|
|
116
|
+
#private;
|
|
117
|
+
readonly filePath: string;
|
|
118
|
+
constructor(options: FileProviderHealthTrackerOptions);
|
|
119
|
+
/** Load once. Never throws. */
|
|
120
|
+
load(): Promise<void>;
|
|
121
|
+
recordOutcome(providerId: string, modelId: string, outcome: OutcomeInput): void;
|
|
122
|
+
healthScore(providerId: string, modelId: string): number;
|
|
123
|
+
get(providerId: string, modelId: string): ProviderModelHealth | undefined;
|
|
124
|
+
flush(): Promise<void>;
|
|
125
|
+
/** Explicit save alias used by tests. */
|
|
126
|
+
save(): Promise<void>;
|
|
127
|
+
}
|
|
128
|
+
export {};
|
|
129
|
+
//# sourceMappingURL=provider-health.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-health.d.ts","sourceRoot":"","sources":["../src/provider-health.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recent-outcome health tracker for same-tier candidate re-ordering.
|
|
3
|
+
*
|
|
4
|
+
* Keeps a small per-(provider, model) record of successes, failures, and an
|
|
5
|
+
* EWMA of observed latency. Used by the router to stable-sort candidates
|
|
6
|
+
* *within* the same auth tier only — tier order is never crossed.
|
|
7
|
+
*
|
|
8
|
+
* Scoring (documented constants below):
|
|
9
|
+
* 1. Failures older than FAILURE_DECAY_MS stop counting (hard cut-off).
|
|
10
|
+
* 2. Each recent failure subtracts FAILURE_PENALTY from a neutral baseline.
|
|
11
|
+
* 3. Recent successes add SUCCESS_BONUS (capped) so a recovering provider
|
|
12
|
+
* climbs back above peers that are merely unknown.
|
|
13
|
+
* 4. EWMA latency is a tiny tie-break only (higher latency -> lower score).
|
|
14
|
+
*
|
|
15
|
+
* Unknown providers (never recorded) score NEUTRAL_HEALTH_SCORE — they are
|
|
16
|
+
* not penalized. That keeps brand-new candidates competitive.
|
|
17
|
+
*
|
|
18
|
+
* Persistence (optional): JSON file at `state/provider-health.json` following
|
|
19
|
+
* the FileUsageStore pattern (atomic write, 0600, corrupt => empty).
|
|
20
|
+
*/
|
|
21
|
+
import { readFileSync } from "node:fs";
|
|
22
|
+
import { chmod, mkdir, readFile, rename, unlink, writeFile, } from "node:fs/promises";
|
|
23
|
+
import { dirname } from "node:path";
|
|
24
|
+
import { randomBytes } from "node:crypto";
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
// Documented scoring constants (ponytail-style: named, not magic numbers)
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
/** Failures older than this window stop counting toward the score. */
|
|
29
|
+
export const FAILURE_DECAY_MS = 10 * 60 * 1000; // 10 minutes
|
|
30
|
+
/** Baseline score for unknown / never-seen provider+model pairs. */
|
|
31
|
+
export const NEUTRAL_HEALTH_SCORE = 0;
|
|
32
|
+
/** Penalty applied per recent (non-decayed) failure. Dominates the score. */
|
|
33
|
+
export const FAILURE_PENALTY = 100;
|
|
34
|
+
/** Small bonus per recent success; capped so successes can't bury failures. */
|
|
35
|
+
export const SUCCESS_BONUS = 1;
|
|
36
|
+
/** Max successes counted toward the bonus (prevents long-run inflation). */
|
|
37
|
+
export const MAX_SUCCESS_BONUS_COUNT = 20;
|
|
38
|
+
/**
|
|
39
|
+
* EWMA smoothing factor for latency (0..1). Higher = more weight on the
|
|
40
|
+
* newest sample. 0.3 is a conservative default.
|
|
41
|
+
*/
|
|
42
|
+
export const LATENCY_EWMA_ALPHA = 0.3;
|
|
43
|
+
/**
|
|
44
|
+
* Latency tie-break coefficient. Subtracted as
|
|
45
|
+
* (ewmaLatencyMs / LATENCY_TIEBREAK_MS) * LATENCY_TIEBREAK_WEIGHT
|
|
46
|
+
* so a 1s difference moves the score by ~0.01 — never enough to override a
|
|
47
|
+
* failure penalty.
|
|
48
|
+
*/
|
|
49
|
+
export const LATENCY_TIEBREAK_MS = 1000;
|
|
50
|
+
export const LATENCY_TIEBREAK_WEIGHT = 0.01;
|
|
51
|
+
/** Successes older than this window stop contributing the success bonus. */
|
|
52
|
+
export const SUCCESS_DECAY_MS = FAILURE_DECAY_MS;
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
// Scoring
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
function keyOf(providerId, modelId) {
|
|
57
|
+
return `${providerId}\0${modelId}`;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Pure scoring function over a (possibly missing) health record.
|
|
61
|
+
* Exported for unit tests so they can pin the formula without a tracker.
|
|
62
|
+
*/
|
|
63
|
+
export function scoreHealthRecord(record, nowMs) {
|
|
64
|
+
if (!record)
|
|
65
|
+
return NEUTRAL_HEALTH_SCORE;
|
|
66
|
+
const failureCutoff = nowMs - FAILURE_DECAY_MS;
|
|
67
|
+
const successCutoff = nowMs - SUCCESS_DECAY_MS;
|
|
68
|
+
const recentFailures = record.recentFailureAts.filter((t) => t >= failureCutoff).length;
|
|
69
|
+
const recentSuccesses = record.recentSuccessAts.filter((t) => t >= successCutoff).length;
|
|
70
|
+
// No observations currently in the window => treat as neutral:
|
|
71
|
+
// long-idle providers shouldn't keep a permanent rust penalty/bonus.
|
|
72
|
+
if (recentFailures === 0 && recentSuccesses === 0) {
|
|
73
|
+
// If we have never seen anything either, this is still neutral.
|
|
74
|
+
// Having historical totals outside the window also decays to neutral.
|
|
75
|
+
return NEUTRAL_HEALTH_SCORE;
|
|
76
|
+
}
|
|
77
|
+
const successBonus = Math.min(recentSuccesses, MAX_SUCCESS_BONUS_COUNT) * SUCCESS_BONUS;
|
|
78
|
+
const failurePenalty = recentFailures * FAILURE_PENALTY;
|
|
79
|
+
let latencyPenalty = 0;
|
|
80
|
+
if (record.ewmaLatencyMs !== undefined &&
|
|
81
|
+
Number.isFinite(record.ewmaLatencyMs) &&
|
|
82
|
+
record.ewmaLatencyMs > 0) {
|
|
83
|
+
latencyPenalty =
|
|
84
|
+
(record.ewmaLatencyMs / LATENCY_TIEBREAK_MS) * LATENCY_TIEBREAK_WEIGHT;
|
|
85
|
+
}
|
|
86
|
+
return NEUTRAL_HEALTH_SCORE + successBonus - failurePenalty - latencyPenalty;
|
|
87
|
+
}
|
|
88
|
+
// ---------------------------------------------------------------------------
|
|
89
|
+
// In-memory tracker
|
|
90
|
+
// ---------------------------------------------------------------------------
|
|
91
|
+
export class InMemoryProviderHealthTracker {
|
|
92
|
+
#records = new Map();
|
|
93
|
+
#now;
|
|
94
|
+
constructor(options = {}) {
|
|
95
|
+
this.#now = options.now ?? (() => Date.now());
|
|
96
|
+
}
|
|
97
|
+
recordOutcome(providerId, modelId, outcome) {
|
|
98
|
+
const atMs = toEpochMs(outcome.at) ?? this.#now();
|
|
99
|
+
const key = keyOf(providerId, modelId);
|
|
100
|
+
let record = this.#records.get(key);
|
|
101
|
+
if (!record) {
|
|
102
|
+
record = {
|
|
103
|
+
providerId,
|
|
104
|
+
modelId,
|
|
105
|
+
successCount: 0,
|
|
106
|
+
failureCount: 0,
|
|
107
|
+
recentFailureAts: [],
|
|
108
|
+
recentSuccessAts: [],
|
|
109
|
+
updatedAt: atMs,
|
|
110
|
+
};
|
|
111
|
+
this.#records.set(key, record);
|
|
112
|
+
}
|
|
113
|
+
this.#prune(record, atMs);
|
|
114
|
+
if (outcome.ok) {
|
|
115
|
+
record.successCount += 1;
|
|
116
|
+
record.lastSuccessAt = atMs;
|
|
117
|
+
record.recentSuccessAts.push(atMs);
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
record.failureCount += 1;
|
|
121
|
+
record.lastFailureAt = atMs;
|
|
122
|
+
record.recentFailureAts.push(atMs);
|
|
123
|
+
}
|
|
124
|
+
if (outcome.latencyMs !== undefined &&
|
|
125
|
+
Number.isFinite(outcome.latencyMs) &&
|
|
126
|
+
outcome.latencyMs >= 0) {
|
|
127
|
+
if (record.ewmaLatencyMs === undefined) {
|
|
128
|
+
record.ewmaLatencyMs = outcome.latencyMs;
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
record.ewmaLatencyMs =
|
|
132
|
+
LATENCY_EWMA_ALPHA * outcome.latencyMs +
|
|
133
|
+
(1 - LATENCY_EWMA_ALPHA) * record.ewmaLatencyMs;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
record.updatedAt = atMs;
|
|
137
|
+
}
|
|
138
|
+
healthScore(providerId, modelId) {
|
|
139
|
+
const nowMs = this.#now();
|
|
140
|
+
const record = this.#records.get(keyOf(providerId, modelId));
|
|
141
|
+
if (record)
|
|
142
|
+
this.#prune(record, nowMs);
|
|
143
|
+
return scoreHealthRecord(record, nowMs);
|
|
144
|
+
}
|
|
145
|
+
get(providerId, modelId) {
|
|
146
|
+
const record = this.#records.get(keyOf(providerId, modelId));
|
|
147
|
+
if (!record)
|
|
148
|
+
return undefined;
|
|
149
|
+
this.#prune(record, this.#now());
|
|
150
|
+
return cloneRecord(record);
|
|
151
|
+
}
|
|
152
|
+
/** Snapshot of all known records (for persistence / tests). */
|
|
153
|
+
list() {
|
|
154
|
+
const nowMs = this.#now();
|
|
155
|
+
const out = [];
|
|
156
|
+
for (const record of this.#records.values()) {
|
|
157
|
+
this.#prune(record, nowMs);
|
|
158
|
+
out.push(cloneRecord(record));
|
|
159
|
+
}
|
|
160
|
+
return out.sort((a, b) => {
|
|
161
|
+
if (a.providerId !== b.providerId) {
|
|
162
|
+
return a.providerId.localeCompare(b.providerId);
|
|
163
|
+
}
|
|
164
|
+
return a.modelId.localeCompare(b.modelId);
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
/** Replace internal state (used by file-backed load). */
|
|
168
|
+
loadRecords(records) {
|
|
169
|
+
this.#records.clear();
|
|
170
|
+
for (const raw of records) {
|
|
171
|
+
if (typeof raw.providerId !== "string" ||
|
|
172
|
+
typeof raw.modelId !== "string") {
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
const record = {
|
|
176
|
+
providerId: raw.providerId,
|
|
177
|
+
modelId: raw.modelId,
|
|
178
|
+
successCount: typeof raw.successCount === "number" ? raw.successCount : 0,
|
|
179
|
+
failureCount: typeof raw.failureCount === "number" ? raw.failureCount : 0,
|
|
180
|
+
lastFailureAt: typeof raw.lastFailureAt === "number" ? raw.lastFailureAt : undefined,
|
|
181
|
+
lastSuccessAt: typeof raw.lastSuccessAt === "number" ? raw.lastSuccessAt : undefined,
|
|
182
|
+
ewmaLatencyMs: typeof raw.ewmaLatencyMs === "number" ? raw.ewmaLatencyMs : undefined,
|
|
183
|
+
recentFailureAts: Array.isArray(raw.recentFailureAts)
|
|
184
|
+
? raw.recentFailureAts.filter((t) => typeof t === "number")
|
|
185
|
+
: [],
|
|
186
|
+
recentSuccessAts: Array.isArray(raw.recentSuccessAts)
|
|
187
|
+
? raw.recentSuccessAts.filter((t) => typeof t === "number")
|
|
188
|
+
: [],
|
|
189
|
+
updatedAt: typeof raw.updatedAt === "number" ? raw.updatedAt : 0,
|
|
190
|
+
};
|
|
191
|
+
this.#records.set(keyOf(record.providerId, record.modelId), record);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
toJSON() {
|
|
195
|
+
return {
|
|
196
|
+
kind: "in-memory-provider-health",
|
|
197
|
+
records: this.list(),
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
#prune(record, nowMs) {
|
|
201
|
+
const failureCutoff = nowMs - FAILURE_DECAY_MS;
|
|
202
|
+
const successCutoff = nowMs - SUCCESS_DECAY_MS;
|
|
203
|
+
record.recentFailureAts = record.recentFailureAts.filter((t) => t >= failureCutoff);
|
|
204
|
+
record.recentSuccessAts = record.recentSuccessAts.filter((t) => t >= successCutoff);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
const EMPTY_DOC = { version: 1, records: [] };
|
|
208
|
+
/**
|
|
209
|
+
* Parse a persisted health document leniently. Missing/corrupt => empty.
|
|
210
|
+
*/
|
|
211
|
+
export function parseHealthDocument(raw) {
|
|
212
|
+
let parsed;
|
|
213
|
+
try {
|
|
214
|
+
parsed = JSON.parse(raw);
|
|
215
|
+
}
|
|
216
|
+
catch {
|
|
217
|
+
return { ...EMPTY_DOC, records: [] };
|
|
218
|
+
}
|
|
219
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
220
|
+
return { ...EMPTY_DOC, records: [] };
|
|
221
|
+
}
|
|
222
|
+
const record = parsed;
|
|
223
|
+
const recordsRaw = record.records;
|
|
224
|
+
if (!Array.isArray(recordsRaw)) {
|
|
225
|
+
return { ...EMPTY_DOC, records: [] };
|
|
226
|
+
}
|
|
227
|
+
const records = [];
|
|
228
|
+
for (const value of recordsRaw) {
|
|
229
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
const entry = value;
|
|
233
|
+
if (typeof entry.providerId !== "string" ||
|
|
234
|
+
typeof entry.modelId !== "string") {
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
records.push({
|
|
238
|
+
providerId: entry.providerId,
|
|
239
|
+
modelId: entry.modelId,
|
|
240
|
+
successCount: typeof entry.successCount === "number" ? entry.successCount : 0,
|
|
241
|
+
failureCount: typeof entry.failureCount === "number" ? entry.failureCount : 0,
|
|
242
|
+
lastFailureAt: typeof entry.lastFailureAt === "number"
|
|
243
|
+
? entry.lastFailureAt
|
|
244
|
+
: undefined,
|
|
245
|
+
lastSuccessAt: typeof entry.lastSuccessAt === "number"
|
|
246
|
+
? entry.lastSuccessAt
|
|
247
|
+
: undefined,
|
|
248
|
+
ewmaLatencyMs: typeof entry.ewmaLatencyMs === "number"
|
|
249
|
+
? entry.ewmaLatencyMs
|
|
250
|
+
: undefined,
|
|
251
|
+
recentFailureAts: Array.isArray(entry.recentFailureAts)
|
|
252
|
+
? entry.recentFailureAts.filter((t) => typeof t === "number")
|
|
253
|
+
: [],
|
|
254
|
+
recentSuccessAts: Array.isArray(entry.recentSuccessAts)
|
|
255
|
+
? entry.recentSuccessAts.filter((t) => typeof t === "number")
|
|
256
|
+
: [],
|
|
257
|
+
updatedAt: typeof entry.updatedAt === "number" ? entry.updatedAt : 0,
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
return { version: 1, records };
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* File-backed tracker. Mirrors FileUsageStore safety:
|
|
264
|
+
* - atomic write via temp + rename
|
|
265
|
+
* - chmod 0600 on POSIX
|
|
266
|
+
* - missing/corrupt file => empty state, never throws on load
|
|
267
|
+
*/
|
|
268
|
+
export class FileProviderHealthTracker {
|
|
269
|
+
filePath;
|
|
270
|
+
#fs;
|
|
271
|
+
#delegate;
|
|
272
|
+
#autoSave;
|
|
273
|
+
#loaded = false;
|
|
274
|
+
#chain = Promise.resolve();
|
|
275
|
+
constructor(options) {
|
|
276
|
+
if (!options?.filePath || typeof options.filePath !== "string") {
|
|
277
|
+
throw new TypeError("FileProviderHealthTracker requires options.filePath");
|
|
278
|
+
}
|
|
279
|
+
this.filePath = options.filePath;
|
|
280
|
+
this.#delegate = new InMemoryProviderHealthTracker({ now: options.now });
|
|
281
|
+
this.#autoSave = options.autoSave !== false;
|
|
282
|
+
this.#fs = {
|
|
283
|
+
mkdir,
|
|
284
|
+
readFile,
|
|
285
|
+
rename,
|
|
286
|
+
unlink,
|
|
287
|
+
writeFile,
|
|
288
|
+
chmod,
|
|
289
|
+
...options.fileSystem,
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
#exclusive(fn) {
|
|
293
|
+
const run = this.#chain.then(fn, fn);
|
|
294
|
+
this.#chain = run.then(() => undefined, () => undefined);
|
|
295
|
+
return run;
|
|
296
|
+
}
|
|
297
|
+
/** Load once. Never throws. */
|
|
298
|
+
async load() {
|
|
299
|
+
if (this.#loaded)
|
|
300
|
+
return;
|
|
301
|
+
try {
|
|
302
|
+
const raw = await this.#fs.readFile(this.filePath, "utf8");
|
|
303
|
+
const doc = parseHealthDocument(raw);
|
|
304
|
+
this.#delegate.loadRecords(doc.records);
|
|
305
|
+
}
|
|
306
|
+
catch (err) {
|
|
307
|
+
if (err &&
|
|
308
|
+
typeof err === "object" &&
|
|
309
|
+
"code" in err &&
|
|
310
|
+
err.code === "ENOENT") {
|
|
311
|
+
// missing file => empty
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
// Any other read failure is treated as empty so a bad write can never
|
|
315
|
+
// wedge the CLI.
|
|
316
|
+
}
|
|
317
|
+
this.#delegate.loadRecords([]);
|
|
318
|
+
}
|
|
319
|
+
this.#loaded = true;
|
|
320
|
+
}
|
|
321
|
+
/** Synchronous load (used by healthScore/get before first async load). */
|
|
322
|
+
#loadSync() {
|
|
323
|
+
if (this.#loaded)
|
|
324
|
+
return;
|
|
325
|
+
try {
|
|
326
|
+
const raw = readFileSync(this.filePath, "utf8");
|
|
327
|
+
const doc = parseHealthDocument(raw);
|
|
328
|
+
this.#delegate.loadRecords(doc.records);
|
|
329
|
+
}
|
|
330
|
+
catch {
|
|
331
|
+
this.#delegate.loadRecords([]);
|
|
332
|
+
}
|
|
333
|
+
this.#loaded = true;
|
|
334
|
+
}
|
|
335
|
+
recordOutcome(providerId, modelId, outcome) {
|
|
336
|
+
this.#loadSync();
|
|
337
|
+
this.#delegate.recordOutcome(providerId, modelId, outcome);
|
|
338
|
+
if (this.#autoSave) {
|
|
339
|
+
// Fire-and-forget save serialized through the chain; errors swallowed so
|
|
340
|
+
// recording never breaks delegation.
|
|
341
|
+
void this.#exclusive(async () => {
|
|
342
|
+
try {
|
|
343
|
+
await this.#persist();
|
|
344
|
+
}
|
|
345
|
+
catch {
|
|
346
|
+
// non-fatal
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
healthScore(providerId, modelId) {
|
|
352
|
+
this.#loadSync();
|
|
353
|
+
return this.#delegate.healthScore(providerId, modelId);
|
|
354
|
+
}
|
|
355
|
+
get(providerId, modelId) {
|
|
356
|
+
this.#loadSync();
|
|
357
|
+
return this.#delegate.get(providerId, modelId);
|
|
358
|
+
}
|
|
359
|
+
async flush() {
|
|
360
|
+
this.#loadSync();
|
|
361
|
+
await this.#exclusive(async () => {
|
|
362
|
+
await this.#persist();
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
/** Explicit save alias used by tests. */
|
|
366
|
+
async save() {
|
|
367
|
+
await this.flush();
|
|
368
|
+
}
|
|
369
|
+
async #persist() {
|
|
370
|
+
const payload = `${JSON.stringify({
|
|
371
|
+
version: 1,
|
|
372
|
+
records: this.#delegate.list(),
|
|
373
|
+
}, null, 2)}\n`;
|
|
374
|
+
await this.#fs.mkdir(dirname(this.filePath), { recursive: true });
|
|
375
|
+
const tmp = `${this.filePath}.${randomBytes(8).toString("hex")}.tmp`;
|
|
376
|
+
try {
|
|
377
|
+
await this.#fs.writeFile(tmp, payload, {
|
|
378
|
+
encoding: "utf8",
|
|
379
|
+
mode: 0o600,
|
|
380
|
+
});
|
|
381
|
+
await this.#fs.chmod(tmp, 0o600);
|
|
382
|
+
await this.#fs.rename(tmp, this.filePath);
|
|
383
|
+
await this.#fs.chmod(this.filePath, 0o600);
|
|
384
|
+
}
|
|
385
|
+
catch (err) {
|
|
386
|
+
await this.#fs.unlink(tmp).catch((unlinkErr) => {
|
|
387
|
+
if (unlinkErr &&
|
|
388
|
+
typeof unlinkErr === "object" &&
|
|
389
|
+
"code" in unlinkErr &&
|
|
390
|
+
unlinkErr.code === "ENOENT") {
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
throw unlinkErr;
|
|
394
|
+
});
|
|
395
|
+
throw err;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
// ---------------------------------------------------------------------------
|
|
400
|
+
// Helpers
|
|
401
|
+
// ---------------------------------------------------------------------------
|
|
402
|
+
function toEpochMs(at) {
|
|
403
|
+
if (at === undefined)
|
|
404
|
+
return undefined;
|
|
405
|
+
if (typeof at === "number")
|
|
406
|
+
return at;
|
|
407
|
+
return at.getTime();
|
|
408
|
+
}
|
|
409
|
+
function cloneRecord(record) {
|
|
410
|
+
return {
|
|
411
|
+
providerId: record.providerId,
|
|
412
|
+
modelId: record.modelId,
|
|
413
|
+
successCount: record.successCount,
|
|
414
|
+
failureCount: record.failureCount,
|
|
415
|
+
lastFailureAt: record.lastFailureAt,
|
|
416
|
+
lastSuccessAt: record.lastSuccessAt,
|
|
417
|
+
ewmaLatencyMs: record.ewmaLatencyMs,
|
|
418
|
+
recentFailureAts: [...record.recentFailureAts],
|
|
419
|
+
recentSuccessAts: [...record.recentSuccessAts],
|
|
420
|
+
updatedAt: record.updatedAt,
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
//# sourceMappingURL=provider-health.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-health.js","sourceRoot":"","sources":["../src/provider-health.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
* by these OpenAI-compatible provider entries.
|
|
16
16
|
*/
|
|
17
17
|
import { z } from "zod";
|
|
18
|
+
import type { ConfiguredProvider } from "../config.js";
|
|
18
19
|
import type { AuthScope, AuthTier } from "../types.js";
|
|
19
20
|
import type { LogicalModelFamily } from "./catalog.js";
|
|
20
21
|
import type { OpenAiCompatibleFlavor } from "./openai-compatible.js";
|
|
@@ -108,6 +109,12 @@ export declare const BuiltinCatalogConfigSchema: z.ZodRecord<z.ZodString, z.ZodO
|
|
|
108
109
|
* Lets callers validate provider catalog overrides at runtime.
|
|
109
110
|
*/
|
|
110
111
|
export declare function parseBuiltinCatalogConfig(input: unknown): BuiltinCatalogConfig;
|
|
112
|
+
/**
|
|
113
|
+
* Derive a BuiltinCatalogConfig from the parsed user config providers map.
|
|
114
|
+
* Only `enabled` and `baseUrl` carry over; configured accounts are orthogonal
|
|
115
|
+
* to the static provider/model metadata.
|
|
116
|
+
*/
|
|
117
|
+
export declare function builtinCatalogConfigFromProviders(providers: Record<string, ConfiguredProvider>): BuiltinCatalogConfig;
|
|
111
118
|
/**
|
|
112
119
|
* Built-in providers. Subscription-backed first-party login happens through the
|
|
113
120
|
* harness adapters (claude/codex/gemini/grok), not these api endpoints, so each
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog-data.d.ts","sourceRoot":"","sources":["../../src/providers/catalog-data.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAErE,6EAA6E;AAC7E,MAAM,WAAW,WAAW;IAC1B,yDAAyD;IACzD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iEAAiE;IACjE,MAAM,EAAE,kBAAkB,CAAC;IAC3B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,wDAAwD;IACxD,OAAO,CAAC,EAAE,WAAW,CAAC;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,cAAc,EAAE,MAAM,CAAC;IACvB,qEAAqE;IACrE,MAAM,EAAE,sBAAsB,CAAC;IAC/B,iEAAiE;IACjE,eAAe,EAAE,QAAQ,CAAC;IAC1B,kEAAkE;IAClE,gBAAgB,EAAE,SAAS,CAAC;IAC5B;;;;OAIG;IACH,2BAA2B,EAAE,OAAO,CAAC;IACrC,oEAAoE;IACpE,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,WAAW,EAAE,SAAS,kBAAkB,EAAE,CAAC;CAC5C;AAED;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,yDAAyD;IACzD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,8CAA8C;IAC9C,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,mFAAmF;AACnF,MAAM,MAAM,oBAAoB,GAAG,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;AAazE,eAAO,MAAM,2BAA2B;;;;;;;;;EAE7B,CAAC;AAEZ,qDAAqD;AACrD,eAAO,MAAM,0BAA0B;;;;;;;;;GAGtC,CAAC;AAEF;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,OAAO,GACb,oBAAoB,CAEtB;
|
|
1
|
+
{"version":3,"file":"catalog-data.d.ts","sourceRoot":"","sources":["../../src/providers/catalog-data.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAErE,6EAA6E;AAC7E,MAAM,WAAW,WAAW;IAC1B,yDAAyD;IACzD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iEAAiE;IACjE,MAAM,EAAE,kBAAkB,CAAC;IAC3B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,wDAAwD;IACxD,OAAO,CAAC,EAAE,WAAW,CAAC;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,cAAc,EAAE,MAAM,CAAC;IACvB,qEAAqE;IACrE,MAAM,EAAE,sBAAsB,CAAC;IAC/B,iEAAiE;IACjE,eAAe,EAAE,QAAQ,CAAC;IAC1B,kEAAkE;IAClE,gBAAgB,EAAE,SAAS,CAAC;IAC5B;;;;OAIG;IACH,2BAA2B,EAAE,OAAO,CAAC;IACrC,oEAAoE;IACpE,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,WAAW,EAAE,SAAS,kBAAkB,EAAE,CAAC;CAC5C;AAED;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,yDAAyD;IACzD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,8CAA8C;IAC9C,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,mFAAmF;AACnF,MAAM,MAAM,oBAAoB,GAAG,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;AAazE,eAAO,MAAM,2BAA2B;;;;;;;;;EAE7B,CAAC;AAEZ,qDAAqD;AACrD,eAAO,MAAM,0BAA0B;;;;;;;;;GAGtC,CAAC;AAEF;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,OAAO,GACb,oBAAoB,CAEtB;AAED;;;;GAIG;AACH,wBAAgB,iCAAiC,CAC/C,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,GAC5C,oBAAoB,CAUtB;AASD;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,SAAS,oBAAoB,EA2Y5D,CAAC;AAEF,oDAAoD;AACpD,eAAO,MAAM,oBAAoB,EAAE,SAAS,MAAM,EAEjD,CAAC;AAEF,yCAAyC;AACzC,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,MAAM,GACjB,oBAAoB,GAAG,SAAS,CAElC;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,GAAE,oBAAyB,GAChC,oBAAoB,EAAE,CAgBxB"}
|