@warmdrift/kgauto-compiler 2.0.0-alpha.32 → 2.0.0-alpha.34
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/{chunk-WXCFWUCN.mjs → chunk-XJZRDGHF.mjs} +11 -6
- package/dist/glassbox/index.d.mts +3 -3
- package/dist/glassbox/index.d.ts +3 -3
- package/dist/glassbox-routes/index.d.mts +2 -2
- package/dist/glassbox-routes/index.d.ts +2 -2
- package/dist/glassbox-routes/index.js +11 -6
- package/dist/glassbox-routes/index.mjs +1 -1
- package/dist/index.d.mts +95 -3
- package/dist/index.d.ts +95 -3
- package/dist/index.js +410 -25
- package/dist/index.mjs +399 -20
- package/dist/{ir-De2AQtlr.d.mts → ir-BAAHLfFL.d.mts} +118 -1
- package/dist/{ir-BIAT9gJk.d.ts → ir-B_ygNURd.d.ts} +118 -1
- package/dist/profiles.d.mts +1 -1
- package/dist/profiles.d.ts +1 -1
- package/dist/{types-BjrIFPGe.d.mts → types-BoqPXoUb.d.mts} +1 -1
- package/dist/{types-D_JAhCv4.d.ts → types-CXyKj6-K.d.ts} +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
isProviderReachable,
|
|
33
33
|
loadChainsFromBrain,
|
|
34
34
|
resolveProviderKey
|
|
35
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-XJZRDGHF.mjs";
|
|
36
36
|
import {
|
|
37
37
|
ALIASES,
|
|
38
38
|
_setProfileBrainHook,
|
|
@@ -1197,6 +1197,9 @@ function compile(ir, opts = {}) {
|
|
|
1197
1197
|
const handle = makeHandle();
|
|
1198
1198
|
const finalShape = computeShape(workingIR, inputTokens);
|
|
1199
1199
|
const _learningKey = learningKey(ir.intent.archetype, profile.id, finalShape);
|
|
1200
|
+
const historyCacheMarkIndex = computeHistoryCacheMarkIndex(workingIR);
|
|
1201
|
+
const systemMessages = buildSystemMessages(workingIR, profile.provider);
|
|
1202
|
+
const systemCacheMarkIndex = lastCacheableSystemIndex(systemMessages);
|
|
1200
1203
|
const diagnostics = {
|
|
1201
1204
|
sectionsKept: workingIR.sections.length,
|
|
1202
1205
|
sectionsDropped: ir.sections.length - workingIR.sections.length,
|
|
@@ -1210,7 +1213,10 @@ function compile(ir, opts = {}) {
|
|
|
1210
1213
|
historyTokensTotal: compressed.historyTokensTotal,
|
|
1211
1214
|
// alpha.20 E3: mirror the consumer's declared mode for Glass-Box +
|
|
1212
1215
|
// brain observability. Undefined when not declared (pre-alpha.20).
|
|
1213
|
-
toolOrchestration: ir.constraints?.toolOrchestration
|
|
1216
|
+
toolOrchestration: ir.constraints?.toolOrchestration,
|
|
1217
|
+
// alpha.33 — see top-of-block comment.
|
|
1218
|
+
historyCacheMarkIndex,
|
|
1219
|
+
systemCacheMarkIndex
|
|
1214
1220
|
};
|
|
1215
1221
|
if (ir.intent.archetype === "hunt" && ir.constraints?.toolOrchestration === "sequential") {
|
|
1216
1222
|
accumulatedMutations.push({
|
|
@@ -1260,9 +1266,45 @@ function compile(ir, opts = {}) {
|
|
|
1260
1266
|
advisories,
|
|
1261
1267
|
diagnostics,
|
|
1262
1268
|
sectionRewritesApplied,
|
|
1263
|
-
wireOverrides
|
|
1269
|
+
wireOverrides,
|
|
1270
|
+
systemMessages
|
|
1264
1271
|
};
|
|
1265
1272
|
}
|
|
1273
|
+
function computeHistoryCacheMarkIndex(ir) {
|
|
1274
|
+
const policy = ir.historyCachePolicy;
|
|
1275
|
+
if (!policy || policy.strategy === "none") return void 0;
|
|
1276
|
+
const historyLen = ir.history?.length ?? 0;
|
|
1277
|
+
if (historyLen === 0) return void 0;
|
|
1278
|
+
if (policy.strategy === "all-but-latest") {
|
|
1279
|
+
return historyLen - 1;
|
|
1280
|
+
}
|
|
1281
|
+
if (policy.strategy === "fixed-suffix") {
|
|
1282
|
+
const idx = historyLen - 1 - policy.suffix;
|
|
1283
|
+
if (idx < 0) return void 0;
|
|
1284
|
+
return idx;
|
|
1285
|
+
}
|
|
1286
|
+
return void 0;
|
|
1287
|
+
}
|
|
1288
|
+
function buildSystemMessages(ir, provider) {
|
|
1289
|
+
const sections = ir.sections;
|
|
1290
|
+
if (!sections || sections.length === 0) return [];
|
|
1291
|
+
return sections.map((s) => {
|
|
1292
|
+
const base = { role: "system", content: s.text };
|
|
1293
|
+
if (provider === "anthropic" && s.cacheable) {
|
|
1294
|
+
base.providerOptions = { anthropic: { cacheControl: { type: "ephemeral" } } };
|
|
1295
|
+
}
|
|
1296
|
+
return base;
|
|
1297
|
+
});
|
|
1298
|
+
}
|
|
1299
|
+
function lastCacheableSystemIndex(systemMessages) {
|
|
1300
|
+
for (let i = systemMessages.length - 1; i >= 0; i--) {
|
|
1301
|
+
const entry = systemMessages[i];
|
|
1302
|
+
if (entry && entry.providerOptions?.anthropic?.cacheControl) {
|
|
1303
|
+
return i;
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
return void 0;
|
|
1307
|
+
}
|
|
1266
1308
|
function validateIR(ir) {
|
|
1267
1309
|
if (!ir.appId) throw new Error("compile(): ir.appId is required");
|
|
1268
1310
|
if (!ir.intent || !ir.intent.archetype) {
|
|
@@ -1683,8 +1725,295 @@ var CallError = class extends Error {
|
|
|
1683
1725
|
}
|
|
1684
1726
|
};
|
|
1685
1727
|
|
|
1686
|
-
// src/
|
|
1728
|
+
// src/streaming.ts
|
|
1687
1729
|
var ANTHROPIC_URL = "https://api.anthropic.com/v1/messages";
|
|
1730
|
+
async function streamAnthropic(request, apiKey, opts) {
|
|
1731
|
+
const { provider: _provider, ...body } = request;
|
|
1732
|
+
const fetchFn = opts.fetchImpl ?? fetch;
|
|
1733
|
+
let res;
|
|
1734
|
+
try {
|
|
1735
|
+
res = await fetchFn(ANTHROPIC_URL, {
|
|
1736
|
+
method: "POST",
|
|
1737
|
+
headers: {
|
|
1738
|
+
"x-api-key": apiKey,
|
|
1739
|
+
"anthropic-version": "2023-06-01",
|
|
1740
|
+
"content-type": "application/json"
|
|
1741
|
+
},
|
|
1742
|
+
body: JSON.stringify({ ...body, stream: true })
|
|
1743
|
+
});
|
|
1744
|
+
} catch (err) {
|
|
1745
|
+
return retryableError(0, "network_error", String(err), null);
|
|
1746
|
+
}
|
|
1747
|
+
if (!res.ok) {
|
|
1748
|
+
const errBody = await res.json().catch(() => ({}));
|
|
1749
|
+
return classifyHttpError(res.status, errBody);
|
|
1750
|
+
}
|
|
1751
|
+
let text = "";
|
|
1752
|
+
let inputTokens = 0;
|
|
1753
|
+
let outputTokens = 0;
|
|
1754
|
+
let cacheReadTokens;
|
|
1755
|
+
let cacheCreatedTokens;
|
|
1756
|
+
let stopReason;
|
|
1757
|
+
const toolBlocks = /* @__PURE__ */ new Map();
|
|
1758
|
+
try {
|
|
1759
|
+
await parseSSEStream(res, (event) => {
|
|
1760
|
+
if (!event.data) return;
|
|
1761
|
+
let payload;
|
|
1762
|
+
try {
|
|
1763
|
+
payload = JSON.parse(event.data);
|
|
1764
|
+
} catch {
|
|
1765
|
+
return;
|
|
1766
|
+
}
|
|
1767
|
+
const type = payload.type;
|
|
1768
|
+
if (type === "message_start") {
|
|
1769
|
+
const msg = payload.message;
|
|
1770
|
+
const usage = msg?.usage;
|
|
1771
|
+
if (usage) {
|
|
1772
|
+
inputTokens = usage.input_tokens ?? 0;
|
|
1773
|
+
outputTokens = usage.output_tokens ?? 0;
|
|
1774
|
+
if (typeof usage.cache_read_input_tokens === "number")
|
|
1775
|
+
cacheReadTokens = usage.cache_read_input_tokens;
|
|
1776
|
+
if (typeof usage.cache_creation_input_tokens === "number")
|
|
1777
|
+
cacheCreatedTokens = usage.cache_creation_input_tokens;
|
|
1778
|
+
}
|
|
1779
|
+
return;
|
|
1780
|
+
}
|
|
1781
|
+
if (type === "content_block_start") {
|
|
1782
|
+
const p = payload;
|
|
1783
|
+
const idx = p.index ?? 0;
|
|
1784
|
+
const block = p.content_block;
|
|
1785
|
+
if (block?.type === "tool_use" && block.id && block.name) {
|
|
1786
|
+
toolBlocks.set(idx, { id: block.id, name: block.name, argsJson: "" });
|
|
1787
|
+
}
|
|
1788
|
+
return;
|
|
1789
|
+
}
|
|
1790
|
+
if (type === "content_block_delta") {
|
|
1791
|
+
const p = payload;
|
|
1792
|
+
const delta = p.delta;
|
|
1793
|
+
if (!delta) return;
|
|
1794
|
+
if (delta.type === "text_delta" && typeof delta.text === "string") {
|
|
1795
|
+
text += delta.text;
|
|
1796
|
+
opts.onChunk(delta.text);
|
|
1797
|
+
} else if (delta.type === "input_json_delta" && typeof delta.partial_json === "string") {
|
|
1798
|
+
const idx = p.index ?? 0;
|
|
1799
|
+
const tool = toolBlocks.get(idx);
|
|
1800
|
+
if (tool) tool.argsJson += delta.partial_json;
|
|
1801
|
+
}
|
|
1802
|
+
return;
|
|
1803
|
+
}
|
|
1804
|
+
if (type === "message_delta") {
|
|
1805
|
+
const p = payload;
|
|
1806
|
+
if (p.delta?.stop_reason) stopReason = p.delta.stop_reason;
|
|
1807
|
+
if (typeof p.usage?.output_tokens === "number") outputTokens = p.usage.output_tokens;
|
|
1808
|
+
return;
|
|
1809
|
+
}
|
|
1810
|
+
});
|
|
1811
|
+
} catch (err) {
|
|
1812
|
+
return retryableError(0, "stream_interrupted", String(err), null);
|
|
1813
|
+
}
|
|
1814
|
+
const toolCalls = Array.from(toolBlocks.values()).map((b) => ({
|
|
1815
|
+
id: b.id,
|
|
1816
|
+
name: b.name,
|
|
1817
|
+
args: tryParseJson(b.argsJson) ?? {}
|
|
1818
|
+
}));
|
|
1819
|
+
const tokens = {
|
|
1820
|
+
input: inputTokens,
|
|
1821
|
+
output: outputTokens,
|
|
1822
|
+
total: inputTokens + outputTokens,
|
|
1823
|
+
cached: cacheReadTokens,
|
|
1824
|
+
cacheCreated: cacheCreatedTokens
|
|
1825
|
+
};
|
|
1826
|
+
const response = {
|
|
1827
|
+
text,
|
|
1828
|
+
structuredOutput: null,
|
|
1829
|
+
toolCalls,
|
|
1830
|
+
tokens,
|
|
1831
|
+
finishReason: stopReason,
|
|
1832
|
+
raw: { streamed: true, provider: "anthropic" }
|
|
1833
|
+
};
|
|
1834
|
+
return { ok: true, status: res.status, response };
|
|
1835
|
+
}
|
|
1836
|
+
async function streamOpenAILike(url, request, apiKey, providerLabel, opts) {
|
|
1837
|
+
const { provider: _provider, ...body } = request;
|
|
1838
|
+
const fetchFn = opts.fetchImpl ?? fetch;
|
|
1839
|
+
const reqBody = {
|
|
1840
|
+
...body,
|
|
1841
|
+
stream: true,
|
|
1842
|
+
stream_options: {
|
|
1843
|
+
...body.stream_options ?? {},
|
|
1844
|
+
include_usage: true
|
|
1845
|
+
}
|
|
1846
|
+
};
|
|
1847
|
+
let res;
|
|
1848
|
+
try {
|
|
1849
|
+
res = await fetchFn(url, {
|
|
1850
|
+
method: "POST",
|
|
1851
|
+
headers: {
|
|
1852
|
+
authorization: `Bearer ${apiKey}`,
|
|
1853
|
+
"content-type": "application/json"
|
|
1854
|
+
},
|
|
1855
|
+
body: JSON.stringify(reqBody)
|
|
1856
|
+
});
|
|
1857
|
+
} catch (err) {
|
|
1858
|
+
return retryableError(0, "network_error", String(err), null);
|
|
1859
|
+
}
|
|
1860
|
+
if (!res.ok) {
|
|
1861
|
+
const errBody = await res.json().catch(() => ({}));
|
|
1862
|
+
return classifyHttpError(res.status, errBody);
|
|
1863
|
+
}
|
|
1864
|
+
let text = "";
|
|
1865
|
+
let finishReason;
|
|
1866
|
+
let inputTokens = 0;
|
|
1867
|
+
let outputTokens = 0;
|
|
1868
|
+
let totalTokens;
|
|
1869
|
+
let cachedTokens;
|
|
1870
|
+
const toolBuffers = /* @__PURE__ */ new Map();
|
|
1871
|
+
try {
|
|
1872
|
+
await parseSSEStream(res, (event) => {
|
|
1873
|
+
if (!event.data) return;
|
|
1874
|
+
if (event.data === "[DONE]") return;
|
|
1875
|
+
let payload;
|
|
1876
|
+
try {
|
|
1877
|
+
payload = JSON.parse(event.data);
|
|
1878
|
+
} catch {
|
|
1879
|
+
return;
|
|
1880
|
+
}
|
|
1881
|
+
const choices = payload.choices;
|
|
1882
|
+
if (choices && choices.length > 0) {
|
|
1883
|
+
const choice = choices[0];
|
|
1884
|
+
const deltaContent = choice.delta?.content;
|
|
1885
|
+
if (typeof deltaContent === "string" && deltaContent.length > 0) {
|
|
1886
|
+
text += deltaContent;
|
|
1887
|
+
opts.onChunk(deltaContent);
|
|
1888
|
+
}
|
|
1889
|
+
const toolDeltas = choice.delta?.tool_calls;
|
|
1890
|
+
if (toolDeltas) {
|
|
1891
|
+
for (const tcDelta of toolDeltas) {
|
|
1892
|
+
const idx = tcDelta.index ?? 0;
|
|
1893
|
+
let buf = toolBuffers.get(idx);
|
|
1894
|
+
if (!buf) {
|
|
1895
|
+
buf = { id: tcDelta.id ?? `tc-${idx}`, name: "", argsJson: "" };
|
|
1896
|
+
toolBuffers.set(idx, buf);
|
|
1897
|
+
}
|
|
1898
|
+
if (tcDelta.id) buf.id = tcDelta.id;
|
|
1899
|
+
if (tcDelta.function?.name) buf.name += tcDelta.function.name;
|
|
1900
|
+
if (tcDelta.function?.arguments) buf.argsJson += tcDelta.function.arguments;
|
|
1901
|
+
}
|
|
1902
|
+
}
|
|
1903
|
+
if (choice.finish_reason) finishReason = choice.finish_reason;
|
|
1904
|
+
}
|
|
1905
|
+
const usage = payload.usage;
|
|
1906
|
+
if (usage) {
|
|
1907
|
+
if (typeof usage.prompt_tokens === "number") inputTokens = usage.prompt_tokens;
|
|
1908
|
+
if (typeof usage.completion_tokens === "number") outputTokens = usage.completion_tokens;
|
|
1909
|
+
if (typeof usage.total_tokens === "number") totalTokens = usage.total_tokens;
|
|
1910
|
+
const details = usage.prompt_tokens_details;
|
|
1911
|
+
if (typeof details?.cached_tokens === "number") cachedTokens = details.cached_tokens;
|
|
1912
|
+
}
|
|
1913
|
+
});
|
|
1914
|
+
} catch (err) {
|
|
1915
|
+
return retryableError(0, "stream_interrupted", String(err), null);
|
|
1916
|
+
}
|
|
1917
|
+
const toolCalls = Array.from(toolBuffers.values()).filter((b) => b.name.length > 0).map((b) => ({
|
|
1918
|
+
id: b.id,
|
|
1919
|
+
name: b.name,
|
|
1920
|
+
args: tryParseJson(b.argsJson) ?? {}
|
|
1921
|
+
}));
|
|
1922
|
+
const tokens = {
|
|
1923
|
+
input: inputTokens,
|
|
1924
|
+
output: outputTokens,
|
|
1925
|
+
total: totalTokens ?? inputTokens + outputTokens,
|
|
1926
|
+
cached: cachedTokens
|
|
1927
|
+
};
|
|
1928
|
+
const response = {
|
|
1929
|
+
text,
|
|
1930
|
+
structuredOutput: null,
|
|
1931
|
+
toolCalls,
|
|
1932
|
+
tokens,
|
|
1933
|
+
finishReason,
|
|
1934
|
+
raw: { streamed: true, provider: providerLabel }
|
|
1935
|
+
};
|
|
1936
|
+
return { ok: true, status: res.status, response };
|
|
1937
|
+
}
|
|
1938
|
+
async function parseSSEStream(response, handler) {
|
|
1939
|
+
const body = response.body;
|
|
1940
|
+
if (!body) throw new Error("Response has no body for SSE parse");
|
|
1941
|
+
const reader = body.getReader();
|
|
1942
|
+
const decoder = new TextDecoder("utf-8");
|
|
1943
|
+
let buffer = "";
|
|
1944
|
+
for (; ; ) {
|
|
1945
|
+
const { value, done } = await reader.read();
|
|
1946
|
+
if (done) break;
|
|
1947
|
+
buffer += decoder.decode(value, { stream: true });
|
|
1948
|
+
let sep;
|
|
1949
|
+
while (sep = buffer.indexOf("\n\n"), sep !== -1) {
|
|
1950
|
+
const block = buffer.slice(0, sep);
|
|
1951
|
+
buffer = buffer.slice(sep + 2);
|
|
1952
|
+
const event = parseSSEBlock(block);
|
|
1953
|
+
if (event) handler(event);
|
|
1954
|
+
}
|
|
1955
|
+
}
|
|
1956
|
+
if (buffer.length > 0) {
|
|
1957
|
+
const event = parseSSEBlock(buffer);
|
|
1958
|
+
if (event) handler(event);
|
|
1959
|
+
}
|
|
1960
|
+
}
|
|
1961
|
+
function parseSSEBlock(block) {
|
|
1962
|
+
const lines = block.split(/\r?\n/);
|
|
1963
|
+
let eventName;
|
|
1964
|
+
const dataLines = [];
|
|
1965
|
+
for (const line of lines) {
|
|
1966
|
+
if (line.startsWith(":")) continue;
|
|
1967
|
+
if (line.startsWith("event:")) {
|
|
1968
|
+
eventName = line.slice(6).trim();
|
|
1969
|
+
} else if (line.startsWith("data:")) {
|
|
1970
|
+
dataLines.push(line.slice(5).trim());
|
|
1971
|
+
}
|
|
1972
|
+
}
|
|
1973
|
+
if (dataLines.length === 0) return void 0;
|
|
1974
|
+
return { event: eventName, data: dataLines.join("\n") };
|
|
1975
|
+
}
|
|
1976
|
+
function tryParseJson(s) {
|
|
1977
|
+
if (typeof s !== "string" || s.length === 0) return void 0;
|
|
1978
|
+
try {
|
|
1979
|
+
const parsed = JSON.parse(s);
|
|
1980
|
+
return typeof parsed === "object" && parsed !== null ? parsed : void 0;
|
|
1981
|
+
} catch {
|
|
1982
|
+
return void 0;
|
|
1983
|
+
}
|
|
1984
|
+
}
|
|
1985
|
+
function classifyHttpError(status, body) {
|
|
1986
|
+
const message = extractErrorMessage(body) ?? `HTTP ${status}`;
|
|
1987
|
+
if (status === 429)
|
|
1988
|
+
return { ok: false, status, errorType: "retryable", errorCode: "rate_limit", message, raw: body };
|
|
1989
|
+
if (status === 408)
|
|
1990
|
+
return { ok: false, status, errorType: "retryable", errorCode: "timeout", message, raw: body };
|
|
1991
|
+
if (status >= 500)
|
|
1992
|
+
return { ok: false, status, errorType: "retryable", errorCode: "server_error", message, raw: body };
|
|
1993
|
+
if (status === 404)
|
|
1994
|
+
return { ok: false, status, errorType: "retryable", errorCode: "model_not_found", message, raw: body };
|
|
1995
|
+
if (status === 401 || status === 403)
|
|
1996
|
+
return { ok: false, status, errorType: "terminal", errorCode: "auth", message, raw: body };
|
|
1997
|
+
if (status === 400)
|
|
1998
|
+
return { ok: false, status, errorType: "terminal", errorCode: "invalid_request", message, raw: body };
|
|
1999
|
+
return { ok: false, status, errorType: "terminal", errorCode: "unknown", message, raw: body };
|
|
2000
|
+
}
|
|
2001
|
+
function extractErrorMessage(body) {
|
|
2002
|
+
if (!body || typeof body !== "object") return void 0;
|
|
2003
|
+
const b = body;
|
|
2004
|
+
if (b.error && typeof b.error === "object") {
|
|
2005
|
+
const e = b.error;
|
|
2006
|
+
if (typeof e.message === "string") return e.message;
|
|
2007
|
+
}
|
|
2008
|
+
if (typeof b.message === "string") return b.message;
|
|
2009
|
+
return void 0;
|
|
2010
|
+
}
|
|
2011
|
+
function retryableError(status, code, message, raw) {
|
|
2012
|
+
return { ok: false, status, errorType: "retryable", errorCode: code, message, raw };
|
|
2013
|
+
}
|
|
2014
|
+
|
|
2015
|
+
// src/execute.ts
|
|
2016
|
+
var ANTHROPIC_URL2 = "https://api.anthropic.com/v1/messages";
|
|
1688
2017
|
var OPENAI_URL = "https://api.openai.com/v1/chat/completions";
|
|
1689
2018
|
var DEEPSEEK_URL = "https://api.deepseek.com/chat/completions";
|
|
1690
2019
|
async function execute(request, opts = {}) {
|
|
@@ -1709,12 +2038,18 @@ async function executeAnthropic(request, opts) {
|
|
|
1709
2038
|
if (!apiKey) {
|
|
1710
2039
|
return terminalError(401, "auth", "ANTHROPIC_API_KEY missing");
|
|
1711
2040
|
}
|
|
2041
|
+
if (opts.onChunk) {
|
|
2042
|
+
return streamAnthropic(request, apiKey, {
|
|
2043
|
+
onChunk: opts.onChunk,
|
|
2044
|
+
fetchImpl: opts.fetchImpl
|
|
2045
|
+
});
|
|
2046
|
+
}
|
|
1712
2047
|
const { provider: _provider, ...body } = request;
|
|
1713
2048
|
const fetchFn = opts.fetchImpl ?? fetch;
|
|
1714
2049
|
let res;
|
|
1715
2050
|
let json;
|
|
1716
2051
|
try {
|
|
1717
|
-
res = await fetchFn(
|
|
2052
|
+
res = await fetchFn(ANTHROPIC_URL2, {
|
|
1718
2053
|
method: "POST",
|
|
1719
2054
|
headers: {
|
|
1720
2055
|
"x-api-key": apiKey,
|
|
@@ -1725,9 +2060,9 @@ async function executeAnthropic(request, opts) {
|
|
|
1725
2060
|
});
|
|
1726
2061
|
json = await res.json().catch(() => ({}));
|
|
1727
2062
|
} catch (err) {
|
|
1728
|
-
return
|
|
2063
|
+
return retryableError2(0, "network_error", String(err), null);
|
|
1729
2064
|
}
|
|
1730
|
-
if (!res.ok) return
|
|
2065
|
+
if (!res.ok) return classifyHttpError2(res.status, json);
|
|
1731
2066
|
return { ok: true, status: res.status, response: normalizeAnthropic(json) };
|
|
1732
2067
|
}
|
|
1733
2068
|
function normalizeAnthropic(raw) {
|
|
@@ -1761,9 +2096,9 @@ async function executeGoogle(request, opts) {
|
|
|
1761
2096
|
});
|
|
1762
2097
|
json = await res.json().catch(() => ({}));
|
|
1763
2098
|
} catch (err) {
|
|
1764
|
-
return
|
|
2099
|
+
return retryableError2(0, "network_error", String(err), null);
|
|
1765
2100
|
}
|
|
1766
|
-
if (!res.ok) return
|
|
2101
|
+
if (!res.ok) return classifyHttpError2(res.status, json);
|
|
1767
2102
|
return { ok: true, status: res.status, response: normalizeGoogle(json) };
|
|
1768
2103
|
}
|
|
1769
2104
|
function normalizeGoogle(raw) {
|
|
@@ -1790,6 +2125,12 @@ async function executeOpenAI(request, opts) {
|
|
|
1790
2125
|
if (!apiKey) {
|
|
1791
2126
|
return terminalError(401, "auth", "OPENAI_API_KEY missing");
|
|
1792
2127
|
}
|
|
2128
|
+
if (opts.onChunk) {
|
|
2129
|
+
return streamOpenAILike(OPENAI_URL, request, apiKey, "openai", {
|
|
2130
|
+
onChunk: opts.onChunk,
|
|
2131
|
+
fetchImpl: opts.fetchImpl
|
|
2132
|
+
});
|
|
2133
|
+
}
|
|
1793
2134
|
const { provider: _provider, ...body } = request;
|
|
1794
2135
|
const fetchFn = opts.fetchImpl ?? fetch;
|
|
1795
2136
|
let res;
|
|
@@ -1802,9 +2143,9 @@ async function executeOpenAI(request, opts) {
|
|
|
1802
2143
|
});
|
|
1803
2144
|
json = await res.json().catch(() => ({}));
|
|
1804
2145
|
} catch (err) {
|
|
1805
|
-
return
|
|
2146
|
+
return retryableError2(0, "network_error", String(err), null);
|
|
1806
2147
|
}
|
|
1807
|
-
if (!res.ok) return
|
|
2148
|
+
if (!res.ok) return classifyHttpError2(res.status, json);
|
|
1808
2149
|
return { ok: true, status: res.status, response: normalizeOpenAILike(json) };
|
|
1809
2150
|
}
|
|
1810
2151
|
async function executeDeepSeek(request, opts) {
|
|
@@ -1812,6 +2153,12 @@ async function executeDeepSeek(request, opts) {
|
|
|
1812
2153
|
if (!apiKey) {
|
|
1813
2154
|
return terminalError(401, "auth", "DEEPSEEK_API_KEY missing");
|
|
1814
2155
|
}
|
|
2156
|
+
if (opts.onChunk) {
|
|
2157
|
+
return streamOpenAILike(DEEPSEEK_URL, request, apiKey, "deepseek", {
|
|
2158
|
+
onChunk: opts.onChunk,
|
|
2159
|
+
fetchImpl: opts.fetchImpl
|
|
2160
|
+
});
|
|
2161
|
+
}
|
|
1815
2162
|
const { provider: _provider, ...body } = request;
|
|
1816
2163
|
const fetchFn = opts.fetchImpl ?? fetch;
|
|
1817
2164
|
let res;
|
|
@@ -1824,9 +2171,9 @@ async function executeDeepSeek(request, opts) {
|
|
|
1824
2171
|
});
|
|
1825
2172
|
json = await res.json().catch(() => ({}));
|
|
1826
2173
|
} catch (err) {
|
|
1827
|
-
return
|
|
2174
|
+
return retryableError2(0, "network_error", String(err), null);
|
|
1828
2175
|
}
|
|
1829
|
-
if (!res.ok) return
|
|
2176
|
+
if (!res.ok) return classifyHttpError2(res.status, json);
|
|
1830
2177
|
return { ok: true, status: res.status, response: normalizeOpenAILike(json) };
|
|
1831
2178
|
}
|
|
1832
2179
|
function normalizeOpenAILike(raw) {
|
|
@@ -1836,7 +2183,7 @@ function normalizeOpenAILike(raw) {
|
|
|
1836
2183
|
const toolCalls = (choice?.message?.tool_calls ?? []).filter((tc) => tc.function?.name).map((tc, i) => ({
|
|
1837
2184
|
id: tc.id ?? `tc-${i}`,
|
|
1838
2185
|
name: tc.function.name,
|
|
1839
|
-
args:
|
|
2186
|
+
args: tryParseJson2(tc.function?.arguments) ?? {}
|
|
1840
2187
|
}));
|
|
1841
2188
|
const u = r.usage ?? {};
|
|
1842
2189
|
const tokens = {
|
|
@@ -1853,8 +2200,8 @@ function applyOverrides(request, overrides) {
|
|
|
1853
2200
|
if (!layer) return request;
|
|
1854
2201
|
return { ...request, ...layer };
|
|
1855
2202
|
}
|
|
1856
|
-
function
|
|
1857
|
-
const message =
|
|
2203
|
+
function classifyHttpError2(status, body) {
|
|
2204
|
+
const message = extractErrorMessage2(body) ?? `HTTP ${status}`;
|
|
1858
2205
|
if (status === 429) {
|
|
1859
2206
|
return { ok: false, status, errorType: "retryable", errorCode: "rate_limit", message, raw: body };
|
|
1860
2207
|
}
|
|
@@ -1875,7 +2222,7 @@ function classifyHttpError(status, body) {
|
|
|
1875
2222
|
}
|
|
1876
2223
|
return { ok: false, status, errorType: "terminal", errorCode: "unknown", message, raw: body };
|
|
1877
2224
|
}
|
|
1878
|
-
function
|
|
2225
|
+
function extractErrorMessage2(body) {
|
|
1879
2226
|
if (!body || typeof body !== "object") return void 0;
|
|
1880
2227
|
const b = body;
|
|
1881
2228
|
if (b.error && typeof b.error === "object") {
|
|
@@ -1888,10 +2235,10 @@ function extractErrorMessage(body) {
|
|
|
1888
2235
|
function terminalError(status, code, message) {
|
|
1889
2236
|
return { ok: false, status, errorType: "terminal", errorCode: code, message, raw: null };
|
|
1890
2237
|
}
|
|
1891
|
-
function
|
|
2238
|
+
function retryableError2(status, code, message, raw) {
|
|
1892
2239
|
return { ok: false, status, errorType: "retryable", errorCode: code, message, raw };
|
|
1893
2240
|
}
|
|
1894
|
-
function
|
|
2241
|
+
function tryParseJson2(s) {
|
|
1895
2242
|
if (typeof s !== "string" || s.length === 0) return void 0;
|
|
1896
2243
|
try {
|
|
1897
2244
|
const parsed = JSON.parse(s);
|
|
@@ -2061,10 +2408,13 @@ async function call(ir, opts = {}) {
|
|
|
2061
2408
|
safeEmit(
|
|
2062
2409
|
() => emitExecuteAttempt(traceId, ir.appId, { model: targetModel, attemptIndex: i })
|
|
2063
2410
|
);
|
|
2411
|
+
const targetSupportsStreaming = targetProfile?.streaming === true;
|
|
2412
|
+
const streamingOnChunk = opts.onChunk && !opts.noStream && targetSupportsStreaming ? opts.onChunk : void 0;
|
|
2064
2413
|
const exec = await execute(activeCompile.request, {
|
|
2065
2414
|
apiKeys: opts.apiKeys,
|
|
2066
2415
|
fetchImpl: opts.fetchImpl,
|
|
2067
|
-
providerOverrides: opts.providerOverrides
|
|
2416
|
+
providerOverrides: opts.providerOverrides,
|
|
2417
|
+
onChunk: streamingOnChunk
|
|
2068
2418
|
});
|
|
2069
2419
|
const validated = exec.ok ? validateStructuredContract(exec, ir) : exec;
|
|
2070
2420
|
if (validated.ok) {
|
|
@@ -2247,6 +2597,34 @@ function safeEmit(fn) {
|
|
|
2247
2597
|
}
|
|
2248
2598
|
}
|
|
2249
2599
|
|
|
2600
|
+
// src/streamtext-helpers.ts
|
|
2601
|
+
function attachCacheControlToStreamTextInput(result, convertedMessages) {
|
|
2602
|
+
const messages = convertedMessages.map((m) => ({ ...m }));
|
|
2603
|
+
const markIdx = result.diagnostics.historyCacheMarkIndex;
|
|
2604
|
+
if (result.provider === "anthropic" && typeof markIdx === "number" && markIdx >= 0 && markIdx < messages.length) {
|
|
2605
|
+
const target = messages[markIdx];
|
|
2606
|
+
if (target) {
|
|
2607
|
+
messages[markIdx] = {
|
|
2608
|
+
role: target.role,
|
|
2609
|
+
content: target.content,
|
|
2610
|
+
providerOptions: {
|
|
2611
|
+
...target.providerOptions ?? {},
|
|
2612
|
+
anthropic: {
|
|
2613
|
+
...target.providerOptions?.anthropic ?? {},
|
|
2614
|
+
cacheControl: { type: "ephemeral" }
|
|
2615
|
+
}
|
|
2616
|
+
}
|
|
2617
|
+
};
|
|
2618
|
+
}
|
|
2619
|
+
}
|
|
2620
|
+
const systemMessages = result.systemMessages;
|
|
2621
|
+
const hasStructuredSystemCacheControl = result.provider === "anthropic" && systemMessages.some(
|
|
2622
|
+
(m) => m.providerOptions?.anthropic?.cacheControl !== void 0
|
|
2623
|
+
);
|
|
2624
|
+
const system = hasStructuredSystemCacheControl ? systemMessages : systemMessages.map((m) => m.content).join("\n\n");
|
|
2625
|
+
return { system, messages };
|
|
2626
|
+
}
|
|
2627
|
+
|
|
2250
2628
|
// src/oracle.ts
|
|
2251
2629
|
var DEFAULT_DIMENSIONS = ["correctness", "completeness", "conciseness", "format"];
|
|
2252
2630
|
var judgeCallTimes = [];
|
|
@@ -2746,6 +3124,7 @@ export {
|
|
|
2746
3124
|
TRANSLATOR_FLOOR,
|
|
2747
3125
|
allProfiles,
|
|
2748
3126
|
applySectionRewrites,
|
|
3127
|
+
attachCacheControlToStreamTextInput,
|
|
2749
3128
|
bucketContext,
|
|
2750
3129
|
bucketHistory,
|
|
2751
3130
|
bucketToolCount,
|