@axlsdk/axl 0.25.0 → 0.25.2
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/README.md +14 -15
- package/dist/index.cjs +831 -157
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +106 -19
- package/dist/index.d.ts +106 -19
- package/dist/index.js +816 -143
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -184,6 +184,7 @@ __export(index_exports, {
|
|
|
184
184
|
TranscriptionProviderRegistry: () => TranscriptionProviderRegistry,
|
|
185
185
|
UnsupportedEventSchemaVersionError: () => UnsupportedEventSchemaVersionError,
|
|
186
186
|
UnsupportedModelInputError: () => UnsupportedModelInputError,
|
|
187
|
+
UnsupportedModelOptionError: () => UnsupportedModelOptionError,
|
|
187
188
|
UnsupportedTranscriptionInputError: () => UnsupportedTranscriptionInputError,
|
|
188
189
|
VLLM_PROFILE: () => VLLM_PROFILE,
|
|
189
190
|
ValidationError: () => ValidationError,
|
|
@@ -272,6 +273,23 @@ var UnsupportedModelInputError = class extends AxlError {
|
|
|
272
273
|
this.source = options.source;
|
|
273
274
|
}
|
|
274
275
|
};
|
|
276
|
+
var UnsupportedModelOptionError = class extends AxlError {
|
|
277
|
+
provider;
|
|
278
|
+
model;
|
|
279
|
+
option;
|
|
280
|
+
remediation;
|
|
281
|
+
constructor(options) {
|
|
282
|
+
super(
|
|
283
|
+
"UNSUPPORTED_MODEL_OPTION",
|
|
284
|
+
`Provider '${options.provider}' model '${options.model}' does not support ${options.option}. ${options.remediation}`
|
|
285
|
+
);
|
|
286
|
+
this.name = "UnsupportedModelOptionError";
|
|
287
|
+
this.provider = options.provider;
|
|
288
|
+
this.model = options.model;
|
|
289
|
+
this.option = options.option;
|
|
290
|
+
this.remediation = options.remediation;
|
|
291
|
+
}
|
|
292
|
+
};
|
|
275
293
|
var InvalidTranscriptionInputError = class extends AxlError {
|
|
276
294
|
constructor(message) {
|
|
277
295
|
super("INVALID_TRANSCRIPTION_INPUT", message);
|
|
@@ -563,7 +581,7 @@ var sharedGuard = typeof installedGuard === "object" && installedGuard !== null
|
|
|
563
581
|
var buildPath = typeof __AXL_BUILD_PATH__ === "string" ? __AXL_BUILD_PATH__ : "<source>";
|
|
564
582
|
var thisCopy = {
|
|
565
583
|
path: buildPath.startsWith("file:") ? (0, import_node_url.fileURLToPath)(buildPath) : buildPath,
|
|
566
|
-
version: true ? "0.25.
|
|
584
|
+
version: true ? "0.25.2" : "unknown"
|
|
567
585
|
};
|
|
568
586
|
function warnCrossCopy(other, joined) {
|
|
569
587
|
if (other === thisCopy) return;
|
|
@@ -3436,8 +3454,12 @@ var OpenAICompatibleProvider = class {
|
|
|
3436
3454
|
for (const key of forbidden) {
|
|
3437
3455
|
if (!userKeys.includes(key)) delete body[key];
|
|
3438
3456
|
}
|
|
3457
|
+
this.validateFinalRequestBody(body);
|
|
3439
3458
|
return body;
|
|
3440
3459
|
}
|
|
3460
|
+
/** Native subclasses may reject model-invalid fields after providerOptions merge. */
|
|
3461
|
+
validateFinalRequestBody(_body) {
|
|
3462
|
+
}
|
|
3441
3463
|
formatMessage(msg, model) {
|
|
3442
3464
|
const modalities = this.inputModalities(model);
|
|
3443
3465
|
const out = {
|
|
@@ -3845,6 +3867,24 @@ var withLongContext = (short) => ({
|
|
|
3845
3867
|
output: short.output * 1.5
|
|
3846
3868
|
});
|
|
3847
3869
|
var DIRECT_OPENAI_CATALOG = [
|
|
3870
|
+
{
|
|
3871
|
+
aliases: ["gpt-6-astra"],
|
|
3872
|
+
short: { input: 10 / M, cachedInput: 1 / M, cacheWrite: 12.5 / M, output: 50 / M },
|
|
3873
|
+
long: { input: 20 / M, cachedInput: 2 / M, cacheWrite: 25 / M, output: 75 / M },
|
|
3874
|
+
contextBoundary: LONG_CONTEXT_BOUNDARY
|
|
3875
|
+
},
|
|
3876
|
+
{
|
|
3877
|
+
aliases: ["gpt-6-sol"],
|
|
3878
|
+
short: { input: 2 / M, cachedInput: 0.2 / M, cacheWrite: 2.5 / M, output: 10 / M },
|
|
3879
|
+
long: { input: 4 / M, cachedInput: 0.4 / M, cacheWrite: 5 / M, output: 15 / M },
|
|
3880
|
+
contextBoundary: LONG_CONTEXT_BOUNDARY
|
|
3881
|
+
},
|
|
3882
|
+
{
|
|
3883
|
+
aliases: ["gpt-6-luna"],
|
|
3884
|
+
short: { input: 0.1 / M, cachedInput: 0.01 / M, cacheWrite: 0.125 / M, output: 0.5 / M },
|
|
3885
|
+
long: { input: 0.2 / M, cachedInput: 0.02 / M, cacheWrite: 0.25 / M, output: 0.75 / M },
|
|
3886
|
+
contextBoundary: LONG_CONTEXT_BOUNDARY
|
|
3887
|
+
},
|
|
3848
3888
|
{
|
|
3849
3889
|
aliases: ["gpt-5.6", "gpt-5.6-sol"],
|
|
3850
3890
|
snapshotBase: "gpt-5.6-sol",
|
|
@@ -4175,7 +4215,7 @@ function estimateDirectOpenAICost(model, usage, context) {
|
|
|
4175
4215
|
const audioOutput = audio_output_tokens ?? 0;
|
|
4176
4216
|
if (![prompt_tokens, completion_tokens, cached, cacheWrite, audioInput, audioOutput].every(
|
|
4177
4217
|
(count) => Number.isSafeInteger(count) && count >= 0
|
|
4178
|
-
) || cached + cacheWrite + audioInput > prompt_tokens || audioOutput > completion_tokens) {
|
|
4218
|
+
) || resolveOpenAIModelDescriptor(model).strictUsageTotals && (!Number.isSafeInteger(usage.total_tokens) || usage.total_tokens !== prompt_tokens + completion_tokens) || cached + cacheWrite + audioInput > prompt_tokens || audioOutput > completion_tokens) {
|
|
4179
4219
|
return void 0;
|
|
4180
4220
|
}
|
|
4181
4221
|
if (audioInput > 0 && entry.audio === void 0 || audioOutput > 0 && entry.audio?.output === void 0) {
|
|
@@ -4200,57 +4240,206 @@ function estimateOpenAICost(model, promptTokens, completionTokens, cachedTokens)
|
|
|
4200
4240
|
cached_tokens: cachedTokens
|
|
4201
4241
|
});
|
|
4202
4242
|
}
|
|
4203
|
-
|
|
4204
|
-
|
|
4243
|
+
var EFFORT_FALLBACK = {
|
|
4244
|
+
none: "minimal",
|
|
4245
|
+
minimal: "low",
|
|
4246
|
+
low: "medium",
|
|
4247
|
+
medium: "high",
|
|
4248
|
+
max: "xhigh",
|
|
4249
|
+
xhigh: "high"
|
|
4250
|
+
};
|
|
4251
|
+
var BASE_EFFORTS = ["minimal", "low", "medium", "high"];
|
|
4252
|
+
function bothEndpoints(value) {
|
|
4253
|
+
return { chat: value, responses: value };
|
|
4205
4254
|
}
|
|
4206
|
-
function
|
|
4207
|
-
return
|
|
4255
|
+
function gpt6(id, efforts, chatTools) {
|
|
4256
|
+
return {
|
|
4257
|
+
id,
|
|
4258
|
+
family: "gpt-6",
|
|
4259
|
+
reasoning: true,
|
|
4260
|
+
efforts: bothEndpoints(efforts),
|
|
4261
|
+
defaultEffort: "medium",
|
|
4262
|
+
// Same policy as GPT-5.x: a portable `temperature` is dropped while
|
|
4263
|
+
// reasoning is active (including the active default). A raw
|
|
4264
|
+
// `providerOptions` sampling field is rejected by the final-body check.
|
|
4265
|
+
sampling: bothEndpoints("unless-effort-none"),
|
|
4266
|
+
chatTools,
|
|
4267
|
+
validatesFinalBody: true,
|
|
4268
|
+
strictUsageTotals: true
|
|
4269
|
+
};
|
|
4208
4270
|
}
|
|
4209
|
-
|
|
4210
|
-
"
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4271
|
+
function gpt56(id) {
|
|
4272
|
+
const chat = ["none", ...BASE_EFFORTS, "xhigh"];
|
|
4273
|
+
return {
|
|
4274
|
+
id,
|
|
4275
|
+
family: "gpt-5.6",
|
|
4276
|
+
reasoning: true,
|
|
4277
|
+
efforts: { chat, responses: [...chat, "max"] },
|
|
4278
|
+
// Responses rejects temperature even at the provider-default effort.
|
|
4279
|
+
sampling: { chat: "when-effort-sent", responses: "always" },
|
|
4280
|
+
chatTools: "allowed",
|
|
4281
|
+
validatesFinalBody: false,
|
|
4282
|
+
strictUsageTotals: false
|
|
4283
|
+
};
|
|
4217
4284
|
}
|
|
4218
|
-
|
|
4219
|
-
|
|
4285
|
+
var OPENAI_EXACT_MODELS = new Map(
|
|
4286
|
+
[
|
|
4287
|
+
gpt6("gpt-6-astra", ["low", "medium", "high", "xhigh", "max"], "never"),
|
|
4288
|
+
gpt6("gpt-6-sol", ["none", "low", "medium", "high", "xhigh", "max"], "effort-none-only"),
|
|
4289
|
+
gpt6("gpt-6-luna", ["none", "low", "medium", "high", "xhigh", "max"], "effort-none-only"),
|
|
4290
|
+
gpt56("gpt-5.6"),
|
|
4291
|
+
gpt56("gpt-5.6-sol"),
|
|
4292
|
+
gpt56("gpt-5.6-terra"),
|
|
4293
|
+
gpt56("gpt-5.6-luna")
|
|
4294
|
+
].map((descriptor) => [descriptor.id, descriptor])
|
|
4295
|
+
);
|
|
4296
|
+
var O_SERIES_DESCRIPTOR = {
|
|
4297
|
+
id: "o-series",
|
|
4298
|
+
family: "o-series",
|
|
4299
|
+
reasoning: true,
|
|
4300
|
+
efforts: bothEndpoints(BASE_EFFORTS),
|
|
4301
|
+
defaultEffort: "medium",
|
|
4302
|
+
sampling: bothEndpoints("always"),
|
|
4303
|
+
chatTools: "allowed",
|
|
4304
|
+
validatesFinalBody: false,
|
|
4305
|
+
strictUsageTotals: false
|
|
4306
|
+
};
|
|
4307
|
+
var GPT_5_PRO_DESCRIPTOR = {
|
|
4308
|
+
id: "gpt-5-pro",
|
|
4309
|
+
family: "gpt-5-pro",
|
|
4310
|
+
reasoning: true,
|
|
4311
|
+
efforts: bothEndpoints(["high"]),
|
|
4312
|
+
defaultEffort: "high",
|
|
4313
|
+
sampling: bothEndpoints("when-effort-sent"),
|
|
4314
|
+
chatTools: "allowed",
|
|
4315
|
+
validatesFinalBody: false,
|
|
4316
|
+
strictUsageTotals: false
|
|
4317
|
+
};
|
|
4318
|
+
var DEFAULT_DESCRIPTOR = {
|
|
4319
|
+
id: "default",
|
|
4320
|
+
family: "default",
|
|
4321
|
+
reasoning: false,
|
|
4322
|
+
// Never emitted (the model is not reasoning-capable); keeps the clamp total.
|
|
4323
|
+
efforts: bothEndpoints(BASE_EFFORTS),
|
|
4324
|
+
sampling: bothEndpoints("never"),
|
|
4325
|
+
chatTools: "allowed",
|
|
4326
|
+
validatesFinalBody: false,
|
|
4327
|
+
strictUsageTotals: false
|
|
4328
|
+
};
|
|
4329
|
+
function gpt5FamilyDescriptor(model) {
|
|
4330
|
+
const none = /^gpt-5\.[1-9]/.test(model);
|
|
4331
|
+
const xhigh = /^gpt-5\.([2-9]|\d{2,})/.test(model);
|
|
4332
|
+
const efforts = [
|
|
4333
|
+
...none ? ["none"] : [],
|
|
4334
|
+
...BASE_EFFORTS,
|
|
4335
|
+
...xhigh ? ["xhigh"] : []
|
|
4336
|
+
];
|
|
4337
|
+
return {
|
|
4338
|
+
id: "gpt-5",
|
|
4339
|
+
family: "gpt-5",
|
|
4340
|
+
reasoning: true,
|
|
4341
|
+
efforts: bothEndpoints(efforts),
|
|
4342
|
+
...none ? {} : { defaultEffort: "medium" },
|
|
4343
|
+
sampling: bothEndpoints("when-effort-sent"),
|
|
4344
|
+
chatTools: "allowed",
|
|
4345
|
+
validatesFinalBody: false,
|
|
4346
|
+
strictUsageTotals: false
|
|
4347
|
+
};
|
|
4220
4348
|
}
|
|
4221
|
-
|
|
4222
|
-
|
|
4349
|
+
var OPENAI_FAMILY_FALLBACKS = [
|
|
4350
|
+
{ match: /^(o1|o3|o4-mini)/, describe: () => O_SERIES_DESCRIPTOR },
|
|
4351
|
+
{ match: /^gpt-5-pro/, describe: () => GPT_5_PRO_DESCRIPTOR },
|
|
4352
|
+
{ match: /^gpt-5/, describe: gpt5FamilyDescriptor }
|
|
4353
|
+
];
|
|
4354
|
+
function resolveOpenAIModelDescriptor(model) {
|
|
4355
|
+
const exact = OPENAI_EXACT_MODELS.get(model);
|
|
4356
|
+
if (exact) return exact;
|
|
4357
|
+
const family = OPENAI_FAMILY_FALLBACKS.find((entry) => entry.match.test(model));
|
|
4358
|
+
return family ? family.describe(model) : DEFAULT_DESCRIPTOR;
|
|
4359
|
+
}
|
|
4360
|
+
function clampToDescriptor(descriptor, endpoint, effort) {
|
|
4361
|
+
const accepted = descriptor.efforts[endpoint];
|
|
4362
|
+
let candidate = effort;
|
|
4363
|
+
while (candidate !== void 0 && !accepted.includes(candidate)) {
|
|
4364
|
+
candidate = EFFORT_FALLBACK[candidate];
|
|
4365
|
+
}
|
|
4366
|
+
if (candidate === void 0) {
|
|
4367
|
+
throw new Error(
|
|
4368
|
+
`OpenAI descriptor '${descriptor.id}' accepts no ${endpoint} effort reachable from '${effort}'`
|
|
4369
|
+
);
|
|
4370
|
+
}
|
|
4371
|
+
return candidate;
|
|
4223
4372
|
}
|
|
4224
|
-
function
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4373
|
+
function stripsPortableSampling(descriptor, endpoint, wireEffort) {
|
|
4374
|
+
switch (descriptor.sampling[endpoint]) {
|
|
4375
|
+
case "never":
|
|
4376
|
+
return false;
|
|
4377
|
+
case "always":
|
|
4378
|
+
return true;
|
|
4379
|
+
case "when-effort-sent":
|
|
4380
|
+
return wireEffort !== void 0;
|
|
4381
|
+
case "unless-effort-none":
|
|
4382
|
+
return (wireEffort ?? descriptor.defaultEffort) !== "none";
|
|
4229
4383
|
}
|
|
4230
|
-
if (effort === "xhigh" && !supportsXhigh(model)) return "high";
|
|
4231
|
-
return effort;
|
|
4232
4384
|
}
|
|
4233
|
-
function
|
|
4234
|
-
return
|
|
4385
|
+
function isOSeriesModel(model) {
|
|
4386
|
+
return resolveOpenAIModelDescriptor(model).family === "o-series";
|
|
4235
4387
|
}
|
|
4236
4388
|
function budgetToReasoningEffort(budget) {
|
|
4237
4389
|
if (budget <= 1024) return "low";
|
|
4238
4390
|
if (budget <= 8192) return "medium";
|
|
4239
4391
|
return "high";
|
|
4240
4392
|
}
|
|
4393
|
+
function resolveEndpointReasoningEffort(model, endpoint, resolved) {
|
|
4394
|
+
const descriptor = resolveOpenAIModelDescriptor(model);
|
|
4395
|
+
if (!descriptor.reasoning) return void 0;
|
|
4396
|
+
const requested = resolved.hasBudgetOverride ? budgetToReasoningEffort(resolved.thinkingBudget) : !resolved.thinkingDisabled && resolved.activeEffort ? resolved.activeEffort : resolved.thinkingDisabled ? "none" : void 0;
|
|
4397
|
+
return requested === void 0 ? void 0 : clampToDescriptor(descriptor, endpoint, requested);
|
|
4398
|
+
}
|
|
4241
4399
|
function resolveOpenAIReasoningEffort(model, resolved) {
|
|
4242
|
-
|
|
4243
|
-
if (resolved.hasBudgetOverride) {
|
|
4244
|
-
return clampReasoningEffort(model, budgetToReasoningEffort(resolved.thinkingBudget));
|
|
4245
|
-
}
|
|
4246
|
-
if (!resolved.thinkingDisabled && resolved.activeEffort) {
|
|
4247
|
-
return clampReasoningEffort(model, effortToReasoningEffort(resolved.activeEffort, model));
|
|
4248
|
-
}
|
|
4249
|
-
return resolved.thinkingDisabled ? clampReasoningEffort(model, "none") : void 0;
|
|
4400
|
+
return resolveEndpointReasoningEffort(model, "responses", resolved);
|
|
4250
4401
|
}
|
|
4251
4402
|
function resolveOpenAIChatReasoningEffort(model, resolved) {
|
|
4252
|
-
|
|
4253
|
-
|
|
4403
|
+
return resolveEndpointReasoningEffort(model, "chat", resolved);
|
|
4404
|
+
}
|
|
4405
|
+
function validateOpenAIFinalRequestBody(body, endpoint) {
|
|
4406
|
+
const model = body.model;
|
|
4407
|
+
if (typeof model !== "string") return;
|
|
4408
|
+
const descriptor = resolveOpenAIModelDescriptor(model);
|
|
4409
|
+
if (!descriptor.validatesFinalBody) return;
|
|
4410
|
+
const provider = endpoint === "chat" ? "openai" : "openai-responses";
|
|
4411
|
+
const fail = (option, remediation) => {
|
|
4412
|
+
throw new UnsupportedModelOptionError({ provider, model, option, remediation });
|
|
4413
|
+
};
|
|
4414
|
+
const rawEffort = endpoint === "chat" ? body.reasoning_effort : body.reasoning !== null && typeof body.reasoning === "object" ? body.reasoning.effort : void 0;
|
|
4415
|
+
const accepted = descriptor.efforts[endpoint];
|
|
4416
|
+
if (rawEffort !== void 0 && !accepted.includes(rawEffort)) {
|
|
4417
|
+
fail("reasoning effort", `Use one of: ${accepted.join(", ")}.`);
|
|
4418
|
+
}
|
|
4419
|
+
const activeReasoning = (rawEffort ?? descriptor.defaultEffort) !== "none";
|
|
4420
|
+
if (endpoint === "chat" && descriptor.chatTools !== "allowed") {
|
|
4421
|
+
const toolChoice = body.tool_choice;
|
|
4422
|
+
const toolIntent = Array.isArray(body.tools) && body.tools.length > 0 || toolChoice !== void 0 && toolChoice !== null && toolChoice !== "none" && toolChoice !== "auto";
|
|
4423
|
+
if (toolIntent && (descriptor.chatTools === "never" || activeReasoning)) {
|
|
4424
|
+
fail(
|
|
4425
|
+
"Chat Completions tool calling",
|
|
4426
|
+
descriptor.chatTools === "never" ? `Use openai-responses:${model} for tools.` : `Use openai-responses:${model} for reasoning with tools, or set effective reasoning_effort to 'none'.`
|
|
4427
|
+
);
|
|
4428
|
+
}
|
|
4429
|
+
}
|
|
4430
|
+
if (activeReasoning) {
|
|
4431
|
+
const forbidden = endpoint === "chat" ? ["temperature", "top_p", "top_logprobs", "logprobs"] : ["temperature", "top_p", "top_logprobs"];
|
|
4432
|
+
for (const key of forbidden) {
|
|
4433
|
+
if (body[key] !== void 0)
|
|
4434
|
+
fail(key, `Remove ${key} or set reasoning effort to 'none' on Sol or Luna.`);
|
|
4435
|
+
}
|
|
4436
|
+
if (endpoint === "responses" && Array.isArray(body.include) && body.include.includes("message.output_text.logprobs")) {
|
|
4437
|
+
fail(
|
|
4438
|
+
"message.output_text.logprobs",
|
|
4439
|
+
"Remove it from include or set reasoning effort to none on Sol or Luna."
|
|
4440
|
+
);
|
|
4441
|
+
}
|
|
4442
|
+
}
|
|
4254
4443
|
}
|
|
4255
4444
|
function resolveOpenAIEffortResolution(options, resolveWireEffort, endpoint) {
|
|
4256
4445
|
const resolved = resolveThinkingOptions(options);
|
|
@@ -4266,11 +4455,15 @@ function resolveOpenAIEffortResolution(options, resolveWireEffort, endpoint) {
|
|
|
4266
4455
|
};
|
|
4267
4456
|
}
|
|
4268
4457
|
var openaiReasoningEmit = (body, resolved, model) => {
|
|
4269
|
-
const oSeries = isOSeriesModel(model);
|
|
4270
|
-
const reasoningCapable = supportsReasoningEffort(model);
|
|
4271
4458
|
const wireEffort = resolveOpenAIChatReasoningEffort(model, resolved);
|
|
4272
4459
|
if (wireEffort) body.reasoning_effort = wireEffort;
|
|
4273
|
-
return {
|
|
4460
|
+
return {
|
|
4461
|
+
stripTemperature: stripsPortableSampling(
|
|
4462
|
+
resolveOpenAIModelDescriptor(model),
|
|
4463
|
+
"chat",
|
|
4464
|
+
wireEffort
|
|
4465
|
+
)
|
|
4466
|
+
};
|
|
4274
4467
|
};
|
|
4275
4468
|
var OPENAI_PROFILE = {
|
|
4276
4469
|
name: "openai",
|
|
@@ -4305,6 +4498,9 @@ var OpenAIProvider = class extends OpenAICompatibleProvider {
|
|
|
4305
4498
|
"OpenAI Chat Completions"
|
|
4306
4499
|
);
|
|
4307
4500
|
}
|
|
4501
|
+
validateFinalRequestBody(body) {
|
|
4502
|
+
validateOpenAIFinalRequestBody(body, "chat");
|
|
4503
|
+
}
|
|
4308
4504
|
computeCost(model, usage, _reportedCost, context) {
|
|
4309
4505
|
return usage ? estimateDirectOpenAICost(model, usage, { ...context, baseUrl: this.baseUrl }) : void 0;
|
|
4310
4506
|
}
|
|
@@ -4577,12 +4773,12 @@ var OpenAIResponsesProvider = class {
|
|
|
4577
4773
|
// ---------------------------------------------------------------------------
|
|
4578
4774
|
buildRequestBody(messages, options, stream) {
|
|
4579
4775
|
const effectiveModel = typeof options.providerOptions?.model === "string" ? options.providerOptions.model : options.model;
|
|
4580
|
-
const
|
|
4581
|
-
const reasoningCapable =
|
|
4776
|
+
const descriptor = resolveOpenAIModelDescriptor(effectiveModel);
|
|
4777
|
+
const reasoningCapable = descriptor.reasoning;
|
|
4582
4778
|
const resolved = resolveThinkingOptions(options);
|
|
4583
4779
|
const { includeThoughts } = resolved;
|
|
4584
4780
|
const wireEffort = resolveOpenAIReasoningEffort(effectiveModel, resolved);
|
|
4585
|
-
const stripTemp =
|
|
4781
|
+
const stripTemp = stripsPortableSampling(descriptor, "responses", wireEffort);
|
|
4586
4782
|
const systemMessages = messages.filter((m) => m.role === "system");
|
|
4587
4783
|
const nonSystemMessages = messages.filter((m) => m.role !== "system");
|
|
4588
4784
|
const body = {
|
|
@@ -4631,6 +4827,7 @@ var OpenAIResponsesProvider = class {
|
|
|
4631
4827
|
if (options.providerOptions) {
|
|
4632
4828
|
Object.assign(body, options.providerOptions);
|
|
4633
4829
|
}
|
|
4830
|
+
validateOpenAIFinalRequestBody(body, "responses");
|
|
4634
4831
|
return body;
|
|
4635
4832
|
}
|
|
4636
4833
|
requestModel(body, fallback) {
|
|
@@ -4945,6 +5142,47 @@ function anthropicImageBlocks(parts, model) {
|
|
|
4945
5142
|
}
|
|
4946
5143
|
var ANTHROPIC_API_VERSION = "2023-06-01";
|
|
4947
5144
|
var ANTHROPIC_FILES_BETA = "files-api-2025-04-14";
|
|
5145
|
+
var ANTHROPIC_THINKING_BINDING_BETA = "thinking-binding-controls-2026-08-01";
|
|
5146
|
+
function isRecord(value) {
|
|
5147
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
5148
|
+
}
|
|
5149
|
+
function isFinalThinkingAdaptive(capability, body) {
|
|
5150
|
+
const thinking = body.thinking;
|
|
5151
|
+
if (thinking === void 0) {
|
|
5152
|
+
return capability.thinking === "adaptive-default-on" || capability.thinking === "adaptive-always-on";
|
|
5153
|
+
}
|
|
5154
|
+
return isRecord(thinking) && thinking.type === "adaptive";
|
|
5155
|
+
}
|
|
5156
|
+
var NATIVE_CLAUDE_EFFORTS = ["low", "medium", "high", "xhigh", "max"];
|
|
5157
|
+
function isNativeClaudeEffort(value) {
|
|
5158
|
+
return NATIVE_CLAUDE_EFFORTS.includes(value);
|
|
5159
|
+
}
|
|
5160
|
+
function hasReplayedThinking(body) {
|
|
5161
|
+
return Array.isArray(body.messages) && body.messages.some(
|
|
5162
|
+
(message) => isRecord(message) && Array.isArray(message.content) && message.content.some(
|
|
5163
|
+
(block) => isRecord(block) && (block.type === "thinking" || block.type === "redacted_thinking")
|
|
5164
|
+
)
|
|
5165
|
+
);
|
|
5166
|
+
}
|
|
5167
|
+
function hasFinalFileImage(body) {
|
|
5168
|
+
return Array.isArray(body.messages) && body.messages.some(
|
|
5169
|
+
(message) => isRecord(message) && Array.isArray(message.content) && message.content.some(
|
|
5170
|
+
(block) => isRecord(block) && block.type === "image" && isRecord(block.source) && block.source.type === "file"
|
|
5171
|
+
)
|
|
5172
|
+
);
|
|
5173
|
+
}
|
|
5174
|
+
function normalizeThinkingDrops(value) {
|
|
5175
|
+
if (!Array.isArray(value)) return void 0;
|
|
5176
|
+
const reasons = {};
|
|
5177
|
+
let droppedBlocks = 0;
|
|
5178
|
+
for (const entry of value) {
|
|
5179
|
+
if (!isRecord(entry) || entry.type !== "thinking_dropped") continue;
|
|
5180
|
+
const reason = entry.reason === "prefix_binding_mismatch" || entry.reason === "model_binding_mismatch" || entry.reason === "organization_binding_mismatch" || entry.reason === "end_user_binding_mismatch" ? entry.reason : "other";
|
|
5181
|
+
reasons[reason] = (reasons[reason] ?? 0) + 1;
|
|
5182
|
+
droppedBlocks++;
|
|
5183
|
+
}
|
|
5184
|
+
return droppedBlocks > 0 ? { droppedBlocks, reasons } : void 0;
|
|
5185
|
+
}
|
|
4948
5186
|
function hasAnthropicProviderFileImage(messages) {
|
|
4949
5187
|
return messages.some(
|
|
4950
5188
|
(message) => Array.isArray(message.content) && message.content.some(
|
|
@@ -4953,11 +5191,51 @@ function hasAnthropicProviderFileImage(messages) {
|
|
|
4953
5191
|
);
|
|
4954
5192
|
}
|
|
4955
5193
|
var CLAUDE_CAPABILITIES = {
|
|
5194
|
+
// Thinking off is `between_tools` (progress updates between tool calls);
|
|
5195
|
+
// `disabled` is a provider 400. Forced tool choice is a 400.
|
|
5196
|
+
"claude-sonnet-5-5": {
|
|
5197
|
+
thinking: "adaptive-default-on",
|
|
5198
|
+
effortLevels: ["low", "medium", "high", "xhigh", "max"],
|
|
5199
|
+
manualBudget: false,
|
|
5200
|
+
stripTemperature: true,
|
|
5201
|
+
disableAt: "high",
|
|
5202
|
+
offShape: "between_tools",
|
|
5203
|
+
forcedToolChoice: "rejected",
|
|
5204
|
+
defaultOnlySampling: true,
|
|
5205
|
+
strictThinking: true,
|
|
5206
|
+
thinkingBinding: true
|
|
5207
|
+
},
|
|
5208
|
+
// Thinking off is `disabled`, only at effort high or below. Forced tool
|
|
5209
|
+
// choice is accepted (the provider skips thinking for that turn).
|
|
5210
|
+
"claude-haiku-5-5": {
|
|
5211
|
+
thinking: "adaptive-default-on",
|
|
5212
|
+
effortLevels: ["low", "medium", "high", "xhigh", "max"],
|
|
5213
|
+
manualBudget: false,
|
|
5214
|
+
stripTemperature: true,
|
|
5215
|
+
disableAt: "high",
|
|
5216
|
+
defaultOnlySampling: true,
|
|
5217
|
+
strictThinking: true,
|
|
5218
|
+
thinkingBinding: true
|
|
5219
|
+
},
|
|
5220
|
+
"claude-opus-5-5": {
|
|
5221
|
+
thinking: "adaptive-always-on",
|
|
5222
|
+
effortLevels: ["low", "medium", "high", "xhigh", "max"],
|
|
5223
|
+
manualBudget: false,
|
|
5224
|
+
stripTemperature: true,
|
|
5225
|
+
forcedToolChoice: "rejected",
|
|
5226
|
+
defaultOnlySampling: true,
|
|
5227
|
+
strictThinking: true,
|
|
5228
|
+
thinkingBinding: true
|
|
5229
|
+
},
|
|
4956
5230
|
"claude-fable-5-1": {
|
|
4957
5231
|
thinking: "adaptive-always-on",
|
|
4958
5232
|
effortLevels: ["low", "medium", "high", "xhigh", "max"],
|
|
4959
5233
|
manualBudget: false,
|
|
4960
|
-
stripTemperature: true
|
|
5234
|
+
stripTemperature: true,
|
|
5235
|
+
forcedToolChoice: "rejected",
|
|
5236
|
+
defaultOnlySampling: true,
|
|
5237
|
+
strictThinking: true,
|
|
5238
|
+
thinkingBinding: true
|
|
4961
5239
|
},
|
|
4962
5240
|
"claude-fable-5": {
|
|
4963
5241
|
thinking: "adaptive-always-on",
|
|
@@ -5051,6 +5329,16 @@ function resolveClaudeCapability(model) {
|
|
|
5051
5329
|
}
|
|
5052
5330
|
var DEFAULT_CACHE_READ_MULTIPLIER = 0.1;
|
|
5053
5331
|
var ANTHROPIC_RATES = {
|
|
5332
|
+
// Sonnet 5.5 cache reads are 0.05x ($0.10/MTok): the pricing table, its
|
|
5333
|
+
// footnote, the models overview, and the prompt-caching guide agree
|
|
5334
|
+
// (re-checked 2026-10-07).
|
|
5335
|
+
"claude-sonnet-5-5": { input: 2e-6, output: 1e-5, cacheReadMultiplier: 0.05 },
|
|
5336
|
+
"claude-haiku-5-5": {
|
|
5337
|
+
input: 1e-7,
|
|
5338
|
+
output: 5e-7,
|
|
5339
|
+
longPrompt: { aboveTokens: 1e5, card: { input: 5e-7, output: 25e-7 } }
|
|
5340
|
+
},
|
|
5341
|
+
"claude-opus-5-5": { input: 4e-6, output: 2e-5, cacheReadMultiplier: 0.05 },
|
|
5054
5342
|
"claude-fable-5-1": { input: 1e-5, output: 5e-5, cacheReadMultiplier: 0.025 },
|
|
5055
5343
|
"claude-fable-5": { input: 1e-5, output: 5e-5 },
|
|
5056
5344
|
// Limited availability (Glasswing). Priced from the public pricing table; no
|
|
@@ -5112,14 +5400,16 @@ function estimateAnthropicCost(model, usage) {
|
|
|
5112
5400
|
return void 0;
|
|
5113
5401
|
}
|
|
5114
5402
|
const cacheWriteTotal = safeTokenSum(cacheWrite5m, cacheWrite1h);
|
|
5115
|
-
|
|
5403
|
+
const promptTokens = cacheWriteTotal === void 0 ? void 0 : safeTokenSum(usage.inputTokens, cacheRead, cacheWriteTotal);
|
|
5404
|
+
if (cacheWriteTotal === void 0 || promptTokens === void 0) {
|
|
5116
5405
|
return void 0;
|
|
5117
5406
|
}
|
|
5118
5407
|
if (usage.aggregateCacheWriteTokens !== void 0 && (!isValidTokenCount(usage.aggregateCacheWriteTokens) || usage.aggregateCacheWriteTokens !== cacheWriteTotal)) {
|
|
5119
5408
|
return void 0;
|
|
5120
5409
|
}
|
|
5121
|
-
const
|
|
5122
|
-
const
|
|
5410
|
+
const card = rate.longPrompt && promptTokens > rate.longPrompt.aboveTokens ? rate.longPrompt.card : rate;
|
|
5411
|
+
const { input, output } = card;
|
|
5412
|
+
const cacheReadRate = input * (card.cacheReadMultiplier ?? DEFAULT_CACHE_READ_MULTIPLIER);
|
|
5123
5413
|
return usage.inputTokens * input + cacheRead * cacheReadRate + cacheWrite5m * input * 1.25 + cacheWrite1h * input * 2 + usage.outputTokens * output;
|
|
5124
5414
|
}
|
|
5125
5415
|
var THINKING_BUDGETS = {
|
|
@@ -5181,7 +5471,7 @@ function resolveClaudeThinking(model, resolved) {
|
|
|
5181
5471
|
};
|
|
5182
5472
|
}
|
|
5183
5473
|
return {
|
|
5184
|
-
thinking: { type: "disabled" },
|
|
5474
|
+
thinking: { type: capability.offShape ?? "disabled" },
|
|
5185
5475
|
outputConfig: activeEffort ? { effort: activeEffort } : void 0,
|
|
5186
5476
|
stripTemperature: true
|
|
5187
5477
|
};
|
|
@@ -5485,11 +5775,12 @@ var AnthropicProvider = class {
|
|
|
5485
5775
|
// chat - non-streaming completion
|
|
5486
5776
|
// ---------------------------------------------------------------------------
|
|
5487
5777
|
async chat(messages, options) {
|
|
5778
|
+
const body = this.buildRequestBody(messages, options, false);
|
|
5488
5779
|
const headers = this.buildHeaders(
|
|
5489
5780
|
await this.resolveKey(),
|
|
5490
|
-
hasAnthropicProviderFileImage(messages)
|
|
5781
|
+
hasAnthropicProviderFileImage(messages) || hasFinalFileImage(body),
|
|
5782
|
+
this.requiresBindingBeta(body)
|
|
5491
5783
|
);
|
|
5492
|
-
const body = this.buildRequestBody(messages, options, false);
|
|
5493
5784
|
const pricingContext = pricingContextFromBody(body);
|
|
5494
5785
|
const recorder = new CallTimingRecorder(options.requestLifecycle);
|
|
5495
5786
|
const governor = this.governorFor(pricingContext.model ?? options.model);
|
|
@@ -5527,11 +5818,12 @@ var AnthropicProvider = class {
|
|
|
5527
5818
|
// stream - SSE streaming completion
|
|
5528
5819
|
// ---------------------------------------------------------------------------
|
|
5529
5820
|
async *stream(messages, options) {
|
|
5821
|
+
const body = this.buildRequestBody(messages, options, true);
|
|
5530
5822
|
const headers = this.buildHeaders(
|
|
5531
5823
|
await this.resolveKey(),
|
|
5532
|
-
hasAnthropicProviderFileImage(messages)
|
|
5824
|
+
hasAnthropicProviderFileImage(messages) || hasFinalFileImage(body),
|
|
5825
|
+
this.requiresBindingBeta(body)
|
|
5533
5826
|
);
|
|
5534
|
-
const body = this.buildRequestBody(messages, options, true);
|
|
5535
5827
|
const pricingContext = pricingContextFromBody(body);
|
|
5536
5828
|
const recorder = new CallTimingRecorder(options.requestLifecycle);
|
|
5537
5829
|
const governor = this.governorFor(pricingContext.model ?? options.model);
|
|
@@ -5573,14 +5865,119 @@ var AnthropicProvider = class {
|
|
|
5573
5865
|
// ---------------------------------------------------------------------------
|
|
5574
5866
|
// Internal: request building
|
|
5575
5867
|
// ---------------------------------------------------------------------------
|
|
5576
|
-
buildHeaders(apiKey, requiresFilesBeta = false) {
|
|
5868
|
+
buildHeaders(apiKey, requiresFilesBeta = false, requiresBindingBeta = false) {
|
|
5869
|
+
const betas = [
|
|
5870
|
+
...requiresFilesBeta ? [ANTHROPIC_FILES_BETA] : [],
|
|
5871
|
+
...requiresBindingBeta ? [ANTHROPIC_THINKING_BINDING_BETA] : []
|
|
5872
|
+
];
|
|
5577
5873
|
return {
|
|
5578
5874
|
"Content-Type": "application/json",
|
|
5579
5875
|
"x-api-key": apiKey,
|
|
5580
5876
|
"anthropic-version": ANTHROPIC_API_VERSION,
|
|
5581
|
-
...
|
|
5877
|
+
...betas.length > 0 ? { "anthropic-beta": betas.join(",") } : {}
|
|
5582
5878
|
};
|
|
5583
5879
|
}
|
|
5880
|
+
/**
|
|
5881
|
+
* Whether the final body needs the binding beta header. Runs after
|
|
5882
|
+
* `validateAndBindFinalBody`, which has already injected `block_binding`
|
|
5883
|
+
* wherever it applies, so the header follows the final body rather than
|
|
5884
|
+
* re-deriving the injection rule.
|
|
5885
|
+
*/
|
|
5886
|
+
requiresBindingBeta(body) {
|
|
5887
|
+
const capability = resolveClaudeCapability(String(body.model));
|
|
5888
|
+
const thinking = body.thinking;
|
|
5889
|
+
return capability?.thinkingBinding === true && isRecord(thinking) && thinking.type === "adaptive" && thinking.block_binding !== void 0;
|
|
5890
|
+
}
|
|
5891
|
+
/**
|
|
5892
|
+
* Validate the final body (after `providerOptions`) against the effective
|
|
5893
|
+
* model's capability, then inject `block_binding` where it applies. Every
|
|
5894
|
+
* rule is gated on its own capability field and is a no-op when unset, so a
|
|
5895
|
+
* model only gets the guards its provider contract calls for.
|
|
5896
|
+
*/
|
|
5897
|
+
validateAndBindFinalBody(body) {
|
|
5898
|
+
const model = typeof body.model === "string" ? body.model : "";
|
|
5899
|
+
const capability = resolveClaudeCapability(model);
|
|
5900
|
+
if (!capability) return;
|
|
5901
|
+
const reject = (option, remediation) => {
|
|
5902
|
+
throw new UnsupportedModelOptionError({ provider: this.name, model, option, remediation });
|
|
5903
|
+
};
|
|
5904
|
+
if (capability.forcedToolChoice === "rejected") {
|
|
5905
|
+
const toolChoice = body.tool_choice;
|
|
5906
|
+
if (isRecord(toolChoice) && (toolChoice.type === "any" || toolChoice.type === "tool")) {
|
|
5907
|
+
reject("forced tool choice", "Use toolChoice: 'auto' or 'none' on this model.");
|
|
5908
|
+
}
|
|
5909
|
+
}
|
|
5910
|
+
if (capability.strictThinking) {
|
|
5911
|
+
const offShape = capability.thinking === "adaptive-always-on" ? void 0 : capability.offShape ?? "disabled";
|
|
5912
|
+
const thinking = body.thinking;
|
|
5913
|
+
const outputConfig = body.output_config;
|
|
5914
|
+
const effort = isRecord(outputConfig) ? outputConfig.effort : void 0;
|
|
5915
|
+
if (thinking !== void 0 && offShape === void 0) {
|
|
5916
|
+
if (!isRecord(thinking) || thinking.type !== "adaptive" || thinking.budget_tokens !== void 0) {
|
|
5917
|
+
reject(
|
|
5918
|
+
"manual or disabled thinking",
|
|
5919
|
+
"Use thinking: { type: 'adaptive' } and output_config.effort."
|
|
5920
|
+
);
|
|
5921
|
+
}
|
|
5922
|
+
} else if (thinking !== void 0) {
|
|
5923
|
+
if (!isRecord(thinking) || thinking.type !== "adaptive" && thinking.type !== offShape) {
|
|
5924
|
+
reject(
|
|
5925
|
+
"thinking.type",
|
|
5926
|
+
`Use thinking: { type: 'adaptive' }, or { type: '${offShape}' } to turn thinking off.`
|
|
5927
|
+
);
|
|
5928
|
+
}
|
|
5929
|
+
const record = thinking;
|
|
5930
|
+
if (record.type === "adaptive" && record.budget_tokens !== void 0) {
|
|
5931
|
+
reject("thinking.budget_tokens", "Use output_config.effort instead of budget_tokens.");
|
|
5932
|
+
}
|
|
5933
|
+
if (record.type === offShape) {
|
|
5934
|
+
const extra = Object.keys(record).filter((key) => key !== "type");
|
|
5935
|
+
if (extra.length > 0) {
|
|
5936
|
+
reject(
|
|
5937
|
+
`thinking.${offShape}.${extra[0]}`,
|
|
5938
|
+
`Send thinking: { type: '${offShape}' } with no other fields.`
|
|
5939
|
+
);
|
|
5940
|
+
}
|
|
5941
|
+
}
|
|
5942
|
+
}
|
|
5943
|
+
if (outputConfig !== void 0 && (!isRecord(outputConfig) || effort !== void 0 && !isNativeClaudeEffort(effort))) {
|
|
5944
|
+
reject("output_config.effort", "Use low, medium, high, xhigh, or max effort.");
|
|
5945
|
+
}
|
|
5946
|
+
if (offShape !== void 0 && isRecord(thinking) && thinking.type === offShape && effort !== void 0 && capability.disableAt && !isEffortAtOrBelow(effort, capability.disableAt)) {
|
|
5947
|
+
reject(
|
|
5948
|
+
"output_config.effort",
|
|
5949
|
+
`Thinking can be turned off only at effort '${capability.disableAt}' or below; lower the effort or use adaptive thinking.`
|
|
5950
|
+
);
|
|
5951
|
+
}
|
|
5952
|
+
}
|
|
5953
|
+
if (capability.defaultOnlySampling) {
|
|
5954
|
+
if (body.temperature !== void 0 && body.temperature !== 1) {
|
|
5955
|
+
reject("temperature", "Omit temperature or use the default value 1.");
|
|
5956
|
+
}
|
|
5957
|
+
if (body.top_p !== void 0 && body.top_p !== 0.99) {
|
|
5958
|
+
reject("top_p", "Omit top_p or use the default value 0.99.");
|
|
5959
|
+
}
|
|
5960
|
+
if (body.temperature !== void 0 && body.top_p !== void 0) {
|
|
5961
|
+
reject("temperature and top_p", "Send at most one of temperature and top_p.");
|
|
5962
|
+
}
|
|
5963
|
+
if (body.top_k !== void 0) {
|
|
5964
|
+
reject("top_k", "Omit top_k on this model.");
|
|
5965
|
+
}
|
|
5966
|
+
}
|
|
5967
|
+
if (capability.thinkingBinding === true && isFinalThinkingAdaptive(capability, body)) {
|
|
5968
|
+
const thinking = isRecord(body.thinking) ? body.thinking : { type: "adaptive" };
|
|
5969
|
+
const binding = thinking.block_binding;
|
|
5970
|
+
if (binding !== void 0 && (!isRecord(binding) || binding.prefix_mismatch_behavior !== "error" && binding.prefix_mismatch_behavior !== "drop_block")) {
|
|
5971
|
+
reject("thinking.block_binding", "Use prefix_mismatch_behavior: 'error' or 'drop_block'.");
|
|
5972
|
+
}
|
|
5973
|
+
if (hasReplayedThinking(body)) {
|
|
5974
|
+
body.thinking = {
|
|
5975
|
+
...thinking,
|
|
5976
|
+
block_binding: binding ?? { prefix_mismatch_behavior: "drop_block" }
|
|
5977
|
+
};
|
|
5978
|
+
}
|
|
5979
|
+
}
|
|
5980
|
+
}
|
|
5584
5981
|
/** Extract a human-readable message from an API error response body. */
|
|
5585
5982
|
extractErrorMessage(body, status) {
|
|
5586
5983
|
try {
|
|
@@ -5657,6 +6054,7 @@ ${jsonInstruction}` : jsonInstruction;
|
|
|
5657
6054
|
if (options.providerOptions) {
|
|
5658
6055
|
Object.assign(body, options.providerOptions);
|
|
5659
6056
|
}
|
|
6057
|
+
this.validateAndBindFinalBody(body);
|
|
5660
6058
|
return body;
|
|
5661
6059
|
}
|
|
5662
6060
|
/**
|
|
@@ -5813,6 +6211,7 @@ ${jsonInstruction}` : jsonInstruction;
|
|
|
5813
6211
|
}
|
|
5814
6212
|
}
|
|
5815
6213
|
const normalized = json.usage ? normalizeAnthropicUsage(json.usage) : void 0;
|
|
6214
|
+
const reasoningContextReset = normalizeThinkingDrops(json.input_transformations);
|
|
5816
6215
|
const effectiveModel = typeof json.model === "string" ? json.model : pricingContext.model;
|
|
5817
6216
|
if (hasFallbackBoundary) {
|
|
5818
6217
|
throw new Error(
|
|
@@ -5827,7 +6226,8 @@ ${jsonInstruction}` : jsonInstruction;
|
|
|
5827
6226
|
usage: normalized?.usage,
|
|
5828
6227
|
cost,
|
|
5829
6228
|
costProvenance: tableEstimate(cost),
|
|
5830
|
-
providerMetadata: thinkingBlocks.length > 0 && !hasFallbackBoundary ? { anthropicThinkingBlocks: thinkingBlocks } : void 0
|
|
6229
|
+
providerMetadata: thinkingBlocks.length > 0 && !hasFallbackBoundary ? { anthropicThinkingBlocks: thinkingBlocks } : void 0,
|
|
6230
|
+
...reasoningContextReset ? { diagnostics: { reasoningContextReset } } : {}
|
|
5831
6231
|
};
|
|
5832
6232
|
}
|
|
5833
6233
|
// ---------------------------------------------------------------------------
|
|
@@ -5849,6 +6249,7 @@ ${jsonInstruction}` : jsonInstruction;
|
|
|
5849
6249
|
let hasFallbackBoundary = false;
|
|
5850
6250
|
let hasFallbackIterationSignal = false;
|
|
5851
6251
|
let refused = false;
|
|
6252
|
+
let reasoningContextReset;
|
|
5852
6253
|
const finalizeUsage = () => {
|
|
5853
6254
|
const normalized = rawUsage ? normalizeAnthropicUsage(rawUsage) : void 0;
|
|
5854
6255
|
usage = normalized?.usage;
|
|
@@ -5861,7 +6262,8 @@ ${jsonInstruction}` : jsonInstruction;
|
|
|
5861
6262
|
usage,
|
|
5862
6263
|
cost,
|
|
5863
6264
|
costProvenance: tableEstimate(cost),
|
|
5864
|
-
providerMetadata: thinkingBlocks.length > 0 && !hasFallbackBoundary && !hasFallbackIterationSignal ? { anthropicThinkingBlocks: thinkingBlocks } : void 0
|
|
6265
|
+
providerMetadata: thinkingBlocks.length > 0 && !hasFallbackBoundary && !hasFallbackIterationSignal ? { anthropicThinkingBlocks: thinkingBlocks } : void 0,
|
|
6266
|
+
...reasoningContextReset ? { diagnostics: { reasoningContextReset } } : {}
|
|
5865
6267
|
};
|
|
5866
6268
|
};
|
|
5867
6269
|
try {
|
|
@@ -5954,6 +6356,7 @@ ${jsonInstruction}` : jsonInstruction;
|
|
|
5954
6356
|
rawUsage = mergeAnthropicUsage(rawUsage, event.message.usage);
|
|
5955
6357
|
}
|
|
5956
6358
|
if (typeof event.message?.model === "string") effectiveModel = event.message.model;
|
|
6359
|
+
reasoningContextReset = normalizeThinkingDrops(event.message?.input_transformations);
|
|
5957
6360
|
const messageFallback = hasFallbackIteration(event.message?.usage?.iterations);
|
|
5958
6361
|
if (isAnthropicResponseModifier(
|
|
5959
6362
|
"inference_geo",
|
|
@@ -5970,6 +6373,10 @@ ${jsonInstruction}` : jsonInstruction;
|
|
|
5970
6373
|
break;
|
|
5971
6374
|
}
|
|
5972
6375
|
case "message_delta": {
|
|
6376
|
+
const finalTransformations = event.input_transformations ?? event.delta?.input_transformations;
|
|
6377
|
+
if (finalTransformations !== void 0) {
|
|
6378
|
+
reasoningContextReset = normalizeThinkingDrops(finalTransformations);
|
|
6379
|
+
}
|
|
5973
6380
|
if (event.usage) {
|
|
5974
6381
|
rawUsage = mergeAnthropicUsage(rawUsage, event.usage);
|
|
5975
6382
|
finalizeUsage();
|
|
@@ -6198,7 +6605,31 @@ var GEMINI_PRICING = {
|
|
|
6198
6605
|
},
|
|
6199
6606
|
"gemini-3.8-flash": { input: 75e-8, cached: 75e-9, output: 375e-8 }
|
|
6200
6607
|
};
|
|
6608
|
+
var GEMINI_FLASH_SUCCESSOR_PRICING = {
|
|
6609
|
+
...GEMINI_PRICING,
|
|
6610
|
+
"gemini-3.6-flash": { input: 15e-7, cached: 15e-8, output: 75e-7 },
|
|
6611
|
+
"gemini-3.7-flash": {
|
|
6612
|
+
input: 15e-7,
|
|
6613
|
+
cached: 15e-8,
|
|
6614
|
+
output: 75e-7,
|
|
6615
|
+
audioInput: 15e-7
|
|
6616
|
+
},
|
|
6617
|
+
"gemini-3.8-flash": { input: 15e-7, cached: 15e-8, output: 75e-7 }
|
|
6618
|
+
};
|
|
6619
|
+
var GEMINI_FLASH_SUCCESSOR_START_MS = Date.UTC(2027, 0, 1);
|
|
6620
|
+
function geminiRatesAtDispatch(at) {
|
|
6621
|
+
return at < GEMINI_FLASH_SUCCESSOR_START_MS ? GEMINI_PRICING : GEMINI_FLASH_SUCCESSOR_PRICING;
|
|
6622
|
+
}
|
|
6201
6623
|
var CANONICAL_GEMINI_BASE_URL = GEMINI_DEFAULT_BASE_URL;
|
|
6624
|
+
function geminiPricingTimingObserver(context, recorder) {
|
|
6625
|
+
return {
|
|
6626
|
+
...recorder.observer,
|
|
6627
|
+
onDispatch: (attempt, at) => {
|
|
6628
|
+
context.rates = geminiRatesAtDispatch(at);
|
|
6629
|
+
recorder.observer.onDispatch?.(attempt, at);
|
|
6630
|
+
}
|
|
6631
|
+
};
|
|
6632
|
+
}
|
|
6202
6633
|
function isValidTokenCount2(value) {
|
|
6203
6634
|
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
6204
6635
|
}
|
|
@@ -6279,8 +6710,8 @@ function geminiInteractionErrorStatus(code) {
|
|
|
6279
6710
|
function isEligibleGeminiPricing(context, hasDefinitiveStandardResponseTier, hasInvalidResponseTier) {
|
|
6280
6711
|
return context.eligibleRequest && isStandardGeminiRequestTier(context.serviceTier) && hasDefinitiveStandardResponseTier && !hasInvalidResponseTier;
|
|
6281
6712
|
}
|
|
6282
|
-
function estimateGeminiCost(model, usage) {
|
|
6283
|
-
const pricing =
|
|
6713
|
+
function estimateGeminiCost(model, usage, rates) {
|
|
6714
|
+
const pricing = rates && Object.hasOwn(rates, model) ? rates[model] : void 0;
|
|
6284
6715
|
const cached = usage.cachedTokens ?? 0;
|
|
6285
6716
|
if (!pricing || !isValidTokenCount2(usage.inputTokens) || !isValidTokenCount2(usage.outputTokens) || !isValidTokenCount2(cached) || cached > usage.inputTokens) {
|
|
6286
6717
|
return void 0;
|
|
@@ -6608,7 +7039,7 @@ var GeminiProvider = class {
|
|
|
6608
7039
|
{
|
|
6609
7040
|
governor: this.governorFor(pricingContext.model),
|
|
6610
7041
|
provider: this.name,
|
|
6611
|
-
timing: recorder
|
|
7042
|
+
timing: geminiPricingTimingObserver(pricingContext, recorder),
|
|
6612
7043
|
admission: options.dispatchAdmission
|
|
6613
7044
|
}
|
|
6614
7045
|
);
|
|
@@ -6651,7 +7082,7 @@ var GeminiProvider = class {
|
|
|
6651
7082
|
{
|
|
6652
7083
|
governor: this.governorFor(pricingContext.model),
|
|
6653
7084
|
provider: this.name,
|
|
6654
|
-
timing: recorder
|
|
7085
|
+
timing: geminiPricingTimingObserver(pricingContext, recorder),
|
|
6655
7086
|
admission: options.dispatchAdmission
|
|
6656
7087
|
}
|
|
6657
7088
|
);
|
|
@@ -6689,7 +7120,7 @@ var GeminiProvider = class {
|
|
|
6689
7120
|
{
|
|
6690
7121
|
governor: this.governorFor(pricingContext.model),
|
|
6691
7122
|
provider: this.name,
|
|
6692
|
-
timing: recorder
|
|
7123
|
+
timing: geminiPricingTimingObserver(pricingContext, recorder),
|
|
6693
7124
|
admission: options.dispatchAdmission
|
|
6694
7125
|
}
|
|
6695
7126
|
);
|
|
@@ -6725,7 +7156,7 @@ var GeminiProvider = class {
|
|
|
6725
7156
|
{
|
|
6726
7157
|
governor: this.governorFor(pricingContext.model),
|
|
6727
7158
|
provider: this.name,
|
|
6728
|
-
timing: recorder
|
|
7159
|
+
timing: geminiPricingTimingObserver(pricingContext, recorder),
|
|
6729
7160
|
admission: options.dispatchAdmission
|
|
6730
7161
|
}
|
|
6731
7162
|
);
|
|
@@ -6944,7 +7375,7 @@ var GeminiProvider = class {
|
|
|
6944
7375
|
)) {
|
|
6945
7376
|
return void 0;
|
|
6946
7377
|
}
|
|
6947
|
-
return estimateGeminiCost(effectiveModel, normalized.pricingUsage);
|
|
7378
|
+
return estimateGeminiCost(effectiveModel, normalized.pricingUsage, pricingContext.rates);
|
|
6948
7379
|
}
|
|
6949
7380
|
/**
|
|
6950
7381
|
* Whether every model-produced step is text. A non-text reply part (image,
|
|
@@ -7529,7 +7960,7 @@ var GeminiProvider = class {
|
|
|
7529
7960
|
pricingContext,
|
|
7530
7961
|
isDefinitiveStandardGeminiResponseTier(json.usageMetadata?.serviceTier),
|
|
7531
7962
|
json.usageMetadata?.serviceTier !== void 0 && !isDefinitiveStandardGeminiResponseTier(json.usageMetadata.serviceTier)
|
|
7532
|
-
) ? estimateGeminiCost(effectiveModel, normalized.pricingUsage) : void 0;
|
|
7963
|
+
) ? estimateGeminiCost(effectiveModel, normalized.pricingUsage, pricingContext.rates) : void 0;
|
|
7533
7964
|
const rawParts = candidate?.content?.parts;
|
|
7534
7965
|
const providerMetadata = rawParts ? { geminiParts: rawParts } : void 0;
|
|
7535
7966
|
return {
|
|
@@ -7620,7 +8051,7 @@ var GeminiProvider = class {
|
|
|
7620
8051
|
pricingContext,
|
|
7621
8052
|
hasDefinitiveStandardResponseTier,
|
|
7622
8053
|
hasInvalidResponseTier
|
|
7623
|
-
) ? estimateGeminiCost(effectiveModel, normalizedUsage.pricingUsage) : void 0;
|
|
8054
|
+
) ? estimateGeminiCost(effectiveModel, normalizedUsage.pricingUsage, pricingContext.rates) : void 0;
|
|
7624
8055
|
yield {
|
|
7625
8056
|
type: "done",
|
|
7626
8057
|
usage: normalizedUsage?.usage,
|
|
@@ -9270,7 +9701,7 @@ var TranscriptionProviderRegistry = class {
|
|
|
9270
9701
|
|
|
9271
9702
|
// src/context.ts
|
|
9272
9703
|
var import_node_async_hooks3 = require("async_hooks");
|
|
9273
|
-
var
|
|
9704
|
+
var import_node_crypto2 = require("crypto");
|
|
9274
9705
|
var import_zod2 = require("zod");
|
|
9275
9706
|
|
|
9276
9707
|
// src/input.ts
|
|
@@ -9533,6 +9964,95 @@ function sessionHistoryForAsk(history, normalizedInput) {
|
|
|
9533
9964
|
return snapshot;
|
|
9534
9965
|
}
|
|
9535
9966
|
|
|
9967
|
+
// src/compaction.ts
|
|
9968
|
+
var import_node_crypto = require("crypto");
|
|
9969
|
+
var SUMMARY_SYSTEM_PROMPT = "Summarize the following conversation concisely, preserving key facts, decisions, and context needed for continuing the conversation.";
|
|
9970
|
+
var SUMMARY_MAX_TOKENS = 1024;
|
|
9971
|
+
function buildSummaryPrompt(messages, previousSummary) {
|
|
9972
|
+
return [
|
|
9973
|
+
...previousSummary ? [`Previous conversation summary: ${previousSummary}`] : [],
|
|
9974
|
+
...messages.map((m) => `${m.role}: ${summarizeModelInput(m.content)}`)
|
|
9975
|
+
].join("\n");
|
|
9976
|
+
}
|
|
9977
|
+
function requestSummary(provider, options) {
|
|
9978
|
+
return provider.chat(
|
|
9979
|
+
[
|
|
9980
|
+
{ role: "system", content: SUMMARY_SYSTEM_PROMPT },
|
|
9981
|
+
{ role: "user", content: options.prompt }
|
|
9982
|
+
],
|
|
9983
|
+
{
|
|
9984
|
+
model: options.model,
|
|
9985
|
+
maxTokens: SUMMARY_MAX_TOKENS,
|
|
9986
|
+
...options.signal ? { signal: options.signal } : {}
|
|
9987
|
+
}
|
|
9988
|
+
);
|
|
9989
|
+
}
|
|
9990
|
+
function summaryContextMessage(summary) {
|
|
9991
|
+
return {
|
|
9992
|
+
role: "system",
|
|
9993
|
+
origin: "runtime",
|
|
9994
|
+
content: `Summary of earlier conversation:
|
|
9995
|
+
${summary}`
|
|
9996
|
+
};
|
|
9997
|
+
}
|
|
9998
|
+
function withoutAnthropicThinking(message) {
|
|
9999
|
+
const metadata = message.providerMetadata;
|
|
10000
|
+
if (!metadata || !Object.hasOwn(metadata, "anthropicThinkingBlocks")) return message;
|
|
10001
|
+
const retainedMetadata = { ...metadata };
|
|
10002
|
+
delete retainedMetadata.anthropicThinkingBlocks;
|
|
10003
|
+
return {
|
|
10004
|
+
...message,
|
|
10005
|
+
...Object.keys(retainedMetadata).length > 0 ? { providerMetadata: retainedMetadata } : { providerMetadata: void 0 }
|
|
10006
|
+
};
|
|
10007
|
+
}
|
|
10008
|
+
function anthropicThinkingBlockCount(message) {
|
|
10009
|
+
const blocks = message.providerMetadata?.anthropicThinkingBlocks;
|
|
10010
|
+
if (!Array.isArray(blocks)) return 0;
|
|
10011
|
+
return blocks.filter(
|
|
10012
|
+
(block) => block !== null && typeof block === "object" && (block.type === "thinking" || block.type === "redacted_thinking")
|
|
10013
|
+
).length;
|
|
10014
|
+
}
|
|
10015
|
+
function askSummaryMetaKey(agentName) {
|
|
10016
|
+
return `askSummary:${agentName}`;
|
|
10017
|
+
}
|
|
10018
|
+
function isCount(value) {
|
|
10019
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
10020
|
+
}
|
|
10021
|
+
function parseAskSummaryRecord(value) {
|
|
10022
|
+
if (!value || typeof value !== "object") return void 0;
|
|
10023
|
+
const record = value;
|
|
10024
|
+
if (typeof record.summary !== "string" || !isCount(record.coveredCount) || typeof record.prefixHash !== "string" || typeof record.summaryModelUri !== "string" || !isCount(record.invalidatedThinkingThrough) || record.sourceSummary !== void 0 && typeof record.sourceSummary !== "string") {
|
|
10025
|
+
return void 0;
|
|
10026
|
+
}
|
|
10027
|
+
return {
|
|
10028
|
+
summary: record.summary,
|
|
10029
|
+
coveredCount: record.coveredCount,
|
|
10030
|
+
prefixHash: record.prefixHash,
|
|
10031
|
+
...record.sourceSummary !== void 0 ? { sourceSummary: record.sourceSummary } : {},
|
|
10032
|
+
summaryModelUri: record.summaryModelUri,
|
|
10033
|
+
invalidatedThinkingThrough: record.invalidatedThinkingThrough
|
|
10034
|
+
};
|
|
10035
|
+
}
|
|
10036
|
+
function isPlainObject(value) {
|
|
10037
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
|
|
10038
|
+
const proto = Object.getPrototypeOf(value);
|
|
10039
|
+
return proto === Object.prototype || proto === null;
|
|
10040
|
+
}
|
|
10041
|
+
function summaryPrefixHash(history, coveredCount) {
|
|
10042
|
+
let canonical;
|
|
10043
|
+
try {
|
|
10044
|
+
canonical = JSON.stringify(
|
|
10045
|
+
history.slice(0, coveredCount),
|
|
10046
|
+
(_key, value) => isPlainObject(value) ? Object.fromEntries(
|
|
10047
|
+
Object.keys(value).sort().map((key) => [key, value[key]])
|
|
10048
|
+
) : value
|
|
10049
|
+
);
|
|
10050
|
+
} catch {
|
|
10051
|
+
return void 0;
|
|
10052
|
+
}
|
|
10053
|
+
return (0, import_node_crypto.createHash)("sha256").update(canonical).digest("hex");
|
|
10054
|
+
}
|
|
10055
|
+
|
|
9536
10056
|
// src/partial-json.ts
|
|
9537
10057
|
var MAX_DEPTH = 256;
|
|
9538
10058
|
function parsePartialJson(input) {
|
|
@@ -11169,9 +11689,9 @@ var LEGACY_REDACTION_RULES = {
|
|
|
11169
11689
|
// which is user content or PII (field paths are schema-shape, preserved like
|
|
11170
11690
|
// `string_delta.path`). Passthrough, as an explicit reviewed decision.
|
|
11171
11691
|
schema_diagnostic: passthrough,
|
|
11172
|
-
// `provider_diagnostic` carries only provider
|
|
11173
|
-
//
|
|
11174
|
-
//
|
|
11692
|
+
// `provider_diagnostic` carries only provider/model metadata, effort levels,
|
|
11693
|
+
// and bounded dropped-thinking reason counts. Raw transformation paths and
|
|
11694
|
+
// signed thinking never enter this event. Passthrough is reviewed here.
|
|
11175
11695
|
provider_diagnostic: passthrough,
|
|
11176
11696
|
log: (e) => {
|
|
11177
11697
|
if (!e.data || typeof e.data !== "object" || Array.isArray(e.data)) return e;
|
|
@@ -13176,7 +13696,14 @@ var WorkflowContext = class _WorkflowContext {
|
|
|
13176
13696
|
* suppresses late branch events after bounded finalization. */
|
|
13177
13697
|
workflowLifecycleState;
|
|
13178
13698
|
signal;
|
|
13179
|
-
|
|
13699
|
+
/** Durable summary of messages removed by Session.history.maxMessages. */
|
|
13700
|
+
sessionSummary;
|
|
13701
|
+
/** Per-agent `maxContext` summaries, keyed by agent name. `null` records a
|
|
13702
|
+
* store lookup that found nothing. Mirrored to session metadata
|
|
13703
|
+
* (`askSummary:<agent>`) when this execution belongs to a session, so a
|
|
13704
|
+
* later execution can reuse the same exact-prefix boundary. Never the
|
|
13705
|
+
* durable `sessionSummary`. */
|
|
13706
|
+
askSummaries = /* @__PURE__ */ new Map();
|
|
13180
13707
|
/** Consecutive provider calls with promptCache on that wrote to the cache
|
|
13181
13708
|
* without reading from it (prefix changes per call), and consecutive calls
|
|
13182
13709
|
* with no cache activity at all (prefix below the model's minimum, which
|
|
@@ -13352,7 +13879,7 @@ var WorkflowContext = class _WorkflowContext {
|
|
|
13352
13879
|
endEmitted: false
|
|
13353
13880
|
};
|
|
13354
13881
|
if (init.metadata?.summaryCache) {
|
|
13355
|
-
this.
|
|
13882
|
+
this.sessionSummary = init.metadata.summaryCache;
|
|
13356
13883
|
}
|
|
13357
13884
|
}
|
|
13358
13885
|
/**
|
|
@@ -13680,7 +14207,7 @@ var WorkflowContext = class _WorkflowContext {
|
|
|
13680
14207
|
this._autoCheckpointName("ask", agentName),
|
|
13681
14208
|
async () => {
|
|
13682
14209
|
const parentFrame = askStorage.getStore();
|
|
13683
|
-
const askId = (0,
|
|
14210
|
+
const askId = (0, import_node_crypto2.randomUUID)();
|
|
13684
14211
|
const depth = (parentFrame?.depth ?? -1) + 1;
|
|
13685
14212
|
const stepRef = parentFrame?.stepRef ?? this.stepRefRoot;
|
|
13686
14213
|
const frame = {
|
|
@@ -13977,6 +14504,7 @@ var WorkflowContext = class _WorkflowContext {
|
|
|
13977
14504
|
if (systemPrompt) {
|
|
13978
14505
|
messages.push({ role: "system", content: systemPrompt });
|
|
13979
14506
|
}
|
|
14507
|
+
const cachedSummaryMessage = this.sessionSummary ? summaryContextMessage(this.sessionSummary) : void 0;
|
|
13980
14508
|
const maxContext = agent2._config.maxContext;
|
|
13981
14509
|
if (maxContext && sessionHistory.length > 0) {
|
|
13982
14510
|
const reserveTokens = this.config.contextManagement?.reserveTokens ?? 2e3;
|
|
@@ -14001,22 +14529,44 @@ var WorkflowContext = class _WorkflowContext {
|
|
|
14001
14529
|
}
|
|
14002
14530
|
});
|
|
14003
14531
|
}
|
|
14004
|
-
|
|
14005
|
-
|
|
14532
|
+
const summaryTokens = cachedSummaryMessage ? estimateMessagesTokens([cachedSummaryMessage]).tokens : 0;
|
|
14533
|
+
if (historyEstimate.tokens + summaryTokens > availableForHistory) {
|
|
14534
|
+
const projection = await this.summarizeHistory(
|
|
14535
|
+
agent2._name,
|
|
14536
|
+
modelUri,
|
|
14006
14537
|
provider,
|
|
14007
14538
|
model,
|
|
14008
14539
|
sessionHistory,
|
|
14009
14540
|
availableForHistory
|
|
14010
14541
|
);
|
|
14011
|
-
|
|
14542
|
+
if (this.budgetContext?.exceeded && this.budgetContext.policy !== "warn") {
|
|
14543
|
+
const { limit, totalCost: spent, policy } = this.budgetContext;
|
|
14544
|
+
throw new BudgetExceededError(limit, spent, policy);
|
|
14545
|
+
}
|
|
14546
|
+
if (projection.removedThinkingBlocks > 0) {
|
|
14547
|
+
this.emitEvent({
|
|
14548
|
+
type: "provider_diagnostic",
|
|
14549
|
+
agent: agent2._name,
|
|
14550
|
+
data: {
|
|
14551
|
+
kind: "reasoning_context_reset",
|
|
14552
|
+
...provider.name ? { provider: provider.name } : {},
|
|
14553
|
+
model: typeof providerOptions?.model === "string" ? providerOptions.model : model,
|
|
14554
|
+
droppedBlocks: projection.removedThinkingBlocks,
|
|
14555
|
+
reasons: { client_prefix_rewrite: projection.removedThinkingBlocks }
|
|
14556
|
+
}
|
|
14557
|
+
});
|
|
14558
|
+
}
|
|
14559
|
+
for (const msg of projection.messages) {
|
|
14012
14560
|
messages.push(msg);
|
|
14013
14561
|
}
|
|
14014
14562
|
} else {
|
|
14563
|
+
if (cachedSummaryMessage) messages.push(cachedSummaryMessage);
|
|
14015
14564
|
for (const msg of sessionHistory) {
|
|
14016
14565
|
messages.push(msg);
|
|
14017
14566
|
}
|
|
14018
14567
|
}
|
|
14019
14568
|
} else {
|
|
14569
|
+
if (cachedSummaryMessage) messages.push(cachedSummaryMessage);
|
|
14020
14570
|
for (const msg of sessionHistory) {
|
|
14021
14571
|
messages.push(msg);
|
|
14022
14572
|
}
|
|
@@ -14117,6 +14667,7 @@ ${appendedSchemaText}`;
|
|
|
14117
14667
|
}
|
|
14118
14668
|
const startTime = Date.now();
|
|
14119
14669
|
const askClock = currentAskClock();
|
|
14670
|
+
const pausedAtStartMs = askClock ? pausedAskClockMs(askClock, startTime) : 0;
|
|
14120
14671
|
const timingTotals = { turns: 0, queuedMs: 0, retryMs: 0, wireMs: 0 };
|
|
14121
14672
|
const currentMessages = [...messages];
|
|
14122
14673
|
let turns = 0;
|
|
@@ -14134,7 +14685,7 @@ ${appendedSchemaText}`;
|
|
|
14134
14685
|
this.currentSignal?.throwIfAborted();
|
|
14135
14686
|
const now = Date.now();
|
|
14136
14687
|
const elapsedMs = now - startTime;
|
|
14137
|
-
const pausedMs = askClock ? pausedAskClockMs(askClock, now) : 0;
|
|
14688
|
+
const pausedMs = askClock ? Math.max(0, pausedAskClockMs(askClock, now) - pausedAtStartMs) : 0;
|
|
14138
14689
|
const chargedMs = Math.max(0, elapsedMs - Math.min(pausedMs, Math.max(0, elapsedMs)));
|
|
14139
14690
|
if (chargedMs > timeoutMs) {
|
|
14140
14691
|
throw new TimeoutError(
|
|
@@ -14389,6 +14940,7 @@ ${appendedSchemaText}`;
|
|
|
14389
14940
|
usage: chunk.usage,
|
|
14390
14941
|
cost: chunk.cost,
|
|
14391
14942
|
providerMetadata: chunk.providerMetadata,
|
|
14943
|
+
diagnostics: chunk.diagnostics,
|
|
14392
14944
|
timing: chunk.timing
|
|
14393
14945
|
};
|
|
14394
14946
|
}
|
|
@@ -14506,6 +15058,34 @@ ${appendedSchemaText}`;
|
|
|
14506
15058
|
timingTotals.retryMs += response.timing.retryMs;
|
|
14507
15059
|
timingTotals.wireMs += response.timing.wireMs;
|
|
14508
15060
|
}
|
|
15061
|
+
const reasoningReset = response.diagnostics?.reasoningContextReset;
|
|
15062
|
+
if (reasoningReset && Number.isSafeInteger(reasoningReset.droppedBlocks) && reasoningReset.droppedBlocks > 0) {
|
|
15063
|
+
const reasons = {};
|
|
15064
|
+
for (const reason of [
|
|
15065
|
+
"prefix_binding_mismatch",
|
|
15066
|
+
"model_binding_mismatch",
|
|
15067
|
+
"organization_binding_mismatch",
|
|
15068
|
+
"end_user_binding_mismatch",
|
|
15069
|
+
"client_prefix_rewrite",
|
|
15070
|
+
"other"
|
|
15071
|
+
]) {
|
|
15072
|
+
const count = reasoningReset.reasons?.[reason];
|
|
15073
|
+
if (typeof count === "number" && Number.isSafeInteger(count) && count > 0) {
|
|
15074
|
+
reasons[reason] = count;
|
|
15075
|
+
}
|
|
15076
|
+
}
|
|
15077
|
+
this.emitEvent({
|
|
15078
|
+
type: "provider_diagnostic",
|
|
15079
|
+
agent: agent2._name,
|
|
15080
|
+
data: {
|
|
15081
|
+
kind: "reasoning_context_reset",
|
|
15082
|
+
...provider.name ? { provider: provider.name } : {},
|
|
15083
|
+
model: typeof providerOptions?.model === "string" ? providerOptions.model : model,
|
|
15084
|
+
droppedBlocks: reasoningReset.droppedBlocks,
|
|
15085
|
+
reasons
|
|
15086
|
+
}
|
|
15087
|
+
});
|
|
15088
|
+
}
|
|
14509
15089
|
this.emitEvent({
|
|
14510
15090
|
type: "agent_call_end",
|
|
14511
15091
|
agent: agent2._name,
|
|
@@ -14556,7 +15136,7 @@ ${appendedSchemaText}`;
|
|
|
14556
15136
|
const sourceFrame = askStorage.getStore();
|
|
14557
15137
|
const handoffFromAskId = sourceFrame?.askId ?? this.executionId;
|
|
14558
15138
|
const handoffSourceDepth = sourceFrame?.depth ?? 0;
|
|
14559
|
-
const handoffToAskId = (0,
|
|
15139
|
+
const handoffToAskId = (0, import_node_crypto2.randomUUID)();
|
|
14560
15140
|
const handoffTargetDepth = handoffSourceDepth + 1;
|
|
14561
15141
|
const targetFrame = {
|
|
14562
15142
|
askId: handoffToAskId,
|
|
@@ -15248,31 +15828,65 @@ ${appendedSchemaText}`;
|
|
|
15248
15828
|
}
|
|
15249
15829
|
return defs;
|
|
15250
15830
|
}
|
|
15831
|
+
/** Session id for session-scoped ask-summary persistence, when this
|
|
15832
|
+
* execution belongs to a session and has a store to persist into. */
|
|
15833
|
+
askSummarySessionId() {
|
|
15834
|
+
const sessionId = this.metadata?.sessionId;
|
|
15835
|
+
if (this.metadata?.sessionPersist === false) return void 0;
|
|
15836
|
+
return this.stateStore && typeof sessionId === "string" && sessionId.length > 0 ? sessionId : void 0;
|
|
15837
|
+
}
|
|
15838
|
+
/** This agent's ask summary: the in-memory copy first, else the session's
|
|
15839
|
+
* persisted record (read once per execution). */
|
|
15840
|
+
async loadAskSummary(agentName) {
|
|
15841
|
+
if (this.askSummaries.has(agentName)) return this.askSummaries.get(agentName) ?? void 0;
|
|
15842
|
+
const sessionId = this.askSummarySessionId();
|
|
15843
|
+
const stored = sessionId ? parseAskSummaryRecord(
|
|
15844
|
+
await this.stateStore.getSessionMeta(sessionId, askSummaryMetaKey(agentName))
|
|
15845
|
+
) : void 0;
|
|
15846
|
+
this.askSummaries.set(agentName, stored ?? null);
|
|
15847
|
+
return stored;
|
|
15848
|
+
}
|
|
15849
|
+
async saveAskSummary(agentName, record) {
|
|
15850
|
+
this.askSummaries.set(agentName, record);
|
|
15851
|
+
const sessionId = this.askSummarySessionId();
|
|
15852
|
+
if (!sessionId) return;
|
|
15853
|
+
const key = askSummaryMetaKey(agentName);
|
|
15854
|
+
try {
|
|
15855
|
+
await this.stateStore.saveSessionMeta(sessionId, key, record);
|
|
15856
|
+
} catch (error) {
|
|
15857
|
+
this.emitEvent({
|
|
15858
|
+
type: "log",
|
|
15859
|
+
agent: agentName,
|
|
15860
|
+
data: {
|
|
15861
|
+
warning: `Could not persist ask summary '${key}' for session '${sessionId}'; later executions will regenerate it. ` + (error instanceof Error ? error.message : String(error))
|
|
15862
|
+
}
|
|
15863
|
+
});
|
|
15864
|
+
}
|
|
15865
|
+
}
|
|
15251
15866
|
/**
|
|
15252
|
-
*
|
|
15253
|
-
*
|
|
15867
|
+
* Project `history` into `availableTokens` for one agent's request: a summary
|
|
15868
|
+
* of an exact covered prefix followed by every later message. Reuses the
|
|
15869
|
+
* agent's cached boundary (in memory or persisted for the session) while the
|
|
15870
|
+
* covered prefix, durable session summary, and summary model are unchanged
|
|
15871
|
+
* and the whole tail fits; otherwise generates a new summary. Also reports how
|
|
15872
|
+
* many Anthropic thinking blocks the projection removed from carried turns.
|
|
15254
15873
|
*/
|
|
15255
|
-
async summarizeHistory(provider, model, history, availableTokens) {
|
|
15256
|
-
|
|
15257
|
-
|
|
15258
|
-
|
|
15259
|
-
|
|
15260
|
-
|
|
15261
|
-
|
|
15262
|
-
|
|
15263
|
-
|
|
15264
|
-
|
|
15265
|
-
|
|
15266
|
-
|
|
15267
|
-
|
|
15268
|
-
|
|
15269
|
-
|
|
15270
|
-
|
|
15271
|
-
splitIdx2 = i;
|
|
15272
|
-
}
|
|
15273
|
-
splitIdx2 = nextUserTurn(history, splitIdx2) ?? history.length;
|
|
15274
|
-
if (splitIdx2 < history.length) {
|
|
15275
|
-
return [summaryMsg2, ...history.slice(splitIdx2)];
|
|
15874
|
+
async summarizeHistory(agentName, modelUri, provider, model, history, availableTokens) {
|
|
15875
|
+
const summaryModelUri = this.config.contextManagement?.summaryModel ?? modelUri;
|
|
15876
|
+
const cache = await this.loadAskSummary(agentName);
|
|
15877
|
+
if (cache && cache.sourceSummary === this.sessionSummary && cache.summaryModelUri === summaryModelUri && cache.coveredCount <= history.length && cache.prefixHash === summaryPrefixHash(history, cache.coveredCount)) {
|
|
15878
|
+
const summaryMsg = summaryContextMessage(cache.summary);
|
|
15879
|
+
const summaryTokens = estimateTokens(summarizeModelInput(summaryMsg.content)) + 4;
|
|
15880
|
+
const tail2 = history.slice(cache.coveredCount);
|
|
15881
|
+
const tailTokens = estimateMessagesTokens(tail2).tokens;
|
|
15882
|
+
if (summaryTokens + tailTokens <= availableTokens && (tail2.length === 0 || tail2[0].role === "user")) {
|
|
15883
|
+
let removedThinkingBlocks = 0;
|
|
15884
|
+
const projected = tail2.map((message, index) => {
|
|
15885
|
+
if (cache.coveredCount + index >= cache.invalidatedThinkingThrough) return message;
|
|
15886
|
+
removedThinkingBlocks += anthropicThinkingBlockCount(message);
|
|
15887
|
+
return withoutAnthropicThinking(message);
|
|
15888
|
+
});
|
|
15889
|
+
return { messages: [summaryMsg, ...projected], removedThinkingBlocks };
|
|
15276
15890
|
}
|
|
15277
15891
|
}
|
|
15278
15892
|
let recentTokens = 0;
|
|
@@ -15297,42 +15911,103 @@ ${this.summaryCache}`
|
|
|
15297
15911
|
} else {
|
|
15298
15912
|
splitIdx = history.length;
|
|
15299
15913
|
}
|
|
15300
|
-
if (splitIdx === 0)
|
|
15914
|
+
if (splitIdx === 0 && this.sessionSummary) splitIdx = history.length;
|
|
15915
|
+
if (splitIdx === 0) return { messages: history, removedThinkingBlocks: 0 };
|
|
15301
15916
|
const oldMessages = history.slice(0, splitIdx);
|
|
15302
|
-
const
|
|
15917
|
+
const configuredSummaryModelUri = this.config.contextManagement?.summaryModel;
|
|
15303
15918
|
let summaryProvider;
|
|
15304
15919
|
let summaryModel;
|
|
15305
|
-
if (
|
|
15306
|
-
const resolved = this.resolveProviderUri(
|
|
15920
|
+
if (configuredSummaryModelUri) {
|
|
15921
|
+
const resolved = this.resolveProviderUri(configuredSummaryModelUri);
|
|
15307
15922
|
summaryProvider = resolved.provider;
|
|
15308
15923
|
summaryModel = resolved.model;
|
|
15309
15924
|
} else {
|
|
15310
15925
|
summaryProvider = provider;
|
|
15311
15926
|
summaryModel = model;
|
|
15312
15927
|
}
|
|
15313
|
-
const
|
|
15314
|
-
const
|
|
15315
|
-
|
|
15316
|
-
|
|
15317
|
-
|
|
15318
|
-
|
|
15319
|
-
|
|
15320
|
-
|
|
15928
|
+
const summaryPrompt = buildSummaryPrompt(oldMessages, this.sessionSummary);
|
|
15929
|
+
const summaryStart = Date.now();
|
|
15930
|
+
this.emitEvent({
|
|
15931
|
+
type: "agent_call_start",
|
|
15932
|
+
agent: agentName,
|
|
15933
|
+
model: summaryModelUri,
|
|
15934
|
+
turn: 0,
|
|
15935
|
+
data: {
|
|
15936
|
+
purpose: "summary",
|
|
15937
|
+
prompt: summaryPrompt,
|
|
15938
|
+
system: SUMMARY_SYSTEM_PROMPT,
|
|
15939
|
+
params: { maxTokens: SUMMARY_MAX_TOKENS },
|
|
15940
|
+
turn: 0
|
|
15941
|
+
}
|
|
15942
|
+
});
|
|
15943
|
+
let summaryResponse;
|
|
15944
|
+
try {
|
|
15945
|
+
this.currentSignal?.throwIfAborted();
|
|
15946
|
+
summaryResponse = await requestSummary(summaryProvider, {
|
|
15947
|
+
model: summaryModel,
|
|
15948
|
+
prompt: summaryPrompt,
|
|
15949
|
+
signal: this.currentSignal
|
|
15950
|
+
});
|
|
15951
|
+
} catch (error) {
|
|
15952
|
+
const providerError = error instanceof ProviderError ? error : void 0;
|
|
15953
|
+
this.emitEvent({
|
|
15954
|
+
type: "agent_call_end",
|
|
15955
|
+
agent: agentName,
|
|
15956
|
+
model: summaryModelUri,
|
|
15957
|
+
duration: Date.now() - summaryStart,
|
|
15958
|
+
...providerError?.timing ? { timing: providerError.timing } : {},
|
|
15959
|
+
data: {
|
|
15960
|
+
purpose: "summary",
|
|
15961
|
+
response: "",
|
|
15962
|
+
turn: 0,
|
|
15963
|
+
// Provider errors may echo the summarized history, so the event
|
|
15964
|
+
// uses a fixed projection even when trace redaction is disabled.
|
|
15965
|
+
error: "Context-management summary call failed",
|
|
15966
|
+
...providerError ? { status: providerError.status, retryable: providerError.retryable } : {}
|
|
15967
|
+
}
|
|
15968
|
+
});
|
|
15969
|
+
throw error;
|
|
15970
|
+
}
|
|
15971
|
+
if (isUsableCost2(summaryResponse.cost)) this._accumulateBudgetCost(summaryResponse.cost);
|
|
15972
|
+
this.emitEvent({
|
|
15973
|
+
type: "agent_call_end",
|
|
15974
|
+
agent: agentName,
|
|
15975
|
+
model: summaryModelUri,
|
|
15976
|
+
cost: summaryResponse.cost,
|
|
15977
|
+
...!isUsableCost2(summaryResponse.cost) ? { unpriced: true } : {},
|
|
15978
|
+
tokens: summaryResponse.usage ? {
|
|
15979
|
+
input: summaryResponse.usage.prompt_tokens,
|
|
15980
|
+
output: summaryResponse.usage.completion_tokens,
|
|
15981
|
+
reasoning: summaryResponse.usage.reasoning_tokens,
|
|
15982
|
+
cached: summaryResponse.usage.cached_tokens,
|
|
15983
|
+
cacheWrite: summaryResponse.usage.cache_write_tokens
|
|
15984
|
+
} : void 0,
|
|
15985
|
+
duration: Date.now() - summaryStart,
|
|
15986
|
+
...summaryResponse.timing ? { timing: summaryResponse.timing } : {},
|
|
15987
|
+
data: { purpose: "summary", response: summaryResponse.content, turn: 0 }
|
|
15988
|
+
});
|
|
15989
|
+
const prefixHash = summaryPrefixHash(history, splitIdx);
|
|
15990
|
+
if (prefixHash) {
|
|
15991
|
+
await this.saveAskSummary(agentName, {
|
|
15992
|
+
summary: summaryResponse.content,
|
|
15993
|
+
coveredCount: splitIdx,
|
|
15994
|
+
prefixHash,
|
|
15995
|
+
...this.sessionSummary !== void 0 ? { sourceSummary: this.sessionSummary } : {},
|
|
15996
|
+
summaryModelUri,
|
|
15997
|
+
invalidatedThinkingThrough: history.length
|
|
15998
|
+
});
|
|
15999
|
+
}
|
|
16000
|
+
const tail = history.slice(splitIdx);
|
|
16001
|
+
return {
|
|
16002
|
+
messages: [
|
|
16003
|
+
summaryContextMessage(summaryResponse.content),
|
|
16004
|
+
...tail.map(withoutAnthropicThinking)
|
|
15321
16005
|
],
|
|
15322
|
-
|
|
15323
|
-
|
|
15324
|
-
|
|
15325
|
-
|
|
15326
|
-
if (sessionId && this.stateStore) {
|
|
15327
|
-
await this.stateStore.saveSessionMeta(sessionId, "summaryCache", this.summaryCache);
|
|
15328
|
-
}
|
|
15329
|
-
const summaryMsg = {
|
|
15330
|
-
role: "system",
|
|
15331
|
-
origin: "runtime",
|
|
15332
|
-
content: `Summary of earlier conversation:
|
|
15333
|
-
${summaryResponse.content}`
|
|
16006
|
+
removedThinkingBlocks: tail.reduce(
|
|
16007
|
+
(count, message) => count + anthropicThinkingBlockCount(message),
|
|
16008
|
+
0
|
|
16009
|
+
)
|
|
15334
16010
|
};
|
|
15335
|
-
return [summaryMsg, ...history.slice(splitIdx)];
|
|
15336
16011
|
}
|
|
15337
16012
|
// ── ctx.checkpoint() ────────────────────────────────────────────────
|
|
15338
16013
|
/**
|
|
@@ -16590,7 +17265,7 @@ ${summaryResponse.content}`
|
|
|
16590
17265
|
* This operation never enters the chat history or chat-provider path. */
|
|
16591
17266
|
async transcribe(request) {
|
|
16592
17267
|
const startedAt = Date.now();
|
|
16593
|
-
const transcriptionId = (0,
|
|
17268
|
+
const transcriptionId = (0, import_node_crypto2.randomUUID)();
|
|
16594
17269
|
const signal = this.currentSignal;
|
|
16595
17270
|
const rawAudio = request && typeof request === "object" && "audio" in request ? request.audio : void 0;
|
|
16596
17271
|
const source = rawAudio?.type;
|
|
@@ -16979,7 +17654,7 @@ ${summaryResponse.content}`
|
|
|
16979
17654
|
};
|
|
16980
17655
|
|
|
16981
17656
|
// src/agent.ts
|
|
16982
|
-
var
|
|
17657
|
+
var import_node_crypto3 = require("crypto");
|
|
16983
17658
|
var agentCounter = 0;
|
|
16984
17659
|
function agent(config) {
|
|
16985
17660
|
agentCounter++;
|
|
@@ -17000,7 +17675,7 @@ function agent(config) {
|
|
|
17000
17675
|
const transcriptionRegistry = new TranscriptionProviderRegistry();
|
|
17001
17676
|
const ctx = new WorkflowContext({
|
|
17002
17677
|
input: prompt,
|
|
17003
|
-
executionId: (0,
|
|
17678
|
+
executionId: (0, import_node_crypto3.randomUUID)(),
|
|
17004
17679
|
config: {},
|
|
17005
17680
|
providerRegistry: registry2,
|
|
17006
17681
|
transcriptionProviderRegistry: transcriptionRegistry
|
|
@@ -17025,7 +17700,7 @@ function workflow(config) {
|
|
|
17025
17700
|
|
|
17026
17701
|
// src/runtime.ts
|
|
17027
17702
|
var import_node_events2 = require("events");
|
|
17028
|
-
var
|
|
17703
|
+
var import_node_crypto5 = require("crypto");
|
|
17029
17704
|
var import_node_async_hooks4 = require("async_hooks");
|
|
17030
17705
|
var import_node_fs3 = require("fs");
|
|
17031
17706
|
var import_node_path3 = require("path");
|
|
@@ -17741,17 +18416,17 @@ var Session = class _Session {
|
|
|
17741
18416
|
throw new Error("SessionOptions.history.summaryModel is required when summarize is true");
|
|
17742
18417
|
}
|
|
17743
18418
|
const messagesToDrop = history.slice(0, history.length - maxMessages);
|
|
17744
|
-
const
|
|
17745
|
-
|
|
17746
|
-
|
|
17747
|
-
|
|
17748
|
-
|
|
18419
|
+
const summary = await this.runtime.summarizeMessages(
|
|
18420
|
+
messagesToDrop,
|
|
18421
|
+
summaryModel,
|
|
18422
|
+
cachedSummary ? { previousSummary: cachedSummary } : void 0
|
|
18423
|
+
);
|
|
17749
18424
|
await this.store.saveSessionMeta(this.sessionId, "summaryCache", summary);
|
|
17750
18425
|
cachedSummary = summary;
|
|
17751
18426
|
}
|
|
17752
18427
|
const trimmed = history.slice(-maxMessages);
|
|
17753
18428
|
history.length = 0;
|
|
17754
|
-
history.push(...trimmed);
|
|
18429
|
+
history.push(...trimmed.map(withoutAnthropicThinking));
|
|
17755
18430
|
}
|
|
17756
18431
|
const userMessage = { role: "user", content: preparedInput.content };
|
|
17757
18432
|
history.push(userMessage);
|
|
@@ -17761,7 +18436,10 @@ var Session = class _Session {
|
|
|
17761
18436
|
const metadata = {
|
|
17762
18437
|
sessionId: this.sessionId,
|
|
17763
18438
|
sessionHistory: history,
|
|
17764
|
-
...cachedSummary ? { summaryCache: cachedSummary } : {}
|
|
18439
|
+
...cachedSummary ? { summaryCache: cachedSummary } : {},
|
|
18440
|
+
// An opted-out session must leave nothing at rest, including the
|
|
18441
|
+
// agent-scoped ask-summary records the runtime would otherwise cache.
|
|
18442
|
+
...this.options.persist === false ? { sessionPersist: false } : {}
|
|
17765
18443
|
};
|
|
17766
18444
|
return { history, metadata };
|
|
17767
18445
|
}
|
|
@@ -18678,7 +19356,7 @@ function warnMissingMemoryMethodsOnce(stateStore) {
|
|
|
18678
19356
|
var import_node_fs2 = require("fs");
|
|
18679
19357
|
var import_promises = require("fs/promises");
|
|
18680
19358
|
var import_node_readline = require("readline");
|
|
18681
|
-
var
|
|
19359
|
+
var import_node_crypto4 = require("crypto");
|
|
18682
19360
|
var import_node_path2 = __toESM(require("path"), 1);
|
|
18683
19361
|
var MANIFEST_FILE = "manifest.json";
|
|
18684
19362
|
var RECORDS_FILE = "records.jsonl";
|
|
@@ -18743,7 +19421,7 @@ var FileDiagnosticArtifactStore = class {
|
|
|
18743
19421
|
async writeManifest(manifest) {
|
|
18744
19422
|
const dir = this.dir(manifest.artifactId);
|
|
18745
19423
|
await (0, import_promises.mkdir)(dir, { recursive: true });
|
|
18746
|
-
const temp = import_node_path2.default.join(dir, `${MANIFEST_FILE}.${(0,
|
|
19424
|
+
const temp = import_node_path2.default.join(dir, `${MANIFEST_FILE}.${(0, import_node_crypto4.randomUUID)()}.tmp`);
|
|
18747
19425
|
await (0, import_promises.writeFile)(temp, JSON.stringify(manifest), "utf-8");
|
|
18748
19426
|
await (0, import_promises.rename)(temp, import_node_path2.default.join(dir, MANIFEST_FILE));
|
|
18749
19427
|
}
|
|
@@ -18780,7 +19458,7 @@ var FileDiagnosticArtifactStore = class {
|
|
|
18780
19458
|
});
|
|
18781
19459
|
}
|
|
18782
19460
|
async stage(owner, opts) {
|
|
18783
|
-
const artifactId = `art_${(0,
|
|
19461
|
+
const artifactId = `art_${(0, import_node_crypto4.randomUUID)()}`;
|
|
18784
19462
|
const now = Date.now();
|
|
18785
19463
|
await this.writeManifest({
|
|
18786
19464
|
version: 1,
|
|
@@ -19981,7 +20659,7 @@ var AxlRuntime = class extends import_node_events2.EventEmitter {
|
|
|
19981
20659
|
}
|
|
19982
20660
|
try {
|
|
19983
20661
|
await this.saveEvalResult({
|
|
19984
|
-
id: resultObj.id ?? (0,
|
|
20662
|
+
id: resultObj.id ?? (0, import_node_crypto5.randomUUID)(),
|
|
19985
20663
|
eval: name,
|
|
19986
20664
|
timestamp: Date.now(),
|
|
19987
20665
|
data: structuredClone(result)
|
|
@@ -20039,7 +20717,7 @@ var AxlRuntime = class extends import_node_events2.EventEmitter {
|
|
|
20039
20717
|
*/
|
|
20040
20718
|
createContext(options) {
|
|
20041
20719
|
assertNoRemovedObservationCallbacks(options);
|
|
20042
|
-
const executionId = (0,
|
|
20720
|
+
const executionId = (0, import_node_crypto5.randomUUID)();
|
|
20043
20721
|
const budgetLimit = options?.budget ? parseCost(options.budget) : Infinity;
|
|
20044
20722
|
this.registerWithCostScope(executionId);
|
|
20045
20723
|
return new WorkflowContext({
|
|
@@ -20118,7 +20796,7 @@ var AxlRuntime = class extends import_node_events2.EventEmitter {
|
|
|
20118
20796
|
}
|
|
20119
20797
|
const validated = workflow2.inputSchema.parse(input);
|
|
20120
20798
|
const branchDrainTimeoutMs = resolveBranchDrainTimeoutMs(options?.branchDrainTimeoutMs);
|
|
20121
|
-
const executionId = (0,
|
|
20799
|
+
const executionId = (0, import_node_crypto5.randomUUID)();
|
|
20122
20800
|
const controller = new AbortController();
|
|
20123
20801
|
this.abortControllers.set(executionId, controller);
|
|
20124
20802
|
const cleanupAbortForwarder = forwardAbortSignal(options?.signal, controller);
|
|
@@ -20233,7 +20911,7 @@ var AxlRuntime = class extends import_node_events2.EventEmitter {
|
|
|
20233
20911
|
const controller = new AbortController();
|
|
20234
20912
|
axlStream.on("close", () => controller.abort());
|
|
20235
20913
|
const cleanupAbortForwarder = forwardAbortSignal(options?.signal, controller);
|
|
20236
|
-
const executionId = (0,
|
|
20914
|
+
const executionId = (0, import_node_crypto5.randomUUID)();
|
|
20237
20915
|
this.abortControllers.set(executionId, controller);
|
|
20238
20916
|
let execInfo;
|
|
20239
20917
|
let wfCtx;
|
|
@@ -20834,22 +21512,17 @@ var AxlRuntime = class extends import_node_events2.EventEmitter {
|
|
|
20834
21512
|
/**
|
|
20835
21513
|
* Summarize a list of chat messages into a concise summary string.
|
|
20836
21514
|
* Used by Session to summarize dropped messages when history.summarize is enabled.
|
|
21515
|
+
* `previousSummary` is folded in so a rolling summary never loses what it
|
|
21516
|
+
* alone still carries. Shares its prompt and provider call with the
|
|
21517
|
+
* `AgentConfig.maxContext` summarizer (see `compaction.ts`). It runs outside
|
|
21518
|
+
* any workflow execution, so it emits no ask-scoped events.
|
|
20837
21519
|
*/
|
|
20838
|
-
async summarizeMessages(messages, modelUri) {
|
|
21520
|
+
async summarizeMessages(messages, modelUri, options) {
|
|
20839
21521
|
const { provider, model } = this.resolveProvider(modelUri);
|
|
20840
|
-
const response = await provider
|
|
20841
|
-
|
|
20842
|
-
|
|
20843
|
-
|
|
20844
|
-
content: "Summarize the following conversation concisely, preserving key facts, decisions, and context needed for continuing the conversation."
|
|
20845
|
-
},
|
|
20846
|
-
{
|
|
20847
|
-
role: "user",
|
|
20848
|
-
content: messages.map((m) => `${m.role}: ${summarizeModelInput(m.content)}`).join("\n")
|
|
20849
|
-
}
|
|
20850
|
-
],
|
|
20851
|
-
{ model, maxTokens: 1024 }
|
|
20852
|
-
);
|
|
21522
|
+
const response = await requestSummary(provider, {
|
|
21523
|
+
model,
|
|
21524
|
+
prompt: buildSummaryPrompt(messages, options?.previousSummary)
|
|
21525
|
+
});
|
|
20853
21526
|
return response.content;
|
|
20854
21527
|
}
|
|
20855
21528
|
/** Get the state store (for testing and advanced use cases). */
|
|
@@ -22280,6 +22953,7 @@ function cosineSimilarity2(a, b) {
|
|
|
22280
22953
|
TranscriptionProviderRegistry,
|
|
22281
22954
|
UnsupportedEventSchemaVersionError,
|
|
22282
22955
|
UnsupportedModelInputError,
|
|
22956
|
+
UnsupportedModelOptionError,
|
|
22283
22957
|
UnsupportedTranscriptionInputError,
|
|
22284
22958
|
VLLM_PROFILE,
|
|
22285
22959
|
ValidationError,
|