@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.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/
|
|
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(
|
|
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
|
|
3699
|
+
return retryableError2(0, "network_error", String(err), null);
|
|
3364
3700
|
}
|
|
3365
|
-
if (!res.ok) return
|
|
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
|
|
3735
|
+
return retryableError2(0, "network_error", String(err), null);
|
|
3400
3736
|
}
|
|
3401
|
-
if (!res.ok) return
|
|
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
|
|
3782
|
+
return retryableError2(0, "network_error", String(err), null);
|
|
3441
3783
|
}
|
|
3442
|
-
if (!res.ok) return
|
|
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
|
|
3810
|
+
return retryableError2(0, "network_error", String(err), null);
|
|
3463
3811
|
}
|
|
3464
|
-
if (!res.ok) return
|
|
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:
|
|
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
|
|
3492
|
-
const message =
|
|
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
|
|
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
|
|
3874
|
+
function retryableError2(status, code, message, raw) {
|
|
3527
3875
|
return { ok: false, status, errorType: "retryable", errorCode: code, message, raw };
|
|
3528
3876
|
}
|
|
3529
|
-
function
|
|
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 =
|
|
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,
|