@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.js CHANGED
@@ -33,6 +33,7 @@ __export(index_exports, {
33
33
  TRANSLATOR_FLOOR: () => TRANSLATOR_FLOOR,
34
34
  allProfiles: () => allProfiles,
35
35
  applySectionRewrites: () => applySectionRewrites,
36
+ attachCacheControlToStreamTextInput: () => attachCacheControlToStreamTextInput,
36
37
  bucketContext: () => bucketContext,
37
38
  bucketHistory: () => bucketHistory,
38
39
  bucketToolCount: () => bucketToolCount,
@@ -2771,6 +2772,9 @@ function compile(ir, opts = {}) {
2771
2772
  const handle = makeHandle();
2772
2773
  const finalShape = computeShape(workingIR, inputTokens);
2773
2774
  const _learningKey = learningKey(ir.intent.archetype, profile.id, finalShape);
2775
+ const historyCacheMarkIndex = computeHistoryCacheMarkIndex(workingIR);
2776
+ const systemMessages = buildSystemMessages(workingIR, profile.provider);
2777
+ const systemCacheMarkIndex = lastCacheableSystemIndex(systemMessages);
2774
2778
  const diagnostics = {
2775
2779
  sectionsKept: workingIR.sections.length,
2776
2780
  sectionsDropped: ir.sections.length - workingIR.sections.length,
@@ -2784,7 +2788,10 @@ function compile(ir, opts = {}) {
2784
2788
  historyTokensTotal: compressed.historyTokensTotal,
2785
2789
  // alpha.20 E3: mirror the consumer's declared mode for Glass-Box +
2786
2790
  // brain observability. Undefined when not declared (pre-alpha.20).
2787
- toolOrchestration: ir.constraints?.toolOrchestration
2791
+ toolOrchestration: ir.constraints?.toolOrchestration,
2792
+ // alpha.33 — see top-of-block comment.
2793
+ historyCacheMarkIndex,
2794
+ systemCacheMarkIndex
2788
2795
  };
2789
2796
  if (ir.intent.archetype === "hunt" && ir.constraints?.toolOrchestration === "sequential") {
2790
2797
  accumulatedMutations.push({
@@ -2834,9 +2841,45 @@ function compile(ir, opts = {}) {
2834
2841
  advisories,
2835
2842
  diagnostics,
2836
2843
  sectionRewritesApplied,
2837
- wireOverrides
2844
+ wireOverrides,
2845
+ systemMessages
2838
2846
  };
2839
2847
  }
2848
+ function computeHistoryCacheMarkIndex(ir) {
2849
+ const policy = ir.historyCachePolicy;
2850
+ if (!policy || policy.strategy === "none") return void 0;
2851
+ const historyLen = ir.history?.length ?? 0;
2852
+ if (historyLen === 0) return void 0;
2853
+ if (policy.strategy === "all-but-latest") {
2854
+ return historyLen - 1;
2855
+ }
2856
+ if (policy.strategy === "fixed-suffix") {
2857
+ const idx = historyLen - 1 - policy.suffix;
2858
+ if (idx < 0) return void 0;
2859
+ return idx;
2860
+ }
2861
+ return void 0;
2862
+ }
2863
+ function buildSystemMessages(ir, provider) {
2864
+ const sections = ir.sections;
2865
+ if (!sections || sections.length === 0) return [];
2866
+ return sections.map((s) => {
2867
+ const base = { role: "system", content: s.text };
2868
+ if (provider === "anthropic" && s.cacheable) {
2869
+ base.providerOptions = { anthropic: { cacheControl: { type: "ephemeral" } } };
2870
+ }
2871
+ return base;
2872
+ });
2873
+ }
2874
+ function lastCacheableSystemIndex(systemMessages) {
2875
+ for (let i = systemMessages.length - 1; i >= 0; i--) {
2876
+ const entry = systemMessages[i];
2877
+ if (entry && entry.providerOptions?.anthropic?.cacheControl) {
2878
+ return i;
2879
+ }
2880
+ }
2881
+ return void 0;
2882
+ }
2840
2883
  function validateIR(ir) {
2841
2884
  if (!ir.appId) throw new Error("compile(): ir.appId is required");
2842
2885
  if (!ir.intent || !ir.intent.archetype) {
@@ -3318,8 +3361,295 @@ function getReachabilityDiagnostic(opts = {}) {
3318
3361
  return out;
3319
3362
  }
3320
3363
 
3321
- // src/execute.ts
3364
+ // src/streaming.ts
3322
3365
  var ANTHROPIC_URL = "https://api.anthropic.com/v1/messages";
3366
+ async function streamAnthropic(request, apiKey, opts) {
3367
+ const { provider: _provider, ...body } = request;
3368
+ const fetchFn = opts.fetchImpl ?? fetch;
3369
+ let res;
3370
+ try {
3371
+ res = await fetchFn(ANTHROPIC_URL, {
3372
+ method: "POST",
3373
+ headers: {
3374
+ "x-api-key": apiKey,
3375
+ "anthropic-version": "2023-06-01",
3376
+ "content-type": "application/json"
3377
+ },
3378
+ body: JSON.stringify({ ...body, stream: true })
3379
+ });
3380
+ } catch (err) {
3381
+ return retryableError(0, "network_error", String(err), null);
3382
+ }
3383
+ if (!res.ok) {
3384
+ const errBody = await res.json().catch(() => ({}));
3385
+ return classifyHttpError(res.status, errBody);
3386
+ }
3387
+ let text = "";
3388
+ let inputTokens = 0;
3389
+ let outputTokens = 0;
3390
+ let cacheReadTokens;
3391
+ let cacheCreatedTokens;
3392
+ let stopReason;
3393
+ const toolBlocks = /* @__PURE__ */ new Map();
3394
+ try {
3395
+ await parseSSEStream(res, (event) => {
3396
+ if (!event.data) return;
3397
+ let payload;
3398
+ try {
3399
+ payload = JSON.parse(event.data);
3400
+ } catch {
3401
+ return;
3402
+ }
3403
+ const type = payload.type;
3404
+ if (type === "message_start") {
3405
+ const msg = payload.message;
3406
+ const usage = msg?.usage;
3407
+ if (usage) {
3408
+ inputTokens = usage.input_tokens ?? 0;
3409
+ outputTokens = usage.output_tokens ?? 0;
3410
+ if (typeof usage.cache_read_input_tokens === "number")
3411
+ cacheReadTokens = usage.cache_read_input_tokens;
3412
+ if (typeof usage.cache_creation_input_tokens === "number")
3413
+ cacheCreatedTokens = usage.cache_creation_input_tokens;
3414
+ }
3415
+ return;
3416
+ }
3417
+ if (type === "content_block_start") {
3418
+ const p = payload;
3419
+ const idx = p.index ?? 0;
3420
+ const block = p.content_block;
3421
+ if (block?.type === "tool_use" && block.id && block.name) {
3422
+ toolBlocks.set(idx, { id: block.id, name: block.name, argsJson: "" });
3423
+ }
3424
+ return;
3425
+ }
3426
+ if (type === "content_block_delta") {
3427
+ const p = payload;
3428
+ const delta = p.delta;
3429
+ if (!delta) return;
3430
+ if (delta.type === "text_delta" && typeof delta.text === "string") {
3431
+ text += delta.text;
3432
+ opts.onChunk(delta.text);
3433
+ } else if (delta.type === "input_json_delta" && typeof delta.partial_json === "string") {
3434
+ const idx = p.index ?? 0;
3435
+ const tool = toolBlocks.get(idx);
3436
+ if (tool) tool.argsJson += delta.partial_json;
3437
+ }
3438
+ return;
3439
+ }
3440
+ if (type === "message_delta") {
3441
+ const p = payload;
3442
+ if (p.delta?.stop_reason) stopReason = p.delta.stop_reason;
3443
+ if (typeof p.usage?.output_tokens === "number") outputTokens = p.usage.output_tokens;
3444
+ return;
3445
+ }
3446
+ });
3447
+ } catch (err) {
3448
+ return retryableError(0, "stream_interrupted", String(err), null);
3449
+ }
3450
+ const toolCalls = Array.from(toolBlocks.values()).map((b) => ({
3451
+ id: b.id,
3452
+ name: b.name,
3453
+ args: tryParseJson(b.argsJson) ?? {}
3454
+ }));
3455
+ const tokens = {
3456
+ input: inputTokens,
3457
+ output: outputTokens,
3458
+ total: inputTokens + outputTokens,
3459
+ cached: cacheReadTokens,
3460
+ cacheCreated: cacheCreatedTokens
3461
+ };
3462
+ const response = {
3463
+ text,
3464
+ structuredOutput: null,
3465
+ toolCalls,
3466
+ tokens,
3467
+ finishReason: stopReason,
3468
+ raw: { streamed: true, provider: "anthropic" }
3469
+ };
3470
+ return { ok: true, status: res.status, response };
3471
+ }
3472
+ async function streamOpenAILike(url, request, apiKey, providerLabel, opts) {
3473
+ const { provider: _provider, ...body } = request;
3474
+ const fetchFn = opts.fetchImpl ?? fetch;
3475
+ const reqBody = {
3476
+ ...body,
3477
+ stream: true,
3478
+ stream_options: {
3479
+ ...body.stream_options ?? {},
3480
+ include_usage: true
3481
+ }
3482
+ };
3483
+ let res;
3484
+ try {
3485
+ res = await fetchFn(url, {
3486
+ method: "POST",
3487
+ headers: {
3488
+ authorization: `Bearer ${apiKey}`,
3489
+ "content-type": "application/json"
3490
+ },
3491
+ body: JSON.stringify(reqBody)
3492
+ });
3493
+ } catch (err) {
3494
+ return retryableError(0, "network_error", String(err), null);
3495
+ }
3496
+ if (!res.ok) {
3497
+ const errBody = await res.json().catch(() => ({}));
3498
+ return classifyHttpError(res.status, errBody);
3499
+ }
3500
+ let text = "";
3501
+ let finishReason;
3502
+ let inputTokens = 0;
3503
+ let outputTokens = 0;
3504
+ let totalTokens;
3505
+ let cachedTokens;
3506
+ const toolBuffers = /* @__PURE__ */ new Map();
3507
+ try {
3508
+ await parseSSEStream(res, (event) => {
3509
+ if (!event.data) return;
3510
+ if (event.data === "[DONE]") return;
3511
+ let payload;
3512
+ try {
3513
+ payload = JSON.parse(event.data);
3514
+ } catch {
3515
+ return;
3516
+ }
3517
+ const choices = payload.choices;
3518
+ if (choices && choices.length > 0) {
3519
+ const choice = choices[0];
3520
+ const deltaContent = choice.delta?.content;
3521
+ if (typeof deltaContent === "string" && deltaContent.length > 0) {
3522
+ text += deltaContent;
3523
+ opts.onChunk(deltaContent);
3524
+ }
3525
+ const toolDeltas = choice.delta?.tool_calls;
3526
+ if (toolDeltas) {
3527
+ for (const tcDelta of toolDeltas) {
3528
+ const idx = tcDelta.index ?? 0;
3529
+ let buf = toolBuffers.get(idx);
3530
+ if (!buf) {
3531
+ buf = { id: tcDelta.id ?? `tc-${idx}`, name: "", argsJson: "" };
3532
+ toolBuffers.set(idx, buf);
3533
+ }
3534
+ if (tcDelta.id) buf.id = tcDelta.id;
3535
+ if (tcDelta.function?.name) buf.name += tcDelta.function.name;
3536
+ if (tcDelta.function?.arguments) buf.argsJson += tcDelta.function.arguments;
3537
+ }
3538
+ }
3539
+ if (choice.finish_reason) finishReason = choice.finish_reason;
3540
+ }
3541
+ const usage = payload.usage;
3542
+ if (usage) {
3543
+ if (typeof usage.prompt_tokens === "number") inputTokens = usage.prompt_tokens;
3544
+ if (typeof usage.completion_tokens === "number") outputTokens = usage.completion_tokens;
3545
+ if (typeof usage.total_tokens === "number") totalTokens = usage.total_tokens;
3546
+ const details = usage.prompt_tokens_details;
3547
+ if (typeof details?.cached_tokens === "number") cachedTokens = details.cached_tokens;
3548
+ }
3549
+ });
3550
+ } catch (err) {
3551
+ return retryableError(0, "stream_interrupted", String(err), null);
3552
+ }
3553
+ const toolCalls = Array.from(toolBuffers.values()).filter((b) => b.name.length > 0).map((b) => ({
3554
+ id: b.id,
3555
+ name: b.name,
3556
+ args: tryParseJson(b.argsJson) ?? {}
3557
+ }));
3558
+ const tokens = {
3559
+ input: inputTokens,
3560
+ output: outputTokens,
3561
+ total: totalTokens ?? inputTokens + outputTokens,
3562
+ cached: cachedTokens
3563
+ };
3564
+ const response = {
3565
+ text,
3566
+ structuredOutput: null,
3567
+ toolCalls,
3568
+ tokens,
3569
+ finishReason,
3570
+ raw: { streamed: true, provider: providerLabel }
3571
+ };
3572
+ return { ok: true, status: res.status, response };
3573
+ }
3574
+ async function parseSSEStream(response, handler) {
3575
+ const body = response.body;
3576
+ if (!body) throw new Error("Response has no body for SSE parse");
3577
+ const reader = body.getReader();
3578
+ const decoder = new TextDecoder("utf-8");
3579
+ let buffer = "";
3580
+ for (; ; ) {
3581
+ const { value, done } = await reader.read();
3582
+ if (done) break;
3583
+ buffer += decoder.decode(value, { stream: true });
3584
+ let sep;
3585
+ while (sep = buffer.indexOf("\n\n"), sep !== -1) {
3586
+ const block = buffer.slice(0, sep);
3587
+ buffer = buffer.slice(sep + 2);
3588
+ const event = parseSSEBlock(block);
3589
+ if (event) handler(event);
3590
+ }
3591
+ }
3592
+ if (buffer.length > 0) {
3593
+ const event = parseSSEBlock(buffer);
3594
+ if (event) handler(event);
3595
+ }
3596
+ }
3597
+ function parseSSEBlock(block) {
3598
+ const lines = block.split(/\r?\n/);
3599
+ let eventName;
3600
+ const dataLines = [];
3601
+ for (const line of lines) {
3602
+ if (line.startsWith(":")) continue;
3603
+ if (line.startsWith("event:")) {
3604
+ eventName = line.slice(6).trim();
3605
+ } else if (line.startsWith("data:")) {
3606
+ dataLines.push(line.slice(5).trim());
3607
+ }
3608
+ }
3609
+ if (dataLines.length === 0) return void 0;
3610
+ return { event: eventName, data: dataLines.join("\n") };
3611
+ }
3612
+ function tryParseJson(s) {
3613
+ if (typeof s !== "string" || s.length === 0) return void 0;
3614
+ try {
3615
+ const parsed = JSON.parse(s);
3616
+ return typeof parsed === "object" && parsed !== null ? parsed : void 0;
3617
+ } catch {
3618
+ return void 0;
3619
+ }
3620
+ }
3621
+ function classifyHttpError(status, body) {
3622
+ const message = extractErrorMessage(body) ?? `HTTP ${status}`;
3623
+ if (status === 429)
3624
+ return { ok: false, status, errorType: "retryable", errorCode: "rate_limit", message, raw: body };
3625
+ if (status === 408)
3626
+ return { ok: false, status, errorType: "retryable", errorCode: "timeout", message, raw: body };
3627
+ if (status >= 500)
3628
+ return { ok: false, status, errorType: "retryable", errorCode: "server_error", message, raw: body };
3629
+ if (status === 404)
3630
+ return { ok: false, status, errorType: "retryable", errorCode: "model_not_found", message, raw: body };
3631
+ if (status === 401 || status === 403)
3632
+ return { ok: false, status, errorType: "terminal", errorCode: "auth", message, raw: body };
3633
+ if (status === 400)
3634
+ return { ok: false, status, errorType: "terminal", errorCode: "invalid_request", message, raw: body };
3635
+ return { ok: false, status, errorType: "terminal", errorCode: "unknown", message, raw: body };
3636
+ }
3637
+ function extractErrorMessage(body) {
3638
+ if (!body || typeof body !== "object") return void 0;
3639
+ const b = body;
3640
+ if (b.error && typeof b.error === "object") {
3641
+ const e = b.error;
3642
+ if (typeof e.message === "string") return e.message;
3643
+ }
3644
+ if (typeof b.message === "string") return b.message;
3645
+ return void 0;
3646
+ }
3647
+ function retryableError(status, code, message, raw) {
3648
+ return { ok: false, status, errorType: "retryable", errorCode: code, message, raw };
3649
+ }
3650
+
3651
+ // src/execute.ts
3652
+ var ANTHROPIC_URL2 = "https://api.anthropic.com/v1/messages";
3323
3653
  var OPENAI_URL = "https://api.openai.com/v1/chat/completions";
3324
3654
  var DEEPSEEK_URL = "https://api.deepseek.com/chat/completions";
3325
3655
  async function execute(request, opts = {}) {
@@ -3344,12 +3674,18 @@ async function executeAnthropic(request, opts) {
3344
3674
  if (!apiKey) {
3345
3675
  return terminalError(401, "auth", "ANTHROPIC_API_KEY missing");
3346
3676
  }
3677
+ if (opts.onChunk) {
3678
+ return streamAnthropic(request, apiKey, {
3679
+ onChunk: opts.onChunk,
3680
+ fetchImpl: opts.fetchImpl
3681
+ });
3682
+ }
3347
3683
  const { provider: _provider, ...body } = request;
3348
3684
  const fetchFn = opts.fetchImpl ?? fetch;
3349
3685
  let res;
3350
3686
  let json;
3351
3687
  try {
3352
- res = await fetchFn(ANTHROPIC_URL, {
3688
+ res = await fetchFn(ANTHROPIC_URL2, {
3353
3689
  method: "POST",
3354
3690
  headers: {
3355
3691
  "x-api-key": apiKey,
@@ -3360,9 +3696,9 @@ async function executeAnthropic(request, opts) {
3360
3696
  });
3361
3697
  json = await res.json().catch(() => ({}));
3362
3698
  } catch (err) {
3363
- return retryableError(0, "network_error", String(err), null);
3699
+ return retryableError2(0, "network_error", String(err), null);
3364
3700
  }
3365
- if (!res.ok) return classifyHttpError(res.status, json);
3701
+ if (!res.ok) return classifyHttpError2(res.status, json);
3366
3702
  return { ok: true, status: res.status, response: normalizeAnthropic(json) };
3367
3703
  }
3368
3704
  function normalizeAnthropic(raw) {
@@ -3396,9 +3732,9 @@ async function executeGoogle(request, opts) {
3396
3732
  });
3397
3733
  json = await res.json().catch(() => ({}));
3398
3734
  } catch (err) {
3399
- return retryableError(0, "network_error", String(err), null);
3735
+ return retryableError2(0, "network_error", String(err), null);
3400
3736
  }
3401
- if (!res.ok) return classifyHttpError(res.status, json);
3737
+ if (!res.ok) return classifyHttpError2(res.status, json);
3402
3738
  return { ok: true, status: res.status, response: normalizeGoogle(json) };
3403
3739
  }
3404
3740
  function normalizeGoogle(raw) {
@@ -3425,6 +3761,12 @@ async function executeOpenAI(request, opts) {
3425
3761
  if (!apiKey) {
3426
3762
  return terminalError(401, "auth", "OPENAI_API_KEY missing");
3427
3763
  }
3764
+ if (opts.onChunk) {
3765
+ return streamOpenAILike(OPENAI_URL, request, apiKey, "openai", {
3766
+ onChunk: opts.onChunk,
3767
+ fetchImpl: opts.fetchImpl
3768
+ });
3769
+ }
3428
3770
  const { provider: _provider, ...body } = request;
3429
3771
  const fetchFn = opts.fetchImpl ?? fetch;
3430
3772
  let res;
@@ -3437,9 +3779,9 @@ async function executeOpenAI(request, opts) {
3437
3779
  });
3438
3780
  json = await res.json().catch(() => ({}));
3439
3781
  } catch (err) {
3440
- return retryableError(0, "network_error", String(err), null);
3782
+ return retryableError2(0, "network_error", String(err), null);
3441
3783
  }
3442
- if (!res.ok) return classifyHttpError(res.status, json);
3784
+ if (!res.ok) return classifyHttpError2(res.status, json);
3443
3785
  return { ok: true, status: res.status, response: normalizeOpenAILike(json) };
3444
3786
  }
3445
3787
  async function executeDeepSeek(request, opts) {
@@ -3447,6 +3789,12 @@ async function executeDeepSeek(request, opts) {
3447
3789
  if (!apiKey) {
3448
3790
  return terminalError(401, "auth", "DEEPSEEK_API_KEY missing");
3449
3791
  }
3792
+ if (opts.onChunk) {
3793
+ return streamOpenAILike(DEEPSEEK_URL, request, apiKey, "deepseek", {
3794
+ onChunk: opts.onChunk,
3795
+ fetchImpl: opts.fetchImpl
3796
+ });
3797
+ }
3450
3798
  const { provider: _provider, ...body } = request;
3451
3799
  const fetchFn = opts.fetchImpl ?? fetch;
3452
3800
  let res;
@@ -3459,9 +3807,9 @@ async function executeDeepSeek(request, opts) {
3459
3807
  });
3460
3808
  json = await res.json().catch(() => ({}));
3461
3809
  } catch (err) {
3462
- return retryableError(0, "network_error", String(err), null);
3810
+ return retryableError2(0, "network_error", String(err), null);
3463
3811
  }
3464
- if (!res.ok) return classifyHttpError(res.status, json);
3812
+ if (!res.ok) return classifyHttpError2(res.status, json);
3465
3813
  return { ok: true, status: res.status, response: normalizeOpenAILike(json) };
3466
3814
  }
3467
3815
  function normalizeOpenAILike(raw) {
@@ -3471,7 +3819,7 @@ function normalizeOpenAILike(raw) {
3471
3819
  const toolCalls = (choice?.message?.tool_calls ?? []).filter((tc) => tc.function?.name).map((tc, i) => ({
3472
3820
  id: tc.id ?? `tc-${i}`,
3473
3821
  name: tc.function.name,
3474
- args: tryParseJson(tc.function?.arguments) ?? {}
3822
+ args: tryParseJson2(tc.function?.arguments) ?? {}
3475
3823
  }));
3476
3824
  const u = r.usage ?? {};
3477
3825
  const tokens = {
@@ -3488,8 +3836,8 @@ function applyOverrides(request, overrides) {
3488
3836
  if (!layer) return request;
3489
3837
  return { ...request, ...layer };
3490
3838
  }
3491
- function classifyHttpError(status, body) {
3492
- const message = extractErrorMessage(body) ?? `HTTP ${status}`;
3839
+ function classifyHttpError2(status, body) {
3840
+ const message = extractErrorMessage2(body) ?? `HTTP ${status}`;
3493
3841
  if (status === 429) {
3494
3842
  return { ok: false, status, errorType: "retryable", errorCode: "rate_limit", message, raw: body };
3495
3843
  }
@@ -3510,7 +3858,7 @@ function classifyHttpError(status, body) {
3510
3858
  }
3511
3859
  return { ok: false, status, errorType: "terminal", errorCode: "unknown", message, raw: body };
3512
3860
  }
3513
- function extractErrorMessage(body) {
3861
+ function extractErrorMessage2(body) {
3514
3862
  if (!body || typeof body !== "object") return void 0;
3515
3863
  const b = body;
3516
3864
  if (b.error && typeof b.error === "object") {
@@ -3523,10 +3871,10 @@ function extractErrorMessage(body) {
3523
3871
  function terminalError(status, code, message) {
3524
3872
  return { ok: false, status, errorType: "terminal", errorCode: code, message, raw: null };
3525
3873
  }
3526
- function retryableError(status, code, message, raw) {
3874
+ function retryableError2(status, code, message, raw) {
3527
3875
  return { ok: false, status, errorType: "retryable", errorCode: code, message, raw };
3528
3876
  }
3529
- function tryParseJson(s) {
3877
+ function tryParseJson2(s) {
3530
3878
  if (typeof s !== "string" || s.length === 0) return void 0;
3531
3879
  try {
3532
3880
  const parsed = JSON.parse(s);
@@ -3581,7 +3929,8 @@ var STARTER_CHAINS_GROUNDED = {
3581
3929
  { id: "claude-sonnet-4-6", grounding: "judgment", reason: "Reasoning + cost balance \u2014 engineer pick" },
3582
3930
  { id: "claude-opus-4-7", grounding: "judgment", reason: 'Same-provider walk-UP on 429 (rare exception to "always cheaper")' },
3583
3931
  { id: "gemini-2.5-pro", grounding: "judgment", reason: "Cross-provider anchor" },
3584
- { id: "deepseek-v4-pro", grounding: "judgment", reason: "Tier 3 cost floor \u2014 no brain evidence yet" }
3932
+ { id: "deepseek-v4-pro", grounding: "judgment", reason: "Tier 3 cost floor \u2014 no brain evidence yet" },
3933
+ { id: "gpt-5.4", grounding: "judgment", reason: "alpha.33: third-provider tail (archetypePerf=7) \u2014 closes openai-in-default-fallback-chains" }
3585
3934
  ],
3586
3935
  // Quality + cost match.
3587
3936
  generate: [
@@ -3612,7 +3961,8 @@ var STARTER_CHAINS_GROUNDED = {
3612
3961
  { id: "claude-sonnet-4-6", grounding: "judgment", reason: "Quality anchor \u2014 engineer pick" },
3613
3962
  { id: "claude-haiku-4-5", grounding: "judgment", reason: "Same-provider step-down" },
3614
3963
  { id: "gemini-2.5-pro", grounding: "judgment", reason: "Cross-provider anchor" },
3615
- { id: "gemini-2.5-flash", grounding: "judgment", reason: "Cost floor \u2014 forgiving archetype tolerates Flash" }
3964
+ { id: "gemini-2.5-flash", grounding: "judgment", reason: "Cost floor \u2014 forgiving archetype tolerates Flash" },
3965
+ { id: "gpt-5.4-mini", grounding: "judgment", reason: "alpha.33: third-provider tail (archetypePerf=7) \u2014 closes openai-in-default-fallback-chains" }
3616
3966
  ],
3617
3967
  // Parallel-tool throughput champion — Flash leads on the L-040 cliff
3618
3968
  // (capability-fact: Flash 15-75 parallel calls/step vs DeepSeek 7-8).
@@ -3620,21 +3970,24 @@ var STARTER_CHAINS_GROUNDED = {
3620
3970
  { id: "gemini-2.5-flash", grounding: "capability-fact", reason: "L-040 parallel-tool throughput champion (15-75 calls/step)" },
3621
3971
  { id: "gemini-2.5-pro", grounding: "capability-fact", reason: "Cross-provider tier 1 with strong parallel-tool support" },
3622
3972
  { id: "claude-sonnet-4-6", grounding: "judgment", reason: "Quality safety net for blocked-Flash case" },
3623
- { id: "claude-haiku-4-5", grounding: "judgment", reason: "Reduced tool budget \u2014 cliff at 16 fires" }
3973
+ { id: "claude-haiku-4-5", grounding: "judgment", reason: "Reduced tool budget \u2014 cliff at 16 fires" },
3974
+ { id: "gpt-5.4-mini", grounding: "judgment", reason: "alpha.33: third-provider tail \u2014 OpenAI parallel-tool capable archetype" }
3624
3975
  ],
3625
3976
  // Cost-sensitive + tolerant. DeepSeek brain-evidence tier 1.
3626
3977
  summarize: [
3627
3978
  { id: "gemini-2.5-flash", grounding: "judgment", reason: "Cost-sensitive primary \u2014 engineer pick" },
3628
3979
  { id: "deepseek-v4-flash", grounding: "measured", reason: "Brain-validated tier 1 for cost-sensitive summarize workloads", n: 169 },
3629
3980
  { id: "claude-haiku-4-5", grounding: "judgment", reason: "Quality safety net" },
3630
- { id: "gemini-2.5-flash-lite", grounding: "judgment", reason: "Emergency floor \u2014 onboarded s22, no brain evidence yet" }
3981
+ { id: "gemini-2.5-flash-lite", grounding: "judgment", reason: "Emergency floor \u2014 onboarded s22, no brain evidence yet" },
3982
+ { id: "gpt-5.4-nano", grounding: "judgment", reason: "alpha.33: third-provider tail (archetypePerf=6) \u2014 cheapest OpenAI, matches summarize cost-band" }
3631
3983
  ],
3632
3984
  // Brain-validated DeepSeek tier 1 (169 rows, 0% empty rate).
3633
3985
  classify: [
3634
3986
  { id: "gemini-2.5-flash", grounding: "judgment", reason: "Cost-sensitive primary \u2014 engineer pick" },
3635
3987
  { id: "deepseek-v4-flash", grounding: "measured", reason: "Brain-validated tier 1 (169 rows, 0% empty rate)", n: 169 },
3636
3988
  { id: "claude-haiku-4-5", grounding: "judgment", reason: "Quality safety net" },
3637
- { id: "gemini-2.5-flash-lite", grounding: "judgment", reason: "Cache-discount 10\xD7 floor for repeat-prompt workloads" }
3989
+ { id: "gemini-2.5-flash-lite", grounding: "judgment", reason: "Cache-discount 10\xD7 floor for repeat-prompt workloads" },
3990
+ { id: "gpt-5.4-nano", grounding: "judgment", reason: "alpha.33: third-provider tail (archetypePerf=6) \u2014 cheapest OpenAI for classify" }
3638
3991
  ]
3639
3992
  };
3640
3993
  var STARTER_CHAINS = (() => {
@@ -3689,7 +4042,7 @@ function resolveStarterForMode(archetype, toolOrchestration, allChains) {
3689
4042
  return allChains[archetype];
3690
4043
  }
3691
4044
  function getDefaultFallbackChain(opts) {
3692
- const { archetype, primary, maxDepth = 3, policy, reachability, toolOrchestration } = opts;
4045
+ const { archetype, primary, maxDepth = 4, policy, reachability, toolOrchestration } = opts;
3693
4046
  if (maxDepth < 1) {
3694
4047
  throw new Error(
3695
4048
  `getDefaultFallbackChain: maxDepth must be >= 1, got ${maxDepth}`
@@ -4335,10 +4688,13 @@ async function call(ir, opts = {}) {
4335
4688
  safeEmit(
4336
4689
  () => emitExecuteAttempt(traceId, ir.appId, { model: targetModel, attemptIndex: i })
4337
4690
  );
4691
+ const targetSupportsStreaming = targetProfile?.streaming === true;
4692
+ const streamingOnChunk = opts.onChunk && !opts.noStream && targetSupportsStreaming ? opts.onChunk : void 0;
4338
4693
  const exec = await execute(activeCompile.request, {
4339
4694
  apiKeys: opts.apiKeys,
4340
4695
  fetchImpl: opts.fetchImpl,
4341
- providerOverrides: opts.providerOverrides
4696
+ providerOverrides: opts.providerOverrides,
4697
+ onChunk: streamingOnChunk
4342
4698
  });
4343
4699
  const validated = exec.ok ? validateStructuredContract(exec, ir) : exec;
4344
4700
  if (validated.ok) {
@@ -4521,6 +4877,34 @@ function safeEmit(fn) {
4521
4877
  }
4522
4878
  }
4523
4879
 
4880
+ // src/streamtext-helpers.ts
4881
+ function attachCacheControlToStreamTextInput(result, convertedMessages) {
4882
+ const messages = convertedMessages.map((m) => ({ ...m }));
4883
+ const markIdx = result.diagnostics.historyCacheMarkIndex;
4884
+ if (result.provider === "anthropic" && typeof markIdx === "number" && markIdx >= 0 && markIdx < messages.length) {
4885
+ const target = messages[markIdx];
4886
+ if (target) {
4887
+ messages[markIdx] = {
4888
+ role: target.role,
4889
+ content: target.content,
4890
+ providerOptions: {
4891
+ ...target.providerOptions ?? {},
4892
+ anthropic: {
4893
+ ...target.providerOptions?.anthropic ?? {},
4894
+ cacheControl: { type: "ephemeral" }
4895
+ }
4896
+ }
4897
+ };
4898
+ }
4899
+ }
4900
+ const systemMessages = result.systemMessages;
4901
+ const hasStructuredSystemCacheControl = result.provider === "anthropic" && systemMessages.some(
4902
+ (m) => m.providerOptions?.anthropic?.cacheControl !== void 0
4903
+ );
4904
+ const system = hasStructuredSystemCacheControl ? systemMessages : systemMessages.map((m) => m.content).join("\n\n");
4905
+ return { system, messages };
4906
+ }
4907
+
4524
4908
  // src/oracle.ts
4525
4909
  var DEFAULT_DIMENSIONS = ["correctness", "completeness", "conciseness", "format"];
4526
4910
  var judgeCallTimes = [];
@@ -5021,6 +5405,7 @@ function compile2(ir, opts) {
5021
5405
  TRANSLATOR_FLOOR,
5022
5406
  allProfiles,
5023
5407
  applySectionRewrites,
5408
+ attachCacheControlToStreamTextInput,
5024
5409
  bucketContext,
5025
5410
  bucketHistory,
5026
5411
  bucketToolCount,