llm-relay 0.35.0 → 0.37.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/LICENSE +21 -0
- package/README.md +12 -0
- package/THIRD_PARTY_NOTICES.md +72 -0
- package/config.example.json +8 -2
- package/dist/accounting-store-io.d.ts +124 -0
- package/dist/accounting-store-io.js +1105 -0
- package/dist/accounting-store-io.js.map +1 -0
- package/dist/accounting-store-schema.d.ts +299 -0
- package/dist/accounting-store-schema.js +1021 -0
- package/dist/accounting-store-schema.js.map +1 -0
- package/dist/accounting-store.d.ts +73 -0
- package/dist/accounting-store.js +1523 -0
- package/dist/accounting-store.js.map +1 -0
- package/dist/accounting.d.ts +177 -0
- package/dist/accounting.js +429 -0
- package/dist/accounting.js.map +1 -0
- package/dist/anthropic.d.ts +2 -2
- package/dist/anthropic.js +22 -5
- package/dist/anthropic.js.map +1 -1
- package/dist/authEnv.d.ts +19 -0
- package/dist/authEnv.js +58 -25
- package/dist/authEnv.js.map +1 -1
- package/dist/backend.d.ts +32 -3
- package/dist/backend.js +324 -41
- package/dist/backend.js.map +1 -1
- package/dist/candidates.d.ts +28 -3
- package/dist/candidates.js +86 -13
- package/dist/candidates.js.map +1 -1
- package/dist/catalog.d.ts +1 -0
- package/dist/catalog.js +36 -12
- package/dist/catalog.js.map +1 -1
- package/dist/circuit-breaker.d.ts +49 -129
- package/dist/circuit-breaker.js +166 -223
- package/dist/circuit-breaker.js.map +1 -1
- package/dist/cli.d.ts +47 -15
- package/dist/cli.js +475 -134
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +23 -1
- package/dist/config.js +189 -19
- package/dist/config.js.map +1 -1
- package/dist/context-limits.js +2 -1
- package/dist/context-limits.js.map +1 -1
- package/dist/control-authorization.js +6 -4
- package/dist/control-authorization.js.map +1 -1
- package/dist/credential-fleet.d.ts +41 -0
- package/dist/credential-fleet.js +78 -0
- package/dist/credential-fleet.js.map +1 -0
- package/dist/credential-id.d.ts +13 -0
- package/dist/credential-id.js +22 -0
- package/dist/credential-id.js.map +1 -0
- package/dist/credential-select.d.ts +86 -0
- package/dist/credential-select.js +303 -0
- package/dist/credential-select.js.map +1 -0
- package/dist/dashboard/.vite/dashboard-bundle-graph.json +32 -0
- package/dist/dashboard/.vite/manifest.json +11 -0
- package/dist/dashboard/assets/index-BeZxN4Lx.css +1 -0
- package/dist/dashboard/assets/index-RtLgb7Cg.js +74 -0
- package/dist/dashboard/index.html +4 -0
- package/dist/dashboard-auth.d.ts +68 -0
- package/dist/dashboard-auth.js +225 -0
- package/dist/dashboard-auth.js.map +1 -0
- package/dist/dashboard-contract.d.ts +391 -0
- package/dist/dashboard-contract.js +619 -0
- package/dist/dashboard-contract.js.map +1 -0
- package/dist/dashboard-routes.d.ts +91 -0
- package/dist/dashboard-routes.js +688 -0
- package/dist/dashboard-routes.js.map +1 -0
- package/dist/dashboard-snapshot.d.ts +36 -0
- package/dist/dashboard-snapshot.js +1132 -0
- package/dist/dashboard-snapshot.js.map +1 -0
- package/dist/dashboard-static.d.ts +61 -0
- package/dist/dashboard-static.js +326 -0
- package/dist/dashboard-static.js.map +1 -0
- package/dist/dispatch.js +11 -6
- package/dist/dispatch.js.map +1 -1
- package/dist/dynamic-pools.js +6 -4
- package/dist/dynamic-pools.js.map +1 -1
- package/dist/kernel/contracts.d.ts +4 -0
- package/dist/kernel/request-lifecycle.js +4 -1
- package/dist/kernel/request-lifecycle.js.map +1 -1
- package/dist/key-checker.d.ts +3 -1
- package/dist/key-checker.js +35 -11
- package/dist/key-checker.js.map +1 -1
- package/dist/key-import.d.ts +29 -0
- package/dist/key-import.js +160 -0
- package/dist/key-import.js.map +1 -0
- package/dist/log.d.ts +20 -2
- package/dist/log.js +53 -2
- package/dist/log.js.map +1 -1
- package/dist/offload.d.ts +9 -0
- package/dist/offload.js +7 -1
- package/dist/offload.js.map +1 -1
- package/dist/onboarding.d.ts +3 -3
- package/dist/onboarding.js +12 -6
- package/dist/onboarding.js.map +1 -1
- package/dist/openai-dialect.d.ts +42 -0
- package/dist/openai-dialect.js +388 -0
- package/dist/openai-dialect.js.map +1 -0
- package/dist/ping/cadence.d.ts +12 -3
- package/dist/ping/cadence.js +68 -15
- package/dist/ping/cadence.js.map +1 -1
- package/dist/ping/ping.d.ts +7 -3
- package/dist/ping/ping.js +11 -35
- package/dist/ping/ping.js.map +1 -1
- package/dist/ping/probe-cache.d.ts +14 -6
- package/dist/ping/probe-cache.js +20 -5
- package/dist/ping/probe-cache.js.map +1 -1
- package/dist/ping/runtime-telemetry.d.ts +2 -1
- package/dist/ping/runtime-telemetry.js +103 -10
- package/dist/ping/runtime-telemetry.js.map +1 -1
- package/dist/pool-health.d.ts +2 -0
- package/dist/pool-health.js +29 -13
- package/dist/pool-health.js.map +1 -1
- package/dist/quota-observation.d.ts +29 -0
- package/dist/quota-observation.js +249 -0
- package/dist/quota-observation.js.map +1 -0
- package/dist/refusal-interpretation.d.ts +13 -7
- package/dist/refusal-interpretation.js +260 -33
- package/dist/refusal-interpretation.js.map +1 -1
- package/dist/registry.d.ts +13 -2
- package/dist/registry.js +12 -4
- package/dist/registry.js.map +1 -1
- package/dist/repair.d.ts +4 -2
- package/dist/repair.js +15 -1
- package/dist/repair.js.map +1 -1
- package/dist/request-log.d.ts +2 -2
- package/dist/request-log.js +9 -1
- package/dist/request-log.js.map +1 -1
- package/dist/reshaper.d.ts +76 -11
- package/dist/reshaper.js +264 -29
- package/dist/reshaper.js.map +1 -1
- package/dist/resolved-attempt.d.ts +14 -0
- package/dist/resolved-attempt.js +21 -0
- package/dist/resolved-attempt.js.map +1 -0
- package/dist/routes/admin.js +7 -1
- package/dist/routes/admin.js.map +1 -1
- package/dist/secret-file-acl.d.ts +25 -0
- package/dist/secret-file-acl.js +37 -0
- package/dist/secret-file-acl.js.map +1 -0
- package/dist/server.d.ts +28 -3
- package/dist/server.js +1774 -467
- package/dist/server.js.map +1 -1
- package/dist/session-pin.d.ts +35 -0
- package/dist/session-pin.js +136 -0
- package/dist/session-pin.js.map +1 -0
- package/dist/stream-commit.d.ts +34 -0
- package/dist/stream-commit.js +325 -0
- package/dist/stream-commit.js.map +1 -0
- package/dist/target-facts.d.ts +23 -136
- package/dist/target-facts.js +138 -179
- package/dist/target-facts.js.map +1 -1
- package/dist/telemetry.d.ts +1 -25
- package/dist/telemetry.js +52 -45
- package/dist/telemetry.js.map +1 -1
- package/dist/think-tags.d.ts +34 -0
- package/dist/think-tags.js +219 -0
- package/dist/think-tags.js.map +1 -0
- package/dist/usage-observer.d.ts +34 -0
- package/dist/usage-observer.js +322 -0
- package/dist/usage-observer.js.map +1 -0
- package/dist/winenv.js +26 -4
- package/dist/winenv.js.map +1 -1
- package/docs/dashboard-bundle-inventory.json +16 -0
- package/package.json +29 -6
- package/skills/llm-relay/SKILL.md +48 -9
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-pin.js","sourceRoot":"","sources":["../src/session-pin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Final-wire streamed response commit probe.
|
|
3
|
+
*
|
|
4
|
+
* A structurally valid SSE preamble is not yet an answer. Keep the downstream head provisional
|
|
5
|
+
* until the client-facing protocol carries meaningful assistant output, then replay every byte
|
|
6
|
+
* exactly as received. Before that point, an in-band error or an empty completion is safe to
|
|
7
|
+
* fail over because the client has observed nothing.
|
|
8
|
+
*/
|
|
9
|
+
export type StreamCommitProtocol = "anthropic-messages" | "openai-chat" | "openai-responses";
|
|
10
|
+
export type StreamCommitProbe = {
|
|
11
|
+
kind: "ready";
|
|
12
|
+
body: ReadableStream<Uint8Array>;
|
|
13
|
+
} | {
|
|
14
|
+
kind: "dead";
|
|
15
|
+
reason: string;
|
|
16
|
+
provenance: "upstream" | "local";
|
|
17
|
+
} | {
|
|
18
|
+
kind: "cancelled";
|
|
19
|
+
};
|
|
20
|
+
export interface StreamCommitProbeOptions {
|
|
21
|
+
/** Client cancellation wins races with EOF/read failures and must never start another target. */
|
|
22
|
+
isCancelled?: () => boolean;
|
|
23
|
+
/** Malformed final wire produced by a response mapper is a local defect, not target health. */
|
|
24
|
+
malformedProvenance?: "upstream" | "local";
|
|
25
|
+
/** A rejected body read is normally transport/upstream even when parsing is mapper-local. */
|
|
26
|
+
readFailureProvenance?: "upstream" | "local";
|
|
27
|
+
}
|
|
28
|
+
/** Shared by structural preflight and final-wire commit probing. */
|
|
29
|
+
export declare const STREAM_PREFLIGHT_LIMIT: number;
|
|
30
|
+
/**
|
|
31
|
+
* Read through metadata-only SSE events until the final wire contains meaningful assistant output.
|
|
32
|
+
* The returned stream replays the exact raw chunks and continues on the same locked reader.
|
|
33
|
+
*/
|
|
34
|
+
export declare function probeStreamForCommit(body: ReadableStream<Uint8Array>, protocol: StreamCommitProtocol, options?: StreamCommitProbeOptions): Promise<StreamCommitProbe>;
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Final-wire streamed response commit probe.
|
|
3
|
+
*
|
|
4
|
+
* A structurally valid SSE preamble is not yet an answer. Keep the downstream head provisional
|
|
5
|
+
* until the client-facing protocol carries meaningful assistant output, then replay every byte
|
|
6
|
+
* exactly as received. Before that point, an in-band error or an empty completion is safe to
|
|
7
|
+
* fail over because the client has observed nothing.
|
|
8
|
+
*/
|
|
9
|
+
/** Shared by structural preflight and final-wire commit probing. */
|
|
10
|
+
export const STREAM_PREFLIGHT_LIMIT = 64 * 1024;
|
|
11
|
+
const HOLD = { kind: "hold" };
|
|
12
|
+
const READY = { kind: "ready" };
|
|
13
|
+
function isRecord(value) {
|
|
14
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
15
|
+
}
|
|
16
|
+
function nonWhitespace(value) {
|
|
17
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
18
|
+
}
|
|
19
|
+
function substantive(value) {
|
|
20
|
+
if (nonWhitespace(value))
|
|
21
|
+
return true;
|
|
22
|
+
if (typeof value === "number" || typeof value === "boolean")
|
|
23
|
+
return true;
|
|
24
|
+
if (Array.isArray(value))
|
|
25
|
+
return value.some(substantive);
|
|
26
|
+
if (isRecord(value))
|
|
27
|
+
return Object.values(value).some(substantive);
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
function substantiveFields(value, ignored) {
|
|
31
|
+
return Object.entries(value).some(([key, field]) => !ignored.has(key) && substantive(field));
|
|
32
|
+
}
|
|
33
|
+
function boundedError(value) {
|
|
34
|
+
const error = isRecord(value.error) ? value.error : value;
|
|
35
|
+
const message = typeof error.message === "string" ? error.message.trim().slice(0, 200) : "";
|
|
36
|
+
return message ? `in-band error before meaningful content: ${message}` : "in-band error before meaningful content";
|
|
37
|
+
}
|
|
38
|
+
function anthropicVerdict(value) {
|
|
39
|
+
const type = typeof value.type === "string" ? value.type : "";
|
|
40
|
+
if (type === "error" || isRecord(value.error)) {
|
|
41
|
+
return { kind: "dead", reason: boundedError(value), provenance: "upstream" };
|
|
42
|
+
}
|
|
43
|
+
if (type === "message_stop") {
|
|
44
|
+
return { kind: "dead", reason: "stream completed without meaningful content", provenance: "upstream" };
|
|
45
|
+
}
|
|
46
|
+
if (type === "content_block_start") {
|
|
47
|
+
if (!isRecord(value.content_block))
|
|
48
|
+
return HOLD;
|
|
49
|
+
const block = value.content_block;
|
|
50
|
+
const blockType = typeof block.type === "string" ? block.type : "";
|
|
51
|
+
if (blockType === "tool_use") {
|
|
52
|
+
return nonWhitespace(block.id) || nonWhitespace(block.name) ? READY : HOLD;
|
|
53
|
+
}
|
|
54
|
+
if (blockType === "text")
|
|
55
|
+
return nonWhitespace(block.text) ? READY : HOLD;
|
|
56
|
+
if (blockType === "thinking")
|
|
57
|
+
return nonWhitespace(block.thinking) ? READY : HOLD;
|
|
58
|
+
// Redacted thinking and future opaque content blocks are output only when they carry an
|
|
59
|
+
// actual payload; a type/index skeleton remains provisional.
|
|
60
|
+
return substantiveFields(block, new Set(["type", "index"])) ? READY : HOLD;
|
|
61
|
+
}
|
|
62
|
+
if (type === "content_block_delta") {
|
|
63
|
+
if (!isRecord(value.delta))
|
|
64
|
+
return HOLD;
|
|
65
|
+
const delta = value.delta;
|
|
66
|
+
const deltaType = typeof delta.type === "string" ? delta.type : "";
|
|
67
|
+
if (deltaType === "text_delta")
|
|
68
|
+
return nonWhitespace(delta.text) ? READY : HOLD;
|
|
69
|
+
if (deltaType === "thinking_delta")
|
|
70
|
+
return nonWhitespace(delta.thinking) ? READY : HOLD;
|
|
71
|
+
// Tool arguments follow a meaningful tool_use start. Signatures are metadata, not content.
|
|
72
|
+
if (deltaType === "input_json_delta" || deltaType === "signature_delta")
|
|
73
|
+
return HOLD;
|
|
74
|
+
return substantiveFields(delta, new Set(["type", "index"])) ? READY : HOLD;
|
|
75
|
+
}
|
|
76
|
+
// Unknown future Anthropic content events are allowed to commit only when their content-shaped
|
|
77
|
+
// payload is substantive. Metadata-only event records stay held.
|
|
78
|
+
if (type.startsWith("content_block_")) {
|
|
79
|
+
if (isRecord(value.content_block) && substantiveFields(value.content_block, new Set(["type", "index"])))
|
|
80
|
+
return READY;
|
|
81
|
+
if (isRecord(value.delta) && substantiveFields(value.delta, new Set(["type", "index"])))
|
|
82
|
+
return READY;
|
|
83
|
+
}
|
|
84
|
+
return HOLD;
|
|
85
|
+
}
|
|
86
|
+
function chatToolCallMeaningful(value) {
|
|
87
|
+
if (!isRecord(value))
|
|
88
|
+
return false;
|
|
89
|
+
if (nonWhitespace(value.id))
|
|
90
|
+
return true;
|
|
91
|
+
if (!isRecord(value.function))
|
|
92
|
+
return false;
|
|
93
|
+
return nonWhitespace(value.function.name) || nonWhitespace(value.function.arguments);
|
|
94
|
+
}
|
|
95
|
+
function openAiChatVerdict(value) {
|
|
96
|
+
if (isRecord(value.error) || value.type === "error") {
|
|
97
|
+
return { kind: "dead", reason: boundedError(value), provenance: "upstream" };
|
|
98
|
+
}
|
|
99
|
+
if (!Array.isArray(value.choices)) {
|
|
100
|
+
return { kind: "dead", reason: "OpenAI stream event is missing choices", provenance: "upstream" };
|
|
101
|
+
}
|
|
102
|
+
if (value.choices.length === 0)
|
|
103
|
+
return HOLD; // usage-only frame
|
|
104
|
+
let finished = false;
|
|
105
|
+
for (const rawChoice of value.choices) {
|
|
106
|
+
if (!isRecord(rawChoice)) {
|
|
107
|
+
return { kind: "dead", reason: "OpenAI stream choice is not an object", provenance: "upstream" };
|
|
108
|
+
}
|
|
109
|
+
if (rawChoice.finish_reason !== null && rawChoice.finish_reason !== undefined)
|
|
110
|
+
finished = true;
|
|
111
|
+
if (!isRecord(rawChoice.delta))
|
|
112
|
+
continue;
|
|
113
|
+
const delta = rawChoice.delta;
|
|
114
|
+
if (nonWhitespace(delta.content) ||
|
|
115
|
+
nonWhitespace(delta.refusal) ||
|
|
116
|
+
nonWhitespace(delta.reasoning_content) ||
|
|
117
|
+
nonWhitespace(delta.reasoning))
|
|
118
|
+
return READY;
|
|
119
|
+
if (Array.isArray(delta.tool_calls) && delta.tool_calls.some(chatToolCallMeaningful))
|
|
120
|
+
return READY;
|
|
121
|
+
if (substantiveFields(delta, new Set(["role", "content", "refusal", "reasoning_content", "reasoning", "tool_calls"])))
|
|
122
|
+
return READY;
|
|
123
|
+
}
|
|
124
|
+
return finished
|
|
125
|
+
? { kind: "dead", reason: "stream completed without meaningful content", provenance: "upstream" }
|
|
126
|
+
: HOLD;
|
|
127
|
+
}
|
|
128
|
+
function responsesItemMeaningful(value) {
|
|
129
|
+
if (!isRecord(value))
|
|
130
|
+
return false;
|
|
131
|
+
const type = typeof value.type === "string" ? value.type : "";
|
|
132
|
+
if (type === "function_call") {
|
|
133
|
+
return nonWhitespace(value.id) || nonWhitespace(value.call_id) || nonWhitespace(value.name) || nonWhitespace(value.arguments);
|
|
134
|
+
}
|
|
135
|
+
if (type === "output_text" || type === "refusal" || type === "reasoning") {
|
|
136
|
+
return nonWhitespace(value.text) || nonWhitespace(value.refusal) || substantive(value.content);
|
|
137
|
+
}
|
|
138
|
+
if (type === "message" && Array.isArray(value.content))
|
|
139
|
+
return value.content.some(responsesItemMeaningful);
|
|
140
|
+
return substantiveFields(value, new Set(["type", "id", "status", "role", "index"]));
|
|
141
|
+
}
|
|
142
|
+
function openAiResponsesVerdict(value) {
|
|
143
|
+
const type = typeof value.type === "string" ? value.type : "";
|
|
144
|
+
if (type === "error" || type === "response.failed" || isRecord(value.error)) {
|
|
145
|
+
return { kind: "dead", reason: boundedError(value), provenance: "upstream" };
|
|
146
|
+
}
|
|
147
|
+
if (type === "response.incomplete" || type === "response.cancelled") {
|
|
148
|
+
return { kind: "dead", reason: `${type} before meaningful content`, provenance: "upstream" };
|
|
149
|
+
}
|
|
150
|
+
if (type === "response.output_text.delta" ||
|
|
151
|
+
type === "response.refusal.delta" ||
|
|
152
|
+
type === "response.reasoning.delta" ||
|
|
153
|
+
type === "response.reasoning_text.delta")
|
|
154
|
+
return nonWhitespace(value.delta) || nonWhitespace(value.text) ? READY : HOLD;
|
|
155
|
+
if (type === "response.function_call_arguments.delta")
|
|
156
|
+
return nonWhitespace(value.delta) ? READY : HOLD;
|
|
157
|
+
if (type === "response.output_item.added" || type === "response.output_item.done") {
|
|
158
|
+
return responsesItemMeaningful(value.item) ? READY : HOLD;
|
|
159
|
+
}
|
|
160
|
+
if (type === "response.content_part.added" || type === "response.content_part.done") {
|
|
161
|
+
return responsesItemMeaningful(value.part) ? READY : HOLD;
|
|
162
|
+
}
|
|
163
|
+
if (type === "response.completed") {
|
|
164
|
+
const response = isRecord(value.response) ? value.response : {};
|
|
165
|
+
if (response.status === "failed" || response.status === "incomplete" || response.status === "cancelled") {
|
|
166
|
+
return { kind: "dead", reason: "response completed unsuccessfully before meaningful content", provenance: "upstream" };
|
|
167
|
+
}
|
|
168
|
+
if (Array.isArray(response.output) && response.output.some(responsesItemMeaningful))
|
|
169
|
+
return READY;
|
|
170
|
+
return { kind: "dead", reason: "stream completed without meaningful content", provenance: "upstream" };
|
|
171
|
+
}
|
|
172
|
+
if (type.endsWith(".delta")) {
|
|
173
|
+
return substantiveFields(value, new Set(["type", "sequence_number", "output_index", "content_index", "item_id"]))
|
|
174
|
+
? READY
|
|
175
|
+
: HOLD;
|
|
176
|
+
}
|
|
177
|
+
if (type.endsWith(".done")) {
|
|
178
|
+
return nonWhitespace(value.text) || nonWhitespace(value.refusal) || responsesItemMeaningful(value.item) ? READY : HOLD;
|
|
179
|
+
}
|
|
180
|
+
return HOLD;
|
|
181
|
+
}
|
|
182
|
+
function classifyEvent(event, protocol, malformedProvenance) {
|
|
183
|
+
const lines = event.split(/\r?\n/);
|
|
184
|
+
const eventName = lines.find((line) => line.startsWith("event:"))?.slice(6).trim() ?? "";
|
|
185
|
+
const data = lines
|
|
186
|
+
.filter((line) => line.startsWith("data:"))
|
|
187
|
+
.map((line) => line.slice(5).replace(/^ /, ""))
|
|
188
|
+
.join("\n")
|
|
189
|
+
.trim();
|
|
190
|
+
if (!data)
|
|
191
|
+
return eventName === "error"
|
|
192
|
+
? { kind: "dead", reason: "in-band error before meaningful content", provenance: "upstream" }
|
|
193
|
+
: HOLD;
|
|
194
|
+
if (data === "[DONE]") {
|
|
195
|
+
return { kind: "dead", reason: "stream completed without meaningful content", provenance: "upstream" };
|
|
196
|
+
}
|
|
197
|
+
let parsed;
|
|
198
|
+
try {
|
|
199
|
+
parsed = JSON.parse(data);
|
|
200
|
+
}
|
|
201
|
+
catch {
|
|
202
|
+
return { kind: "dead", reason: "stream event before meaningful content is not valid JSON", provenance: malformedProvenance };
|
|
203
|
+
}
|
|
204
|
+
if (!isRecord(parsed)) {
|
|
205
|
+
return { kind: "dead", reason: "stream event before meaningful content is not an object", provenance: malformedProvenance };
|
|
206
|
+
}
|
|
207
|
+
if (eventName === "error" && parsed.type !== "error" && !isRecord(parsed.error)) {
|
|
208
|
+
return { kind: "dead", reason: boundedError(parsed), provenance: "upstream" };
|
|
209
|
+
}
|
|
210
|
+
switch (protocol) {
|
|
211
|
+
case "anthropic-messages": return anthropicVerdict(parsed);
|
|
212
|
+
case "openai-chat": return openAiChatVerdict(parsed);
|
|
213
|
+
case "openai-responses": return openAiResponsesVerdict(parsed);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
function firstBoundary(value) {
|
|
217
|
+
const match = /\r?\n\r?\n/.exec(value);
|
|
218
|
+
return match ? { index: match.index, length: match[0].length } : null;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Read through metadata-only SSE events until the final wire contains meaningful assistant output.
|
|
222
|
+
* The returned stream replays the exact raw chunks and continues on the same locked reader.
|
|
223
|
+
*/
|
|
224
|
+
export async function probeStreamForCommit(body, protocol, options = {}) {
|
|
225
|
+
const reader = body.getReader();
|
|
226
|
+
const chunks = [];
|
|
227
|
+
const decoder = new TextDecoder();
|
|
228
|
+
const malformedProvenance = options.malformedProvenance ?? "upstream";
|
|
229
|
+
const readFailureProvenance = options.readFailureProvenance ?? "upstream";
|
|
230
|
+
let buffered = "";
|
|
231
|
+
let inspectedBytes = 0;
|
|
232
|
+
const isCancelled = () => options.isCancelled?.() ?? false;
|
|
233
|
+
const cancelled = async () => {
|
|
234
|
+
await reader.cancel("client disconnected before stream commit").catch(() => { });
|
|
235
|
+
return { kind: "cancelled" };
|
|
236
|
+
};
|
|
237
|
+
const dead = async (reason, provenance = "upstream") => {
|
|
238
|
+
if (isCancelled())
|
|
239
|
+
return cancelled();
|
|
240
|
+
await reader.cancel(reason).catch(() => { });
|
|
241
|
+
return { kind: "dead", reason, provenance };
|
|
242
|
+
};
|
|
243
|
+
const ready = () => {
|
|
244
|
+
let prefixIndex = 0;
|
|
245
|
+
return {
|
|
246
|
+
kind: "ready",
|
|
247
|
+
body: new ReadableStream({
|
|
248
|
+
async pull(controller) {
|
|
249
|
+
if (prefixIndex < chunks.length) {
|
|
250
|
+
controller.enqueue(chunks[prefixIndex++]);
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
try {
|
|
254
|
+
const next = await reader.read();
|
|
255
|
+
if (next.done)
|
|
256
|
+
controller.close();
|
|
257
|
+
else
|
|
258
|
+
controller.enqueue(next.value);
|
|
259
|
+
}
|
|
260
|
+
catch (error) {
|
|
261
|
+
controller.error(error);
|
|
262
|
+
}
|
|
263
|
+
},
|
|
264
|
+
async cancel(reason) {
|
|
265
|
+
await reader.cancel(reason).catch(() => { });
|
|
266
|
+
},
|
|
267
|
+
}),
|
|
268
|
+
};
|
|
269
|
+
};
|
|
270
|
+
const inspectCompleteEvents = (final = false) => {
|
|
271
|
+
while (true) {
|
|
272
|
+
const boundary = firstBoundary(buffered);
|
|
273
|
+
if (!boundary)
|
|
274
|
+
break;
|
|
275
|
+
const event = buffered.slice(0, boundary.index);
|
|
276
|
+
buffered = buffered.slice(boundary.index + boundary.length);
|
|
277
|
+
const verdict = classifyEvent(event, protocol, malformedProvenance);
|
|
278
|
+
if (verdict.kind !== "hold")
|
|
279
|
+
return verdict;
|
|
280
|
+
}
|
|
281
|
+
if (final && buffered.trim().length > 0) {
|
|
282
|
+
const event = buffered;
|
|
283
|
+
buffered = "";
|
|
284
|
+
return classifyEvent(event, protocol, malformedProvenance);
|
|
285
|
+
}
|
|
286
|
+
return HOLD;
|
|
287
|
+
};
|
|
288
|
+
while (inspectedBytes < STREAM_PREFLIGHT_LIMIT) {
|
|
289
|
+
let next;
|
|
290
|
+
try {
|
|
291
|
+
next = await reader.read();
|
|
292
|
+
}
|
|
293
|
+
catch {
|
|
294
|
+
if (isCancelled())
|
|
295
|
+
return cancelled();
|
|
296
|
+
return dead("stream failed before meaningful content", readFailureProvenance);
|
|
297
|
+
}
|
|
298
|
+
if (isCancelled())
|
|
299
|
+
return cancelled();
|
|
300
|
+
if (next.done) {
|
|
301
|
+
buffered += decoder.decode();
|
|
302
|
+
const verdict = inspectCompleteEvents(true);
|
|
303
|
+
if (verdict.kind === "ready")
|
|
304
|
+
return ready();
|
|
305
|
+
if (verdict.kind === "dead")
|
|
306
|
+
return dead(verdict.reason, verdict.provenance);
|
|
307
|
+
return dead("stream ended before meaningful content");
|
|
308
|
+
}
|
|
309
|
+
chunks.push(next.value);
|
|
310
|
+
const remaining = STREAM_PREFLIGHT_LIMIT - inspectedBytes;
|
|
311
|
+
const inspectBytes = next.value.byteLength > remaining ? next.value.subarray(0, remaining) : next.value;
|
|
312
|
+
inspectedBytes += inspectBytes.byteLength;
|
|
313
|
+
buffered += decoder.decode(inspectBytes, { stream: true });
|
|
314
|
+
const verdict = inspectCompleteEvents();
|
|
315
|
+
if (verdict.kind === "ready")
|
|
316
|
+
return isCancelled() ? cancelled() : ready();
|
|
317
|
+
if (verdict.kind === "dead")
|
|
318
|
+
return dead(verdict.reason, verdict.provenance);
|
|
319
|
+
if (next.value.byteLength > inspectBytes.byteLength) {
|
|
320
|
+
return dead("no meaningful content within commit probe limit");
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
return dead("no meaningful content within commit probe limit");
|
|
324
|
+
}
|
|
325
|
+
//# sourceMappingURL=stream-commit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream-commit.js","sourceRoot":"","sources":["../src/stream-commit.ts"],"names":[],"mappings":"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"}
|
package/dist/target-facts.d.ts
CHANGED
|
@@ -1,86 +1,28 @@
|
|
|
1
|
+
import { type CredentialId } from "./credential-id.js";
|
|
2
|
+
/** A learned condition or measurement about a routing target. */
|
|
3
|
+
export type FactKind = "not-servable" | "subscription-required" | "allowance-exhausted" | "credential-invalid" | "rate-limited" | "context-limit";
|
|
1
4
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* The problem this exists to stop recurring: a fact's natural scope and its storage keying kept
|
|
5
|
-
* drifting apart, independently, in every store that learned something. Measured 2026-08-08:
|
|
6
|
-
*
|
|
7
|
-
* - a HuggingFace credit balance is stated per ACCOUNT, and was being rediscovered once per
|
|
8
|
-
* model — six pool members, six round-trips, six expiries, to learn one number;
|
|
9
|
-
* - a revoked key is a fact about the CREDENTIAL, and `credentialFaultUntil` is keyed per
|
|
10
|
-
* deployment, so every model on that provider must independently discover the same 401;
|
|
11
|
-
* - an account-level 429 is the same shape again.
|
|
12
|
-
*
|
|
13
|
-
* Each was a separate patch waiting to be written. So scope is now part of the fact rather than a
|
|
14
|
-
* property of whichever module happened to record it, and every lookup resolves MOST SPECIFIC
|
|
15
|
-
* FIRST with its provenance attached — the shape `metadata.ts` already uses for limits and prices
|
|
16
|
-
* (serving provider's own figure → another provider's figure for the same id → null).
|
|
17
|
-
*
|
|
18
|
-
* ⚠ **Scope comes from EVIDENCE, never from inference.** "Three models on this provider returned
|
|
19
|
-
* 401" is not proof the key is bad — it is equally three gated models under a working credential,
|
|
20
|
-
* which is the false accusation `key-checker.ts` exists to avoid. A provider-scoped fact requires
|
|
21
|
-
* something that *states* an account-level condition; when a situation is ambiguous it goes to the
|
|
22
|
-
* offline review tier in `refusal-interpretation.ts` and binds only once accepted. Nothing here
|
|
23
|
-
* promotes a fact by counting failures.
|
|
24
|
-
*/
|
|
25
|
-
/**
|
|
26
|
-
* What was learned. Deliberately one enum across fact kinds, because the consequence of a fact is
|
|
27
|
-
* a property of the fact and not of the store it came from.
|
|
28
|
-
*
|
|
29
|
-
* ⚠ `allowance-exhausted` is TEMPORAL, not a cost verdict — a free lane that has spent this
|
|
30
|
-
* period's credits is the normal state of a working free lane. It demotes and expires; it must
|
|
31
|
-
* never evict anything from a free pool, or the eviction outlives the exhaustion. `isCostBlocked`
|
|
32
|
-
* is the enforcement of that and deliberately cannot see it.
|
|
33
|
-
*/
|
|
34
|
-
export type FactKind =
|
|
35
|
-
/** The deployment does not exist (404/400 "does not exist", "not found for account"). */
|
|
36
|
-
"not-servable"
|
|
37
|
-
/** It exists, but is not covered by the plan we hold (403 naming a subscription). */
|
|
38
|
-
| "subscription-required"
|
|
39
|
-
/** Free, and spent until the allowance refreshes (402 naming a credit balance). */
|
|
40
|
-
| "allowance-exhausted"
|
|
41
|
-
/** The credential itself is rejected — stated, e.g. "invalid api key". NOT inferred from 401s. */
|
|
42
|
-
| "credential-invalid"
|
|
43
|
-
/**
|
|
44
|
-
* Rate limited at a scope the response STATED — "your account has exceeded its rate limit".
|
|
45
|
-
*
|
|
46
|
-
* ⚠ This is not where ordinary 429s go. A bare 429 is one deployment's back-pressure and belongs
|
|
47
|
-
* to the breaker's per-target cooldown, which already handles it well. This kind exists only for
|
|
48
|
-
* the case the breaker cannot express: a limit the provider says belongs to the ACCOUNT, where
|
|
49
|
-
* every sibling is equally throttled and discovering that once per model is the waste.
|
|
50
|
-
*/
|
|
51
|
-
| "rate-limited"
|
|
52
|
-
/**
|
|
53
|
-
* The context ceiling a deployment STATED when it refused an over-length request, in tokens.
|
|
54
|
-
*
|
|
55
|
-
* ⚠ A MEASUREMENT, not a condition — and the distinction is load-bearing. Every other kind here
|
|
56
|
-
* describes something that is currently true and stops being true: a success disproves it. A
|
|
57
|
-
* context window is a property of the deployment, so a successful request says nothing about it
|
|
58
|
-
* and must not clear it. See `CONDITIONS` below.
|
|
59
|
-
*/
|
|
60
|
-
| "context-limit";
|
|
61
|
-
/**
|
|
62
|
-
* Who a fact applies to, specific → general. Resolution walks this order and stops at the first
|
|
63
|
-
* live hit, so a deployment's own verdict always beats its provider's.
|
|
64
|
-
*
|
|
65
|
-
* deployment — this (provider, model) alone.
|
|
66
|
-
* group — an explicit set of models on one provider. ⚠ The membership travels WITH the
|
|
67
|
-
* fact rather than being inferred from id prefixes: prefix matching is the
|
|
68
|
-
* heuristic `authEnv.ts` refuses, and one bad match evicts a working family. A
|
|
69
|
-
* group verdict is reviewed with its member list visible before it binds.
|
|
70
|
-
* provider — every deployment behind that credential. Balances, revoked keys, account rate
|
|
71
|
-
* limits. This is the scope that turns N discoveries into one.
|
|
72
|
-
* model — the same model id wherever it is served. Reference-grade only, and never used for
|
|
73
|
-
* cost or availability: the same id on two providers is two deployments with
|
|
74
|
-
* different ceilings, prices and entitlements (see `metadata.ts`).
|
|
5
|
+
* The evidence scope, in lookup order. `provider` deliberately means every credential for the
|
|
6
|
+
* provider; credential-wide evidence must use `credential` instead.
|
|
75
7
|
*/
|
|
76
8
|
export type FactScope = {
|
|
77
|
-
kind: "
|
|
9
|
+
kind: "attempt";
|
|
78
10
|
provider: string;
|
|
11
|
+
credentialId: CredentialId;
|
|
79
12
|
model: string;
|
|
80
13
|
} | {
|
|
81
14
|
kind: "group";
|
|
82
15
|
provider: string;
|
|
16
|
+
credentialId?: CredentialId;
|
|
83
17
|
members: string[];
|
|
18
|
+
} | {
|
|
19
|
+
kind: "deployment";
|
|
20
|
+
provider: string;
|
|
21
|
+
model: string;
|
|
22
|
+
} | {
|
|
23
|
+
kind: "credential";
|
|
24
|
+
provider: string;
|
|
25
|
+
credentialId: CredentialId;
|
|
84
26
|
} | {
|
|
85
27
|
kind: "provider";
|
|
86
28
|
provider: string;
|
|
@@ -88,45 +30,18 @@ export type FactScope = {
|
|
|
88
30
|
kind: "model";
|
|
89
31
|
model: string;
|
|
90
32
|
};
|
|
91
|
-
/** Scope names in resolution order. Exported so callers cannot invent a different precedence. */
|
|
92
33
|
export declare const SCOPE_PRECEDENCE: Array<FactScope["kind"]>;
|
|
93
|
-
/**
|
|
94
|
-
* How long each kind is believed without re-checking. All expire, because all are reversible: a
|
|
95
|
-
* de-listed model returns, a plan is upgraded, an allowance refreshes, a key is rotated.
|
|
96
|
-
*
|
|
97
|
-
* `allowance-exhausted` is deliberately the SHORTEST despite monthly credit cycles — cooling a
|
|
98
|
-
* whole provider for a month on one 402 would be catastrophic if the balance were topped up an
|
|
99
|
-
* hour later, and one re-probe an hour is cheap and self-correcting. It also matches the breaker's
|
|
100
|
-
* `QUOTA_EXHAUSTED_COOLDOWN_MS`, so the two cannot disagree about when to try again.
|
|
101
|
-
* `credential-invalid` is short for the same reason from the other direction: a rotated key must
|
|
102
|
-
* recover quickly, and any success clears it outright.
|
|
103
|
-
*/
|
|
104
34
|
export declare const FACT_TTL_MS: Record<FactKind, number>;
|
|
105
|
-
/**
|
|
106
|
-
* Every fact kind, for callers that must enumerate them (the review CLI's `--class` validation).
|
|
107
|
-
*
|
|
108
|
-
* Derived from `FACT_TTL_MS`, which is a `Record<FactKind, …>` and therefore exhaustive by
|
|
109
|
-
* compiler enforcement — so this list cannot fall behind the type. A hand-maintained copy already
|
|
110
|
-
* did: `rate-limited` existed in the store while the CLI rejected it, which made the review
|
|
111
|
-
* command unusable for the one kind it had just gained.
|
|
112
|
-
*/
|
|
113
35
|
export declare const FACT_KINDS: FactKind[];
|
|
114
|
-
/**
|
|
115
|
-
|
|
116
|
-
*
|
|
117
|
-
* A fresh observation replaces an older one at the SAME scope: the target is the authority on
|
|
118
|
-
* itself, and one that changed its answer is telling us so. Facts at different scopes coexist —
|
|
119
|
-
* a deployment can be `subscription-required` while its provider is `allowance-exhausted`, and
|
|
120
|
-
* resolution decides which applies.
|
|
121
|
-
*/
|
|
36
|
+
/** Canonical persisted key. Kept exported so persistence tests cannot duplicate it. */
|
|
37
|
+
export declare function keyOf(scope: FactScope): string;
|
|
122
38
|
export declare function recordFact(kind: FactKind, scope: FactScope, opts?: {
|
|
123
39
|
path?: string;
|
|
124
40
|
now?: number;
|
|
125
41
|
retryAfterMs?: number | null;
|
|
126
42
|
value?: number;
|
|
127
43
|
}): void;
|
|
128
|
-
|
|
129
|
-
export declare function factsFor(provider: string, model: string | null | undefined, opts?: {
|
|
44
|
+
export declare function factsFor(provider: string, credentialId: CredentialId | null, model: string | null | undefined, opts?: {
|
|
130
45
|
path?: string;
|
|
131
46
|
now?: number;
|
|
132
47
|
}): Array<{
|
|
@@ -135,43 +50,18 @@ export declare function factsFor(provider: string, model: string | null | undefi
|
|
|
135
50
|
until: number;
|
|
136
51
|
value?: number;
|
|
137
52
|
}>;
|
|
138
|
-
|
|
139
|
-
* Has this deployment been PROVEN unfit for a free pool?
|
|
140
|
-
*
|
|
141
|
-
* ⚠ True only for facts in `COST_BLOCKING`. `allowance-exhausted` is deliberately excluded and
|
|
142
|
-
* must stay excluded — see the `FactKind` note. `credential-invalid` is excluded too: a bad key is
|
|
143
|
-
* a configuration problem, not a statement that the deployment costs money, and removing members
|
|
144
|
-
* from a pool over it would empty the pool on a mistake that a rotation fixes in seconds.
|
|
145
|
-
*/
|
|
146
|
-
export declare function isCostBlocked(provider: string, model: string | null | undefined, opts?: {
|
|
53
|
+
export declare function isCostBlocked(provider: string, credentialId: CredentialId | null, model: string | null | undefined, opts?: {
|
|
147
54
|
path?: string;
|
|
148
55
|
now?: number;
|
|
149
56
|
}): boolean;
|
|
150
|
-
|
|
151
|
-
* When a temporarily-unusable target is worth trying again, or null when nothing is cooling it.
|
|
152
|
-
* Only `COOLING` kinds produce this — the others are exclusions, not cooldowns, and a caller that
|
|
153
|
-
* wants those wants `isCostBlocked`.
|
|
154
|
-
*/
|
|
155
|
-
export declare function cooldownUntil(provider: string, model: string | null | undefined, opts?: {
|
|
57
|
+
export declare function cooldownUntil(provider: string, credentialId: CredentialId | null, model: string | null | undefined, opts?: {
|
|
156
58
|
path?: string;
|
|
157
59
|
now?: number;
|
|
158
60
|
}): number | null;
|
|
159
|
-
/**
|
|
160
|
-
|
|
161
|
-
*
|
|
162
|
-
* A served request is first-party proof that the deployment exists, the credential authenticates,
|
|
163
|
-
* and the allowance is not spent. That is strictly better evidence than any stored refusal, and it
|
|
164
|
-
* covers the cases that matter most: credits topped up, a key rotated, a month rolled over, all
|
|
165
|
-
* well before the TTL would have expired. Same contract as the breaker clearing a credential fault
|
|
166
|
-
* on success.
|
|
167
|
-
*
|
|
168
|
-
* ⚠ A group fact is cleared only if this model is IN the group — one member serving says nothing
|
|
169
|
-
* about the others, and dropping the whole verdict would re-admit models that are genuinely gated.
|
|
170
|
-
*/
|
|
171
|
-
export declare function clearFacts(provider: string, model: string | null | undefined, opts?: {
|
|
61
|
+
/** A success retracts conditions covering this credential/model cell, never measurements. */
|
|
62
|
+
export declare function clearFacts(provider: string, credentialId: CredentialId | null, model: string | null | undefined, opts?: {
|
|
172
63
|
path?: string;
|
|
173
64
|
}): FactKind[];
|
|
174
|
-
/** Every live fact, for `llm-relay eligibility`. Expired entries are omitted, not reported. */
|
|
175
65
|
export declare function allFacts(opts?: {
|
|
176
66
|
path?: string;
|
|
177
67
|
now?: number;
|
|
@@ -181,11 +71,8 @@ export declare function allFacts(opts?: {
|
|
|
181
71
|
at: number;
|
|
182
72
|
until: number;
|
|
183
73
|
}>;
|
|
184
|
-
/** A human-readable label for a scope — used by the CLI and by nothing that makes decisions. */
|
|
185
74
|
export declare function describeScope(scope: FactScope): string;
|
|
186
|
-
/** Flush pending writes. Called on shutdown, like the other write-behind stores. */
|
|
187
75
|
export declare function flushFacts(opts?: {
|
|
188
76
|
path?: string;
|
|
189
77
|
}): void;
|
|
190
|
-
/** Test seam: drop the in-memory store so a suite can point at a fresh path. */
|
|
191
78
|
export declare function resetFacts(): void;
|