@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/index.mjs CHANGED
@@ -32,7 +32,7 @@ import {
32
32
  isProviderReachable,
33
33
  loadChainsFromBrain,
34
34
  resolveProviderKey
35
- } from "./chunk-WXCFWUCN.mjs";
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/execute.ts
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(ANTHROPIC_URL, {
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 retryableError(0, "network_error", String(err), null);
2063
+ return retryableError2(0, "network_error", String(err), null);
1729
2064
  }
1730
- if (!res.ok) return classifyHttpError(res.status, json);
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 retryableError(0, "network_error", String(err), null);
2099
+ return retryableError2(0, "network_error", String(err), null);
1765
2100
  }
1766
- if (!res.ok) return classifyHttpError(res.status, json);
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 retryableError(0, "network_error", String(err), null);
2146
+ return retryableError2(0, "network_error", String(err), null);
1806
2147
  }
1807
- if (!res.ok) return classifyHttpError(res.status, json);
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 retryableError(0, "network_error", String(err), null);
2174
+ return retryableError2(0, "network_error", String(err), null);
1828
2175
  }
1829
- if (!res.ok) return classifyHttpError(res.status, json);
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: tryParseJson(tc.function?.arguments) ?? {}
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 classifyHttpError(status, body) {
1857
- const message = extractErrorMessage(body) ?? `HTTP ${status}`;
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 extractErrorMessage(body) {
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 retryableError(status, code, message, raw) {
2238
+ function retryableError2(status, code, message, raw) {
1892
2239
  return { ok: false, status, errorType: "retryable", errorCode: code, message, raw };
1893
2240
  }
1894
- function tryParseJson(s) {
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,